{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://spreadsheets.diyaccounting.co.uk/schema/diya-gl-lines-v2.schema.json",
  "title": "DIY Accounting GL-aligned Transaction Lines (v2)",
  "description": "A single financial transaction record. Field names adapted from XBRL Global Ledger Taxonomy Framework 2015 (gl-cor, gl-bus, gl-muc, gl-taf modules). Reference: http://www.xbrl.org/int/gl/2015-03-25/gl-framework-REC-2015-03-25.html. v2 makes debitCreditCode required on journal lines and adds the fields that link a line to the book's asset, hire purchase and member registers.",
  "type": "object",
  "required": ["postingDate", "amount", "accountMainID", "sourceJournalID"],
  "additionalProperties": false,
  "allOf": [
    {
      "if": {
        "required": ["sourceJournalID"],
        "properties": { "sourceJournalID": { "const": "journal" } }
      },
      "then": { "required": ["debitCreditCode"] }
    }
  ],
  "properties": {
    "entryNumber": {
      "type": "string",
      "description": "gl-cor:entryNumber — Unique transaction identifier within this book"
    },
    "lineNumber": {
      "type": "integer",
      "minimum": 1,
      "description": "gl-cor:lineNumber — Line within a multi-line journal entry (Company Accounts only)"
    },
    "sourceJournalID": {
      "type": "string",
      "enum": ["sales", "purchases", "bank", "journal", "payroll", "petty-cash"],
      "description": "gl-cor:sourceJournalID — Which journal/daybook this belongs to"
    },
    "enteredDate": {
      "type": "string",
      "format": "date",
      "description": "gl-cor:enteredDate — Date keyed (ISO 8601)"
    },
    "enteredBy": {
      "type": "string",
      "description": "gl-cor:enteredBy — User or system that entered the transaction"
    },
    "postingDate": {
      "type": "string",
      "format": "date",
      "description": "gl-cor:postingDate — Tax-relevant date (ISO 8601)"
    },
    "accountMainID": {
      "type": "string",
      "description": "gl-cor:accountMainID — Nominal code from the chart of accounts in book.toml. Must name an account the book declares; enforced by the validator, not this schema."
    },
    "accountMainDescription": {
      "type": "string",
      "description": "gl-cor:accountMainDescription — Human-readable account name"
    },
    "accountSubID": {
      "type": "string",
      "description": "gl-cor:accountSubID — Sub-account or department code"
    },
    "accountSubDescription": {
      "type": "string",
      "description": "gl-cor:accountSubDescription — Sub-account description"
    },
    "debitCreditCode": {
      "type": "string",
      "enum": ["D", "C"],
      "description": "gl-cor:debitCreditCode — D=Debit, C=Credit. Required on journal lines, because a journal line's sign is otherwise ambiguous."
    },
    "amount": {
      "type": "number",
      "minimum": 0,
      "description": "gl-cor:amount — Always positive, penny precision"
    },
    "amountCurrency": {
      "type": "string",
      "pattern": "^[A-Z]{3}$",
      "default": "GBP",
      "description": "gl-muc:amountCurrency — ISO 4217 currency code"
    },
    "documentType": {
      "type": "string",
      "enum": ["invoice", "credit-note", "receipt", "bank-statement", "journal", "payslip", "mileage-log", "other"],
      "description": "gl-cor:documentType — Type of source document"
    },
    "documentReference": {
      "type": "string",
      "description": "gl-cor:documentReference — Invoice/receipt number"
    },
    "documentNumber": {
      "type": "string",
      "description": "gl-cor:documentNumber — Internal document number"
    },
    "documentDate": {
      "type": "string",
      "format": "date",
      "description": "gl-cor:documentDate — Date on source document (ISO 8601)"
    },
    "detailComment": {
      "type": "string",
      "description": "gl-cor:detailComment — Customer/supplier name or narrative"
    },
    "lineItemComment": {
      "type": "string",
      "description": "Adapted from gl-cor:detailComment — Description of goods/services"
    },
    "postingStatus": {
      "type": "string",
      "enum": ["posted", "draft", "voided"],
      "description": "gl-cor:postingStatus — Entry status"
    },
    "taxCode": {
      "type": "string",
      "enum": ["S", "R", "Z", "E", "OS", "RC", "NA"],
      "description": "gl-taf — UK VAT code: S=Standard, R=Reduced, Z=Zero, E=Exempt, OS=Outside Scope, RC=Reverse Charge, NA=Not Applicable"
    },
    "taxAmount": {
      "type": "number",
      "minimum": 0,
      "description": "gl-cor:taxAmount — VAT amount, always positive"
    },
    "taxRate": {
      "type": "number",
      "minimum": 0,
      "maximum": 1,
      "description": "gl-taf:taxRate — VAT rate as decimal (0.20 = 20%)"
    },
    "taxPointDate": {
      "type": "string",
      "format": "date",
      "description": "gl-taf:taxPointDate — VAT tax point if different from postingDate"
    },
    "taxDescription": {
      "type": "string",
      "description": "gl-cor:taxDescription — Human-readable tax description"
    },
    "paymentMethod": {
      "type": "string",
      "enum": ["bank-transfer", "cash", "cheque", "debit-card", "credit-card", "direct-debit", "standing-order", "online-payment", "other"],
      "description": "gl-bus:paymentMethod — How payment was made/received"
    },
    "measurableQuantity": {
      "type": "number",
      "description": "gl-bus:measurableQuantity — Non-monetary quantity (miles, hours, units)"
    },
    "measurableUnitOfMeasure": {
      "type": "string",
      "enum": ["miles", "km", "hours", "units", "litres", "other"],
      "description": "gl-bus:measurableUnitOfMeasure — Unit for measurableQuantity"
    },
    "measurableDescription": {
      "type": "string",
      "description": "gl-bus:measurableQualifier — What is being measured"
    },
    "diya-gl:bankCode": {
      "type": "string",
      "enum": ["BB", "BS", "BC", "BD", "DR", "CR", "K", "LDR", "LCR", "RV", "RC", "RT", "RP", "W", "B", "J", "DV", "DL", "X"],
      "description": "diya-gl: extension — Bank receipt/payment code, matching the analysis columns of the bank account workbooks. Transfers between accounts carry the letter of the account on the other side: BB=current, BS=savings, BC=cash, BD=credit card. Receipt only: K=interest received. Payment only: W=net wages, B=bank charges, J=interest paid, DV=dividend, RP=HMRC PAYE, RT=HMRC corporation tax. Either side: DR=trade debtor, CR=trade creditor, LDR=long term debtor, LCR=long term creditor, RV=HMRC VAT, RC=HMRC CIS, DL=directors loan, X=bank contra item. BC on a bank line with no other account on the other side is the workbook's own opening balance."
    },
    "diya-gl:bankAccountID": {
      "type": "string",
      "description": "diya-gl: extension — Bank account code from book.toml accounts.bank (e.g. 1200=current, 1210=savings). Identifies which bank workbook this transaction belongs to."
    },
    "diya-gl:employeeID": {
      "type": "string",
      "description": "diya-gl: extension — Employee identifier matching employees[] in book.toml. Used for payroll lines (sourceJournalID=payroll)."
    },
    "diya-gl:grossPay": {
      "type": "number",
      "minimum": 0,
      "description": "diya-gl: extension — Gross pay for this payroll period. Payroll lines only."
    },
    "diya-gl:incomeTax": {
      "type": "number",
      "minimum": 0,
      "description": "diya-gl: extension — PAYE income tax deducted. Payroll lines only."
    },
    "diya-gl:employeeNI": {
      "type": "number",
      "minimum": 0,
      "description": "diya-gl: extension — Employee National Insurance deducted. Payroll lines only."
    },
    "diya-gl:employerNI": {
      "type": "number",
      "minimum": 0,
      "description": "diya-gl: extension — Employer National Insurance contribution. Payroll lines only."
    },
    "diya-gl:netPay": {
      "type": "number",
      "minimum": 0,
      "description": "diya-gl: extension — Net pay (gross - tax - employee NI). Payroll lines only."
    },
    "diya-gl:cisDeduction": {
      "type": "number",
      "minimum": 0,
      "description": "diya-gl: extension — CIS deduction amount withheld from sub-contractor payment. Purchases lines with CIS sub-contractors only."
    },
    "diya-gl:hpAgreement": {
      "type": "string",
      "description": "diya-gl: extension — Reference of the hire purchase agreement that finances this purchase, matching an id on book.toml hpAgreements[]. A purchase carrying one reaches the books as an ordinary trade creditor; the year-end journal then moves the amount financed onto creditors falling due after more than one year."
    },
    "diya-gl:cisRate": {
      "type": "number",
      "minimum": 0,
      "maximum": 1,
      "description": "diya-gl: extension — CIS deduction rate (0.20=20% standard, 0.30=30% higher, 0=gross payment). CIS lines only."
    },
    "diya-gl:vatPeriodEnd": {
      "type": "string",
      "format": "date",
      "description": "diya-gl: extension — The VAT return period this line is declared on, when that period falls outside the accounting year the book covers. This is what makes a straddling entry representable: the line's postingDate sits in one accounting year, but its VAT is due on the return ending vatPeriodEnd."
    },
    "diya-gl:assetID": {
      "type": "string",
      "description": "diya-gl: extension — The book.toml fixedAssets[] id this line moves: a capital purchase that registers the asset, or a disposal (an 'fs'-coded sale) that removes it."
    },
    "diya-gl:memberID": {
      "type": "string",
      "description": "diya-gl: extension — The book.toml members[] id a dividend payment line settles."
    }
  }
}
