@diy-accounting-uk/diya-gl 1.2.56 → 1.2.58

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -96,8 +96,9 @@ Each subcommand is also its own command, if you only want one on your `PATH`:
96
96
 
97
97
  ## API
98
98
 
99
- The package root exports three functions that turn a book into the figures HMRC's MTD APIs
100
- take. Each takes the parsed book, its lines and a parameters object, and returns a promise.
99
+ The package root exports five functions that turn a book into the figures HMRC's MTD APIs
100
+ take. Each takes the parsed book, its lines and a parameters object. The VAT and self-employment
101
+ functions return a promise; the two UK property functions return their answer directly.
101
102
  Nothing is sent anywhere: the answer is the request body to send, plus what fed it.
102
103
 
103
104
  Load a book first:
@@ -166,6 +167,36 @@ const answer = await deriveItsaAnnualSubmission(book, lines, { taxYear: "2025-26
166
167
  console.log(answer.allowances.annualInvestmentAllowance);
167
168
  ```
168
169
 
170
+ ### `deriveUkPropertyPeriod(book, lines, { periodStartDate, periodEndDate })`
171
+
172
+ One period of HMRC's Property Business API (UK property) from a sole trader book. The book's
173
+ chart names the HMRC field each account feeds with `diya-gl:ukPropertyField` on the account
174
+ (for example `"income.periodAmount"` on the rent account, `"expenses.repairsAndMaintenance"` on
175
+ the repairs account). The function sums the sales and purchases postings on those accounts
176
+ between the two dates inclusive, net of VAT, with a credit note taking from its field. The
177
+ answer carries `income`, `expenses`, `omitted` (the fields no posting fed; they are left out of
178
+ the body, never sent as zero), `lines` and `warnings`. A book that names
179
+ `expenses.consolidatedExpenses` and an itemised expense in the same period is refused, because
180
+ HMRC takes one or the other.
181
+
182
+ ```js
183
+ import { deriveUkPropertyPeriod } from "@diy-accounting-uk/diya-gl";
184
+
185
+ const { book, lines } = loadBook("my-landlord-book");
186
+ const answer = deriveUkPropertyPeriod(book, lines, { periodStartDate: "2025-04-06", periodEndDate: "2025-07-05" });
187
+ console.log(answer.income.periodAmount, answer.expenses.repairsAndMaintenance);
188
+ ```
189
+
190
+ ### `deriveUkPropertyAnnual(book, lines, { taxYear? })`
191
+
192
+ The year's adjustments (`balancingCharge`, `privateUseAdjustment`,
193
+ `businessPremisesRenovationAllowanceBalancingCharges`) and allowances (`annualInvestmentAllowance`,
194
+ `businessPremisesRenovationAllowance`, `otherCapitalAllowance`, `costOfReplacingDomesticItems`,
195
+ `zeroEmissionsCarAllowance`) from the postings on the accounts the chart names, for the tax year
196
+ `taxYear` (as `2025-26`; the default is the year the book's period end falls in). The property
197
+ income allowance, `nonResidentLandlord` and `rentARoom.jointlyLet` are choices and facts about the
198
+ landlord, not ledger figures; the answer lists them under `leftToPage`.
199
+
169
200
  ## The format
170
201
 
171
202
  A diya-gl book's fields are drawn from the XBRL Global Ledger Taxonomy Framework 2015 and
@@ -60,6 +60,7 @@ import {
60
60
  PackagePartError,
61
61
  ProductNotAvailableError,
62
62
  } from "../lib/diya-gl-interchange.js";
63
+ import { frcSuiteConcepts } from "../lib/frc-suite-concepts-node.js";
63
64
  import { PRODUCTS } from "../lib/products.js";
64
65
 
65
66
  // A book read through --file whose sniffed product disagrees with the
@@ -216,7 +217,12 @@ async function writeBookChecksJson(outputDir, book, lines) {
216
217
  export async function extractBookFromFile(filePath, { product } = {}) {
217
218
  const resolvedFile = resolve(filePath);
218
219
  const bytes = readFileSync(resolvedFile);
219
- const { product: sniffedProduct, book, lines, overtyped } = await readBookSource(bytes, basename(resolvedFile), { products: PRODUCTS });
220
+ const {
221
+ product: sniffedProduct,
222
+ book,
223
+ lines,
224
+ overtyped,
225
+ } = await readBookSource(bytes, basename(resolvedFile), { products: PRODUCTS, suiteConcepts: frcSuiteConcepts });
220
226
  if (product && product !== sniffedProduct) {
221
227
  throw new PackageMismatchError(product, PRODUCTS[sniffedProduct].PRODUCT.name);
222
228
  }
@@ -19,6 +19,7 @@ import { join, resolve } from "path";
19
19
  import { fileURLToPath } from "url";
20
20
  import { parseDiyaGlData } from "../lib/diya-gl-loader.js";
21
21
  import { readBookSource } from "../lib/diya-gl-interchange.js";
22
+ import { frcSuiteConcepts } from "../lib/frc-suite-concepts-node.js";
22
23
  import { canonicalBookToml, canonicalLinesJsonl } from "../lib/diya-gl-canonical.js";
23
24
  import { productIdOf } from "../lib/xlsx-exporter.js";
24
25
  import { PRODUCTS } from "../lib/products.js";
@@ -51,7 +52,7 @@ async function readBookText(source) {
51
52
  const lines = readFileSync(join(path, "lines.jsonl"), "utf8");
52
53
  return { toml, lines, book: parseDiyaGlData(toml, lines).book };
53
54
  }
54
- const { book, lines } = await readBookSource(readFileSync(path), source, { products: PRODUCTS });
55
+ const { book, lines } = await readBookSource(readFileSync(path), source, { products: PRODUCTS, suiteConcepts: frcSuiteConcepts });
55
56
  return { toml: canonicalBookToml(book), lines: canonicalLinesJsonl(lines), book };
56
57
  }
57
58
 
@@ -22,6 +22,7 @@ import { join, resolve } from "path";
22
22
  import { fileURLToPath } from "url";
23
23
  import { parseDiyaGlData } from "../lib/diya-gl-loader.js";
24
24
  import { readBookSource } from "../lib/diya-gl-interchange.js";
25
+ import { frcSuiteConcepts } from "../lib/frc-suite-concepts-node.js";
25
26
  import { PRODUCTS } from "../lib/products.js";
26
27
  import { TOOLS, createSession } from "../lib/mcp/diya-gl-tools.js";
27
28
  import { writeBookDirectory } from "./export.js";
@@ -52,7 +53,7 @@ async function readBook(source) {
52
53
  if (statSync(path).isDirectory()) {
53
54
  return parseDiyaGlData(readFileSync(join(path, "book.toml"), "utf8"), readFileSync(join(path, "lines.jsonl"), "utf8"));
54
55
  }
55
- const { book, lines } = await readBookSource(readFileSync(path), source, { products: PRODUCTS });
56
+ const { book, lines } = await readBookSource(readFileSync(path), source, { products: PRODUCTS, suiteConcepts: frcSuiteConcepts });
56
57
  return { book, lines };
57
58
  }
58
59
 
@@ -18,6 +18,7 @@ import { readFileSync, writeFileSync, mkdirSync } from "fs";
18
18
  import { resolve } from "path";
19
19
  import { loadDiyaGlData } from "../lib/diya-gl-loader.js";
20
20
  import { readBookSource } from "../lib/diya-gl-interchange.js";
21
+ import { frcSuiteConcepts } from "../lib/frc-suite-concepts-node.js";
21
22
  import { saveWorkbook, saveWorkbookFiles, savePackageZip, productOf } from "../lib/product-workbook.js";
22
23
  import { productModule, PRODUCTS } from "../lib/products.js";
23
24
 
@@ -59,7 +60,7 @@ async function loadBookAndLines(dataDir, file, offset) {
59
60
  return loadDiyaGlData(resolve(dataDir), offset);
60
61
  }
61
62
  const bytes = readFileSync(resolve(file));
62
- const { book, lines } = await readBookSource(bytes, file, { products: PRODUCTS });
63
+ const { book, lines } = await readBookSource(bytes, file, { products: PRODUCTS, suiteConcepts: frcSuiteConcepts });
63
64
  return { book, lines };
64
65
  }
65
66