@diy-accounting-uk/diya-gl 1.2.80 → 1.2.82

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.
@@ -2313,6 +2313,58 @@
2313
2313
  "scorecard": "101608 passed, 0 warnings, 0 failed"
2314
2314
  }
2315
2315
  }
2316
+ },
2317
+ {
2318
+ "tag": "diya-gl-v1.2.80",
2319
+ "date": "2026-11-12",
2320
+ "formatVersion": "diya-gl/2",
2321
+ "engineVersion": "1.2.80+279af012c",
2322
+ "taxDataHash": "76cb698e3ca8",
2323
+ "reconciledCommit": "54e8731a91279975e61b1a232fbb67fda89515f0",
2324
+ "templates": {
2325
+ "bst": {
2326
+ "hash": "0d003e10e00c",
2327
+ "scorecard": "812 passed, 0 warnings, 0 failed"
2328
+ },
2329
+ "taxi": {
2330
+ "hash": "1ff69654d64d",
2331
+ "scorecard": "700 passed, 0 warnings, 0 failed"
2332
+ },
2333
+ "se": {
2334
+ "hash": "064605ae76ed",
2335
+ "scorecard": "8015 passed, 0 warnings, 0 failed"
2336
+ },
2337
+ "ltd": {
2338
+ "hash": "b90d8b0f54a0",
2339
+ "scorecard": "101608 passed, 0 warnings, 0 failed"
2340
+ }
2341
+ }
2342
+ },
2343
+ {
2344
+ "tag": "diya-gl-v1.2.81",
2345
+ "date": "2026-11-13",
2346
+ "formatVersion": "diya-gl/2",
2347
+ "engineVersion": "1.2.81+279af012c",
2348
+ "taxDataHash": "76cb698e3ca8",
2349
+ "reconciledCommit": "54e8731a91279975e61b1a232fbb67fda89515f0",
2350
+ "templates": {
2351
+ "bst": {
2352
+ "hash": "0d003e10e00c",
2353
+ "scorecard": "812 passed, 0 warnings, 0 failed"
2354
+ },
2355
+ "taxi": {
2356
+ "hash": "1ff69654d64d",
2357
+ "scorecard": "700 passed, 0 warnings, 0 failed"
2358
+ },
2359
+ "se": {
2360
+ "hash": "064605ae76ed",
2361
+ "scorecard": "8015 passed, 0 warnings, 0 failed"
2362
+ },
2363
+ "ltd": {
2364
+ "hash": "b90d8b0f54a0",
2365
+ "scorecard": "101608 passed, 0 warnings, 0 failed"
2366
+ }
2367
+ }
2316
2368
  }
2317
2369
  ]
2318
2370
  }
@@ -818,18 +818,41 @@ export function extractTaxDataFromBook(book, product) {
818
818
  const mi = tax.mileage || {};
819
819
  const ct = tax.corporationTax || {};
820
820
 
821
+ // A figure the book does not state is the figure of the book's own tax
822
+ // year; a year file that lacks it too refuses the book.
823
+ const taxYearFile = taxYearFileForBook(book, product === "ltd" ? "ltd" : "se");
824
+ const selfEmploymentYearFile = product === "ltd" ? taxYearFileForBook(book, "se") : taxYearFile;
825
+ const taxYearLabel = (taxYearFile.tax_year ?? taxYearFile.financial_year)?.label;
826
+ const stated = (bookValue, yearFile, section, key, bookField) => {
827
+ if (bookValue !== undefined && bookValue !== null) return bookValue;
828
+ const yearValue = yearFile[section]?.[key];
829
+ if (yearValue === undefined) {
830
+ throw new Error(`book.toml states no ${bookField} and the tax-year file for ${taxYearLabel} has no [${section}] ${key}`);
831
+ }
832
+ return yearValue;
833
+ };
834
+ const income = (bookValue, key, bookField) => stated(bookValue, selfEmploymentYearFile, "income_tax", key, `tax.incomeTax.${bookField}`);
835
+ const class4 = (bookValue, key, bookField) =>
836
+ stated(bookValue, selfEmploymentYearFile, "national_insurance", key, `tax.nationalInsurance.${bookField}`);
837
+ const regimeStated = (bookValue, section, key, bookField) => stated(bookValue, taxYearFile, section, key, bookField);
838
+ const basicRateLimit = income(it.basicRateLimit, "basic_band_end", "basicRateLimit");
839
+
821
840
  const baseTaxData = {
822
841
  income_tax: {
823
- personal_allowance: it.personalAllowance || 12570,
842
+ personal_allowance: income(it.personalAllowance, "personal_allowance", "personalAllowance"),
824
843
  starting_rate: 0,
825
- basic_rate: it.basicRate || 0.2,
826
- higher_rate: it.higherRate || 0.4,
844
+ basic_rate: income(it.basicRate, "basic_rate", "basicRate"),
845
+ higher_rate: income(it.higherRate, "higher_rate", "higherRate"),
827
846
  starter_band_end: 0,
828
- basic_band_end: it.basicRateLimit || 37700,
829
- higher_band_start: (it.basicRateLimit || 37700) + 1,
830
- higher_band_end: it.higherRateLimit || 125140,
831
- additional_rate: it.additionalRate || 0.45,
832
- personal_allowance_taper_threshold: it.personalAllowanceTaperThreshold || 100000,
847
+ basic_band_end: basicRateLimit,
848
+ higher_band_start: basicRateLimit + 1,
849
+ higher_band_end: income(it.higherRateLimit, "higher_band_end", "higherRateLimit"),
850
+ additional_rate: income(it.additionalRate, "additional_rate", "additionalRate"),
851
+ personal_allowance_taper_threshold: income(
852
+ it.personalAllowanceTaperThreshold,
853
+ "personal_allowance_taper_threshold",
854
+ "personalAllowanceTaperThreshold",
855
+ ),
833
856
  },
834
857
  national_insurance: {
835
858
  // Class 2 and Class 4 are the self-employed rates; a book with no
@@ -839,53 +862,78 @@ export function extractTaxDataFromBook(book, product) {
839
862
  class2_rate: ni.class2WeeklyRate,
840
863
  class2_weekly_rate: ni.class2WeeklyRate,
841
864
  class2_small_profits_threshold: ni.class2SmallProfitsThreshold,
842
- class4_lower_rate: ni.class4MainRate ?? 0.06,
843
- class4_lower_limit: ni.class4LowerProfits ?? 12570,
844
- class4_upper_rate: ni.class4UpperRate ?? 0.02,
845
- class4_upper_limit: ni.class4UpperProfits ?? 50270,
865
+ class4_lower_rate: class4(ni.class4MainRate, "class4_lower_rate", "class4MainRate"),
866
+ class4_lower_limit: class4(ni.class4LowerProfits, "class4_lower_limit", "class4LowerProfits"),
867
+ class4_upper_rate: class4(ni.class4UpperRate, "class4_upper_rate", "class4UpperRate"),
868
+ class4_upper_limit: class4(ni.class4UpperProfits, "class4_upper_limit", "class4UpperProfits"),
846
869
  },
847
870
  mileage: {
848
- higher_rate_limit: 10000,
849
- higher_rate_pence: mi.carFirst10000 || 0.45,
850
- lower_rate_start: 10001,
851
- lower_rate_pence: mi.carOver10000 || 0.25,
871
+ higher_rate_limit: regimeStated(undefined, "mileage", "higher_rate_limit", "mileage.higher_rate_limit"),
872
+ higher_rate_pence: regimeStated(mi.carFirst10000, "mileage", "higher_rate_pence", "tax.mileage.carFirst10000"),
873
+ lower_rate_start: regimeStated(undefined, "mileage", "lower_rate_start", "mileage.lower_rate_start"),
874
+ lower_rate_pence: regimeStated(mi.carOver10000, "mileage", "lower_rate_pence", "tax.mileage.carOver10000"),
852
875
  },
853
876
  vat: {
854
- registration_threshold: 90000,
855
- standard_rate: 0.2,
877
+ registration_threshold: regimeStated(undefined, "vat", "registration_threshold", "vat.registration_threshold"),
878
+ standard_rate: regimeStated(undefined, "vat", "standard_rate", "vat.standard_rate"),
856
879
  },
857
880
  };
858
881
 
882
+ const annualInvestmentAllowance = regimeStated(
883
+ ca.annualInvestmentAllowance ? ca.annualInvestmentAllowance / 1000000 : undefined,
884
+ "capital_allowances",
885
+ "annual_investment_allowance",
886
+ "tax.capitalAllowances.annualInvestmentAllowance",
887
+ );
888
+ const capitalAllowance = (bookValue, key, bookField) =>
889
+ regimeStated(bookValue, "capital_allowances", key, `tax.capitalAllowances.${bookField}`);
890
+
859
891
  // Capital allowances differ by regime: Ltd has main/special rates and full expensing;
860
892
  // SE (and other regimes) use a single writing_down_allowance rate.
861
893
  if (product === "ltd") {
862
894
  baseTaxData.capital_allowances = {
863
- annual_investment_allowance: ca.annualInvestmentAllowance ? ca.annualInvestmentAllowance / 1000000 : 1.0,
864
- writing_down_allowance_main: ca.mainRateWDA || 0.18,
865
- writing_down_allowance_special: ca.specialRateWDA || 0.06,
895
+ annual_investment_allowance: annualInvestmentAllowance,
896
+ writing_down_allowance_main: capitalAllowance(ca.mainRateWDA, "writing_down_allowance_main", "mainRateWDA"),
897
+ writing_down_allowance_special: capitalAllowance(ca.specialRateWDA, "writing_down_allowance_special", "specialRateWDA"),
866
898
  full_expensing_rate: 0, // Defaults to 0; varies by tax year but not available from book.toml
867
899
  };
868
900
  baseTaxData.corporation_tax = {
869
- main_rate: ct.mainRate || 0.25,
870
- small_profits_rate: ct.smallProfitsRate || 0.19,
871
- small_profits_limit: ct.smallProfitsLimit || 50000,
872
- main_rate_limit: ct.mainRateThreshold || 250000,
901
+ main_rate: regimeStated(ct.mainRate, "corporation_tax", "main_rate", "tax.corporationTax.mainRate"),
902
+ small_profits_rate: regimeStated(ct.smallProfitsRate, "corporation_tax", "small_profits_rate", "tax.corporationTax.smallProfitsRate"),
903
+ small_profits_limit: regimeStated(
904
+ ct.smallProfitsLimit,
905
+ "corporation_tax",
906
+ "small_profits_limit",
907
+ "tax.corporationTax.smallProfitsLimit",
908
+ ),
909
+ main_rate_limit: regimeStated(ct.mainRateThreshold, "corporation_tax", "main_rate_limit", "tax.corporationTax.mainRateThreshold"),
873
910
  marginal_relief_fraction: 0.015, // Not available from book.toml; use standard value
874
911
  };
875
912
  } else {
876
913
  // SE/BST/Taxi use a single writing_down_allowance key; the Self Employed
877
914
  // schedule also keeps a special rate pool.
878
915
  baseTaxData.capital_allowances = {
879
- annual_investment_allowance: ca.annualInvestmentAllowance ? ca.annualInvestmentAllowance / 1000000 : 1.0,
880
- writing_down_allowance: ca.mainRateWDA || 0.18,
916
+ annual_investment_allowance: annualInvestmentAllowance,
917
+ writing_down_allowance: capitalAllowance(ca.mainRateWDA, "writing_down_allowance", "mainRateWDA"),
881
918
  };
882
919
  if (product === "se") {
883
- baseTaxData.capital_allowances.writing_down_allowance_special = ca.specialRateWDA || 0.06;
884
- baseTaxData.capital_allowances.structures_and_buildings_allowance = ca.structuresAndBuildingsAllowance || 0.03;
885
- baseTaxData.capital_allowances.structures_and_buildings_allowance_enhanced = ca.structuresAndBuildingsAllowanceEnhanced || 0.1;
920
+ baseTaxData.capital_allowances.writing_down_allowance_special = capitalAllowance(
921
+ ca.specialRateWDA,
922
+ "writing_down_allowance_special",
923
+ "specialRateWDA",
924
+ );
925
+ baseTaxData.capital_allowances.structures_and_buildings_allowance = capitalAllowance(
926
+ ca.structuresAndBuildingsAllowance,
927
+ "structures_and_buildings_allowance",
928
+ "structuresAndBuildingsAllowance",
929
+ );
930
+ baseTaxData.capital_allowances.structures_and_buildings_allowance_enhanced = capitalAllowance(
931
+ ca.structuresAndBuildingsAllowanceEnhanced,
932
+ "structures_and_buildings_allowance_enhanced",
933
+ "structuresAndBuildingsAllowanceEnhanced",
934
+ );
886
935
  }
887
936
  }
888
- const taxYearFile = taxYearFileForBook(book, product === "ltd" ? "ltd" : "se");
889
937
  baseTaxData.depreciation = taxYearFile.depreciation;
890
938
  if (product === "ltd") {
891
939
  baseTaxData.corporation_tax_previous_financial_year = taxYearFile.corporation_tax_previous_financial_year;
@@ -12,7 +12,7 @@
12
12
 
13
13
  export const PROVENANCE_DATA = {
14
14
  formatVersion: "diya-gl/2",
15
- engineVersion: "1.2.80+279af012c",
15
+ engineVersion: "1.2.82+f64a4eb29",
16
16
  taxDataHash: "76cb698e3ca8",
17
17
  reconciledCommit: "54e8731a91279975e61b1a232fbb67fda89515f0",
18
18
  templates: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@diy-accounting-uk/diya-gl",
3
- "version": "1.2.80",
3
+ "version": "1.2.82",
4
4
  "type": "module",
5
5
  "description": "Recalculate, read and write DIYA-GL books from the command line",
6
6
  "license": "Apache-2.0",