@diy-accounting-uk/diya-gl 1.2.15 → 1.2.17
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/dist/app/data/hmrc/form-layouts/se.json +8 -4
- package/dist/app/data/hmrc/sa103-mtd-mapping.json +4 -4
- package/dist/app/data/releases.json +52 -0
- package/dist/app/data/render-unrepresentable/se.json +17 -1
- package/dist/app/data/se-2020-2021.toml +2 -0
- package/dist/app/data/se-2021-2022.toml +2 -0
- package/dist/app/data/se-2022-2023.toml +2 -0
- package/dist/app/data/se-2023-2024.toml +2 -0
- package/dist/app/data/se-2024-2025.toml +2 -0
- package/dist/app/data/se-2025-2026.toml +2 -0
- package/dist/app/data/se-2026-2027.toml +2 -0
- package/dist/app/lib/anchors/se.js +9 -1
- package/dist/app/lib/calculators/se-derivations.js +44 -6
- package/dist/app/lib/calculators/se.js +86 -6
- package/dist/app/lib/diya-gl-canonical.js +28 -6
- package/dist/app/lib/diya-gl-loader.js +17 -2
- package/dist/app/lib/generator.js +5 -1
- package/dist/app/lib/provenance-data.js +4 -4
- package/dist/app/lib/scenario-extractor.js +20 -0
- package/dist/app/lib/xlsx-exporter.js +35 -3
- package/dist/app/products/se.js +221 -32
- package/dist/web/spreadsheets.diyaccounting.co.uk/public/schema/diya-gl-book-v2.schema.json +55 -3
- package/package.json +1 -1
|
@@ -251,10 +251,14 @@
|
|
|
251
251
|
"label": "Capital allowances at 6% on equipment, including cars with higher CO2 emissions",
|
|
252
252
|
"cell": "Financialaccounts.xlsx!SE Full!D147"
|
|
253
253
|
},
|
|
254
|
-
{ "box": "52", "label": "Zero-emission goods vehicle allowance", "cell": "Financialaccounts.xlsx!SE Full!
|
|
255
|
-
{ "box": "52.1", "label": "Zero-emission car allowance", "cell": "Financialaccounts.xlsx!SE Full!
|
|
256
|
-
{ "box": "53", "label": "The Structures and Buildings Allowance", "cell": "Financialaccounts.xlsx!SE Full!
|
|
257
|
-
{
|
|
254
|
+
{ "box": "52", "label": "Zero-emission goods vehicle allowance", "cell": "Financialaccounts.xlsx!SE Full!D150" },
|
|
255
|
+
{ "box": "52.1", "label": "Zero-emission car allowance", "cell": "Financialaccounts.xlsx!SE Full!D152" },
|
|
256
|
+
{ "box": "53", "label": "The Structures and Buildings Allowance", "cell": "Financialaccounts.xlsx!SE Full!D156" },
|
|
257
|
+
{
|
|
258
|
+
"box": "53.1",
|
|
259
|
+
"label": "Freeport and Investment Zones Structures and Buildings Allowance",
|
|
260
|
+
"cell": "Financialaccounts.xlsx!SE Full!D160"
|
|
261
|
+
},
|
|
258
262
|
{ "box": "54", "label": "Electric charge-point allowance", "cell": "Financialaccounts.xlsx!SE Full!O139" },
|
|
259
263
|
{ "box": "55", "label": "100% and other enhanced capital allowances", "cell": "Financialaccounts.xlsx!SE Full!O144" },
|
|
260
264
|
{ "box": "56", "label": "Allowances on sale or cessation of business use", "cell": "Financialaccounts.xlsx!SE Full!O149" },
|
|
@@ -452,7 +452,7 @@
|
|
|
452
452
|
"form": "SA103F",
|
|
453
453
|
"box": "52",
|
|
454
454
|
"label": "Zero-emission goods vehicle allowance",
|
|
455
|
-
"cell": "SE Full!
|
|
455
|
+
"cell": "SE Full!D150",
|
|
456
456
|
"field": "allowances.zeroEmissionsGoodsVehicleAllowance",
|
|
457
457
|
"route": "annual"
|
|
458
458
|
},
|
|
@@ -460,7 +460,7 @@
|
|
|
460
460
|
"form": "SA103F",
|
|
461
461
|
"box": "52.1",
|
|
462
462
|
"label": "Zero-emission car allowance",
|
|
463
|
-
"cell": "SE Full!
|
|
463
|
+
"cell": "SE Full!D152",
|
|
464
464
|
"field": "allowances.zeroEmissionsCarAllowance",
|
|
465
465
|
"route": "annual"
|
|
466
466
|
},
|
|
@@ -468,7 +468,7 @@
|
|
|
468
468
|
"form": "SA103F",
|
|
469
469
|
"box": "53",
|
|
470
470
|
"label": "The Structures and Buildings Allowance",
|
|
471
|
-
"cell": "SE Full!
|
|
471
|
+
"cell": "SE Full!D156",
|
|
472
472
|
"field": "allowances.structuredBuildingAllowance",
|
|
473
473
|
"route": "annual"
|
|
474
474
|
},
|
|
@@ -476,7 +476,7 @@
|
|
|
476
476
|
"form": "SA103F",
|
|
477
477
|
"box": "53.1",
|
|
478
478
|
"label": "Freeport Structures and Buildings Allowance",
|
|
479
|
-
"cell":
|
|
479
|
+
"cell": "SE Full!D160",
|
|
480
480
|
"field": "allowances.enhancedStructuredBuildingAllowance",
|
|
481
481
|
"route": "annual"
|
|
482
482
|
},
|
|
@@ -623,6 +623,58 @@
|
|
|
623
623
|
"scorecard": "101605 passed, 0 warnings, 0 failed"
|
|
624
624
|
}
|
|
625
625
|
}
|
|
626
|
+
},
|
|
627
|
+
{
|
|
628
|
+
"tag": "diya-gl-v1.2.15",
|
|
629
|
+
"date": "2026-09-15",
|
|
630
|
+
"formatVersion": "diya-gl/1",
|
|
631
|
+
"engineVersion": "1.2.15+27b706de",
|
|
632
|
+
"taxDataHash": "4ecdbe985d22",
|
|
633
|
+
"reconciledCommit": "54e8731a91279975e61b1a232fbb67fda89515f0",
|
|
634
|
+
"templates": {
|
|
635
|
+
"bst": {
|
|
636
|
+
"hash": "0d003e10e00c",
|
|
637
|
+
"scorecard": "812 passed, 0 warnings, 0 failed"
|
|
638
|
+
},
|
|
639
|
+
"taxi": {
|
|
640
|
+
"hash": "1ff69654d64d",
|
|
641
|
+
"scorecard": "686 passed, 0 warnings, 0 failed"
|
|
642
|
+
},
|
|
643
|
+
"se": {
|
|
644
|
+
"hash": "3c88a8ba129b",
|
|
645
|
+
"scorecard": "7966 passed, 0 warnings, 0 failed"
|
|
646
|
+
},
|
|
647
|
+
"ltd": {
|
|
648
|
+
"hash": "caa14632083b",
|
|
649
|
+
"scorecard": "101605 passed, 0 warnings, 0 failed"
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
},
|
|
653
|
+
{
|
|
654
|
+
"tag": "diya-gl-v1.2.16",
|
|
655
|
+
"date": "2026-09-15",
|
|
656
|
+
"formatVersion": "diya-gl/1",
|
|
657
|
+
"engineVersion": "1.2.16+25abe637",
|
|
658
|
+
"taxDataHash": "3221a7c2f39c",
|
|
659
|
+
"reconciledCommit": "54e8731a91279975e61b1a232fbb67fda89515f0",
|
|
660
|
+
"templates": {
|
|
661
|
+
"bst": {
|
|
662
|
+
"hash": "0d003e10e00c",
|
|
663
|
+
"scorecard": "812 passed, 0 warnings, 0 failed"
|
|
664
|
+
},
|
|
665
|
+
"taxi": {
|
|
666
|
+
"hash": "1ff69654d64d",
|
|
667
|
+
"scorecard": "686 passed, 0 warnings, 0 failed"
|
|
668
|
+
},
|
|
669
|
+
"se": {
|
|
670
|
+
"hash": "107ff1b5c94a",
|
|
671
|
+
"scorecard": "7969 passed, 0 warnings, 0 failed"
|
|
672
|
+
},
|
|
673
|
+
"ltd": {
|
|
674
|
+
"hash": "caa14632083b",
|
|
675
|
+
"scorecard": "101605 passed, 0 warnings, 0 failed"
|
|
676
|
+
}
|
|
677
|
+
}
|
|
626
678
|
}
|
|
627
679
|
]
|
|
628
680
|
}
|
|
@@ -339,6 +339,7 @@
|
|
|
339
339
|
"section/accounting-profit-to-tax-profit-bridge/less-small-balance-allowance-box-24": "The page has no profit-bridge view; the bridge from accounting profit to tax profit is not printed anywhere on the books page.",
|
|
340
340
|
"section/accounting-profit-to-tax-profit-bridge/less-the-full-return-s-own-box-62-adjustment": "The page has no profit-bridge view; the bridge from accounting profit to tax profit is not printed anywhere on the books page.",
|
|
341
341
|
"section/accounting-profit-to-tax-profit-bridge/less-the-full-return-s-own-electric-charge-point-allowance-box-54": "The page has no profit-bridge view; the bridge from accounting profit to tax profit is not printed anywhere on the books page.",
|
|
342
|
+
"section/accounting-profit-to-tax-profit-bridge/less-the-full-return-s-own-freeport-and-investment-zone-structures-and-buildings-allowance-box-53-1": "The page has no profit-bridge view; the bridge from accounting profit to tax profit is not printed anywhere on the books page.",
|
|
342
343
|
"section/accounting-profit-to-tax-profit-bridge/less-the-full-return-s-own-structures-and-buildings-allowance-box-53": "The page has no profit-bridge view; the bridge from accounting profit to tax profit is not printed anywhere on the books page.",
|
|
343
344
|
"section/accounting-profit-to-tax-profit-bridge/less-the-full-return-s-own-zero-emission-car-allowance-box-52-1": "The page has no profit-bridge view; the bridge from accounting profit to tax profit is not printed anywhere on the books page.",
|
|
344
345
|
"section/accounting-profit-to-tax-profit-bridge/less-the-full-return-s-own-zero-emission-goods-vehicle-allowance-box-52": "The page has no profit-bridge view; the bridge from accounting profit to tax profit is not printed anywhere on the books page.",
|
|
@@ -466,5 +467,20 @@
|
|
|
466
467
|
"cell/Fixedassets.xlsx!Schedule!AD40": "The single asset pool car's own Schedule row (the third motor asset brought forward): its private use share, its P marker, its allowance and its written-down value. The Fixed assets view lists the brought-forward register by asset, without a cell key a row, and the AE1, AF1 and AG1 totals those rows sum into are on the same view under their own cell keys.",
|
|
467
468
|
"cell/Fixedassets.xlsx!Schedule!AE40": "The single asset pool car's own Schedule row (the third motor asset brought forward): its private use share, its P marker, its allowance and its written-down value. The Fixed assets view lists the brought-forward register by asset, without a cell key a row, and the AE1, AF1 and AG1 totals those rows sum into are on the same view under their own cell keys.",
|
|
468
469
|
"cell/Fixedassets.xlsx!Schedule!AG40": "The single asset pool car's own Schedule row (the third motor asset brought forward): its private use share, its P marker, its allowance and its written-down value. The Fixed assets view lists the brought-forward register by asset, without a cell key a row, and the AE1, AF1 and AG1 totals those rows sum into are on the same view under their own cell keys.",
|
|
469
|
-
"section/accounting-profit-to-tax-profit-bridge/add-the-full-return-s-own-box-71-adjustment-for-change-of-accounting-practice": "The page has no profit-bridge view; the bridge from accounting profit to tax profit is not printed anywhere on the books page."
|
|
470
|
+
"section/accounting-profit-to-tax-profit-bridge/add-the-full-return-s-own-box-71-adjustment-for-change-of-accounting-practice": "The page has no profit-bridge view; the bridge from accounting profit to tax profit is not printed anywhere on the books page.",
|
|
471
|
+
"cell/Fixedassets.xlsx!Schedule!B115": "The fixture's own Structures and Buildings Allowance claim row (standard rate): its date, building, expenditure and postcode. The Fixed assets view has no per-claim table, and the K120 total those rows sum into is on the same view under its own cell key.",
|
|
472
|
+
"cell/Fixedassets.xlsx!Schedule!C115": "The fixture's own Structures and Buildings Allowance claim row (standard rate): its date, building, expenditure and postcode. The Fixed assets view has no per-claim table, and the K120 total those rows sum into is on the same view under its own cell key.",
|
|
473
|
+
"cell/Fixedassets.xlsx!Schedule!E115": "The fixture's own Structures and Buildings Allowance claim row (standard rate): its date, building, expenditure and postcode. The Fixed assets view has no per-claim table, and the K120 total those rows sum into is on the same view under its own cell key.",
|
|
474
|
+
"cell/Fixedassets.xlsx!Schedule!F115": "The fixture's own Structures and Buildings Allowance claim row (standard rate): its date, building, expenditure and postcode. The Fixed assets view has no per-claim table, and the K120 total those rows sum into is on the same view under its own cell key.",
|
|
475
|
+
"cell/Fixedassets.xlsx!Schedule!H115": "The fixture's own Structures and Buildings Allowance claim row (standard rate): its rate, its days claimed and its allowance. The Fixed assets view has no per-claim table, and the K120 total those rows sum into is on the same view under its own cell key.",
|
|
476
|
+
"cell/Fixedassets.xlsx!Schedule!J115": "The fixture's own Structures and Buildings Allowance claim row (standard rate): its rate, its days claimed and its allowance. The Fixed assets view has no per-claim table, and the K120 total those rows sum into is on the same view under its own cell key.",
|
|
477
|
+
"cell/Fixedassets.xlsx!Schedule!K115": "The fixture's own Structures and Buildings Allowance claim row (standard rate): its rate, its days claimed and its allowance. The Fixed assets view has no per-claim table, and the K120 total those rows sum into is on the same view under its own cell key.",
|
|
478
|
+
"cell/Fixedassets.xlsx!Schedule!B116": "The fixture's own Structures and Buildings Allowance claim row (the Freeport claim): its date, building, expenditure, postcode and tax site marker. The Fixed assets view has no per-claim table, and the K121 total those rows sum into is on the same view under its own cell key.",
|
|
479
|
+
"cell/Fixedassets.xlsx!Schedule!D116": "The fixture's own Structures and Buildings Allowance claim row (the Freeport claim): its date, building, expenditure, postcode and tax site marker. The Fixed assets view has no per-claim table, and the K121 total those rows sum into is on the same view under its own cell key.",
|
|
480
|
+
"cell/Fixedassets.xlsx!Schedule!E116": "The fixture's own Structures and Buildings Allowance claim row (the Freeport claim): its date, building, expenditure, postcode and tax site marker. The Fixed assets view has no per-claim table, and the K121 total those rows sum into is on the same view under its own cell key.",
|
|
481
|
+
"cell/Fixedassets.xlsx!Schedule!F116": "The fixture's own Structures and Buildings Allowance claim row (the Freeport claim): its date, building, expenditure, postcode and tax site marker. The Fixed assets view has no per-claim table, and the K121 total those rows sum into is on the same view under its own cell key.",
|
|
482
|
+
"cell/Fixedassets.xlsx!Schedule!G116": "The fixture's own Structures and Buildings Allowance claim row (the Freeport claim): its date, building, expenditure, postcode and tax site marker. The Fixed assets view has no per-claim table, and the K121 total those rows sum into is on the same view under its own cell key.",
|
|
483
|
+
"cell/Fixedassets.xlsx!Schedule!H116": "The fixture's own Structures and Buildings Allowance claim row (the Freeport claim): its rate, its days claimed and its allowance. The Fixed assets view has no per-claim table, and the K121 total those rows sum into is on the same view under its own cell key.",
|
|
484
|
+
"cell/Fixedassets.xlsx!Schedule!J116": "The fixture's own Structures and Buildings Allowance claim row (the Freeport claim): its rate, its days claimed and its allowance. The Fixed assets view has no per-claim table, and the K121 total those rows sum into is on the same view under its own cell key.",
|
|
485
|
+
"cell/Fixedassets.xlsx!Schedule!K116": "The fixture's own Structures and Buildings Allowance claim row (the Freeport claim): its rate, its days claimed and its allowance. The Fixed assets view has no per-claim table, and the K121 total those rows sum into is on the same view under its own cell key."
|
|
470
486
|
}
|
|
@@ -36,6 +36,8 @@ class2_small_profits_threshold = 6475
|
|
|
36
36
|
annual_investment_allowance = 1.00
|
|
37
37
|
writing_down_allowance = 0.18
|
|
38
38
|
writing_down_allowance_special = 0.06
|
|
39
|
+
structures_and_buildings_allowance = 0.03
|
|
40
|
+
structures_and_buildings_allowance_enhanced = 0.10
|
|
39
41
|
|
|
40
42
|
[depreciation]
|
|
41
43
|
land_and_property = 0.00
|
|
@@ -36,6 +36,8 @@ class2_small_profits_threshold = 6515
|
|
|
36
36
|
annual_investment_allowance = 1.00
|
|
37
37
|
writing_down_allowance = 0.18
|
|
38
38
|
writing_down_allowance_special = 0.06
|
|
39
|
+
structures_and_buildings_allowance = 0.03
|
|
40
|
+
structures_and_buildings_allowance_enhanced = 0.10
|
|
39
41
|
|
|
40
42
|
[depreciation]
|
|
41
43
|
land_and_property = 0.00
|
|
@@ -39,6 +39,8 @@ class2_small_profits_threshold = 6725
|
|
|
39
39
|
annual_investment_allowance = 1.00
|
|
40
40
|
writing_down_allowance = 0.18
|
|
41
41
|
writing_down_allowance_special = 0.06
|
|
42
|
+
structures_and_buildings_allowance = 0.03
|
|
43
|
+
structures_and_buildings_allowance_enhanced = 0.10
|
|
42
44
|
|
|
43
45
|
[depreciation]
|
|
44
46
|
land_and_property = 0.00
|
|
@@ -38,6 +38,8 @@ class2_small_profits_threshold = 6725
|
|
|
38
38
|
annual_investment_allowance = 1.00
|
|
39
39
|
writing_down_allowance = 0.18
|
|
40
40
|
writing_down_allowance_special = 0.06
|
|
41
|
+
structures_and_buildings_allowance = 0.03
|
|
42
|
+
structures_and_buildings_allowance_enhanced = 0.10
|
|
41
43
|
|
|
42
44
|
[depreciation]
|
|
43
45
|
land_and_property = 0.00
|
|
@@ -35,6 +35,8 @@ class2_small_profits_threshold = 6725
|
|
|
35
35
|
annual_investment_allowance = 1.00
|
|
36
36
|
writing_down_allowance = 0.18
|
|
37
37
|
writing_down_allowance_special = 0.06
|
|
38
|
+
structures_and_buildings_allowance = 0.03
|
|
39
|
+
structures_and_buildings_allowance_enhanced = 0.10
|
|
38
40
|
|
|
39
41
|
[depreciation]
|
|
40
42
|
land_and_property = 0.00
|
|
@@ -35,6 +35,8 @@ class2_small_profits_threshold = 6845
|
|
|
35
35
|
annual_investment_allowance = 1.00
|
|
36
36
|
writing_down_allowance = 0.18
|
|
37
37
|
writing_down_allowance_special = 0.06
|
|
38
|
+
structures_and_buildings_allowance = 0.03
|
|
39
|
+
structures_and_buildings_allowance_enhanced = 0.10
|
|
38
40
|
|
|
39
41
|
[depreciation]
|
|
40
42
|
land_and_property = 0.00
|
|
@@ -35,6 +35,8 @@ class2_small_profits_threshold = 7105
|
|
|
35
35
|
annual_investment_allowance = 1.00
|
|
36
36
|
writing_down_allowance = 0.14
|
|
37
37
|
writing_down_allowance_special = 0.06
|
|
38
|
+
structures_and_buildings_allowance = 0.03
|
|
39
|
+
structures_and_buildings_allowance_enhanced = 0.10
|
|
38
40
|
|
|
39
41
|
[depreciation]
|
|
40
42
|
land_and_property = 0.00
|
|
@@ -41,6 +41,8 @@ import {
|
|
|
41
41
|
EXISTING_ASSET_ROWS,
|
|
42
42
|
NEW_PLANT_ROWS,
|
|
43
43
|
HP_AGREEMENT_ROWS,
|
|
44
|
+
SBA_CLAIM_ROWS,
|
|
45
|
+
SBA_CLAIM_COLUMNS,
|
|
44
46
|
} from "../../products/se.js";
|
|
45
47
|
import { SALES_ANALYSIS_COLUMNS, PURCHASES_ANALYSIS_COLUMNS } from "../calculators/se.js";
|
|
46
48
|
import {
|
|
@@ -230,6 +232,7 @@ export const SE_ANCHORS = {
|
|
|
230
232
|
{ sheet: "Schedule", cell: "C1", label: "FIXED ASSETS" },
|
|
231
233
|
{ sheet: "Schedule", cell: "B59", label: "NEW FIXED ASSETS Bought AFTER" }, // template carries a trailing space; textAt() trims it
|
|
232
234
|
{ sheet: "Schedule", cell: "B64", label: "New Land & Property" },
|
|
235
|
+
{ sheet: "Schedule", cell: "B113", label: "STRUCTURES AND BUILDINGS ALLOWANCE (SA103F boxes 53 and 53.1)" },
|
|
233
236
|
{ sheet: "HPfinance", cell: "B5", label: "Agreement Date" },
|
|
234
237
|
{ sheet: "HPfinance", cell: "C5", label: "Finance Company" },
|
|
235
238
|
{ sheet: "HPfinance", cell: "E5", label: "Total Amount Financed excluding Admin & Interest" },
|
|
@@ -361,7 +364,9 @@ function isPayslipsInputCell(sheet, cellRef) {
|
|
|
361
364
|
// its private use share (M), its special rate pool marker (AB) and its single
|
|
362
365
|
// asset pool marker (AD) on its existing-asset row, or an
|
|
363
366
|
// in-year disposal's date/proceeds (U, V) on that same row; a new purchase's
|
|
364
|
-
// date/supplier/cost (B, C, E) on a New Plant & Machinery row
|
|
367
|
+
// date/supplier/cost (B, C, E) on a New Plant & Machinery row; a Structures
|
|
368
|
+
// and Buildings Allowance claim's date/building/expenditure/postcode/tax
|
|
369
|
+
// site/ceased date (B, C, D, E, F, G, I) on an SBA claim row. See
|
|
365
370
|
// app/products/se.js's cellWrites() Schedule writer.
|
|
366
371
|
const EXISTING_SCHEDULE_ROWS = new Set([...EXISTING_ASSET_ROWS.motor, ...EXISTING_ASSET_ROWS.computer]);
|
|
367
372
|
const NEW_SCHEDULE_ROWS = new Set(NEW_PLANT_ROWS);
|
|
@@ -377,6 +382,8 @@ const EXISTING_SCHEDULE_COLUMNS = [
|
|
|
377
382
|
SINGLE_ASSET_POOL_MARKER_COLUMN,
|
|
378
383
|
];
|
|
379
384
|
const NEW_SCHEDULE_COLUMNS = ["B", "C", "E"];
|
|
385
|
+
const SBA_SCHEDULE_ROWS = new Set(SBA_CLAIM_ROWS);
|
|
386
|
+
const SBA_SCHEDULE_COLUMNS = Object.values(SBA_CLAIM_COLUMNS);
|
|
380
387
|
const HP_ROWS = new Set(HP_AGREEMENT_ROWS);
|
|
381
388
|
const HP_COLUMNS = ["B", "C", "D", "E", "F", "G", "H", "L"];
|
|
382
389
|
|
|
@@ -386,6 +393,7 @@ function isFixedAssetsInputCell(sheet, cellRef) {
|
|
|
386
393
|
if (sheet === "Schedule") {
|
|
387
394
|
if (EXISTING_SCHEDULE_ROWS.has(ref.row)) return EXISTING_SCHEDULE_COLUMNS.includes(ref.col);
|
|
388
395
|
if (NEW_SCHEDULE_ROWS.has(ref.row)) return NEW_SCHEDULE_COLUMNS.includes(ref.col);
|
|
396
|
+
if (SBA_SCHEDULE_ROWS.has(ref.row)) return SBA_SCHEDULE_COLUMNS.includes(ref.col);
|
|
389
397
|
return false;
|
|
390
398
|
}
|
|
391
399
|
if (sheet === "HPfinance") return HP_ROWS.has(ref.row) && HP_COLUMNS.includes(ref.col);
|
|
@@ -17,7 +17,7 @@ import { resolve, dirname } from "path";
|
|
|
17
17
|
import { fileURLToPath } from "url";
|
|
18
18
|
import { diyaGlToScenario } from "../diya-gl-loader.js";
|
|
19
19
|
import { calculateSeCells } from "./se.js";
|
|
20
|
-
import { SE_YEAR_END_MONTH } from "../../products/se.js";
|
|
20
|
+
import { SE_YEAR_END_MONTH, SBA_CLAIM_ROWS } from "../../products/se.js";
|
|
21
21
|
import { extractTaxYearStart, parseDate } from "../scenario-loader.js";
|
|
22
22
|
import { shiftMonths, periodShiftMonths } from "../period-shift.js";
|
|
23
23
|
import { splitVat } from "../tax/vat.js";
|
|
@@ -465,9 +465,8 @@ export function buildSelfEmploymentQuarterlyUpdates(book, lines, taxData, option
|
|
|
465
465
|
// reads it back from there, so the payload carries what the return prints.
|
|
466
466
|
// A box the book does not state stays blank and warns.
|
|
467
467
|
const BOOK_STATED_ANNUAL_BOXES = [
|
|
468
|
-
{ box: "52", cell: "
|
|
469
|
-
{ box: "52.1", cell: "
|
|
470
|
-
{ box: "53", cell: "D160", table: "allowances" }, // structuredBuildingAllowance
|
|
468
|
+
{ box: "52", cell: "D150", table: "allowances" }, // zeroEmissionsGoodsVehicleAllowance -- gone from 2025-26
|
|
469
|
+
{ box: "52.1", cell: "D152", table: "allowances" }, // zeroEmissionsCarAllowance
|
|
471
470
|
{ box: "62", cell: "D179", table: "adjustments" }, // includedNonTaxableProfits
|
|
472
471
|
{ box: "71", cell: "D210", table: "adjustments" }, // accountingAdjustment
|
|
473
472
|
];
|
|
@@ -477,9 +476,10 @@ const BOOK_STATED_ANNUAL_BOXES = [
|
|
|
477
476
|
// out of reach today: no cell in the template, or a figure the book has no
|
|
478
477
|
// record for. Box 69's field also moves out of HMRC's own schema by tax
|
|
479
478
|
// year -- annualFieldsUnavailableForYear() below is what keeps a year that
|
|
480
|
-
// no longer accepts a field from warning about it as if it still did.
|
|
479
|
+
// no longer accepts a field from warning about it as if it still did. Boxes
|
|
480
|
+
// 53 and 53.1 are not here: the Schedule's SBA block computes them, and
|
|
481
|
+
// they are filed as arrays below, one item per claim.
|
|
481
482
|
const NO_SOURCE_ANNUAL_BOXES = [
|
|
482
|
-
{ box: "53.1", pick: 0 }, // allowances.enhancedStructuredBuildingAllowance
|
|
483
483
|
{ box: "55", pick: 1 }, // allowances.businessPremisesRenovationAllowance (shared with enhancedCapitalAllowance)
|
|
484
484
|
{ box: "59", pick: 1 }, // adjustments.balancingChargeBpra (shared with balancingChargeOther)
|
|
485
485
|
{ box: "68", pick: 0 }, // adjustments.basisAdjustment
|
|
@@ -624,6 +624,44 @@ export function buildSelfEmploymentAnnualSubmission(book, lines, taxData, option
|
|
|
624
624
|
});
|
|
625
625
|
}
|
|
626
626
|
|
|
627
|
+
// Structures and Buildings Allowance (boxes 53 and 53.1): the Schedule's
|
|
628
|
+
// SBA block computes each claim's year allowance from the book's own
|
|
629
|
+
// inputs, so the claim files as one item per row, not a stated scalar. A
|
|
630
|
+
// claim whose allowance is nil this year (ceased before the period, or
|
|
631
|
+
// past the 33 1/3 year limit) carries nothing to file. firstYear is the
|
|
632
|
+
// API's first-year details, filed once, on the claim's own qualifying
|
|
633
|
+
// date -- a claim already running before this package's period does not
|
|
634
|
+
// repeat them.
|
|
635
|
+
const admin = rawResults["Admin"] || {};
|
|
636
|
+
const structuredBuildingAllowance = [];
|
|
637
|
+
const enhancedStructuredBuildingAllowance = [];
|
|
638
|
+
SBA_CLAIM_ROWS.forEach((row, index) => {
|
|
639
|
+
const claim = (scenario.sba_claims || [])[index];
|
|
640
|
+
if (!claim) return;
|
|
641
|
+
const amount = schedule?.[`K${row}`];
|
|
642
|
+
if (typeof amount !== "number" || amount === 0) return;
|
|
643
|
+
const item = { amount: round2(amount), building: { ...claim.building } };
|
|
644
|
+
const qualifyingSerial = schedule[`B${row}`];
|
|
645
|
+
if (typeof qualifyingSerial === "number" && typeof admin.B4 === "number" && qualifyingSerial >= admin.B4) {
|
|
646
|
+
// A book's own TOML date parses as a Date instance; the API payload
|
|
647
|
+
// states a date the same way every time, regardless of how the
|
|
648
|
+
// caller's scenario happened to carry it.
|
|
649
|
+
item.firstYear = {
|
|
650
|
+
qualifyingDate: parseDate(claim.qualifyingDate).toISOString().slice(0, 10),
|
|
651
|
+
qualifyingAmountExpenditure: claim.qualifyingAmountExpenditure,
|
|
652
|
+
};
|
|
653
|
+
}
|
|
654
|
+
(claim.enhanced ? enhancedStructuredBuildingAllowance : structuredBuildingAllowance).push(item);
|
|
655
|
+
});
|
|
656
|
+
const structuredBuildingField = primaryField(boxes, "53");
|
|
657
|
+
const enhancedStructuredBuildingField = primaryField(boxes, "53.1");
|
|
658
|
+
if (structuredBuildingAllowance.length > 0 && !unavailableFields.has(structuredBuildingField)) {
|
|
659
|
+
setPath(root, structuredBuildingField, structuredBuildingAllowance);
|
|
660
|
+
}
|
|
661
|
+
if (enhancedStructuredBuildingAllowance.length > 0 && !unavailableFields.has(enhancedStructuredBuildingField)) {
|
|
662
|
+
setPath(root, enhancedStructuredBuildingField, enhancedStructuredBuildingAllowance);
|
|
663
|
+
}
|
|
664
|
+
|
|
627
665
|
const allowances = root.allowances || {};
|
|
628
666
|
const adjustments = root.adjustments || {};
|
|
629
667
|
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
import { MONTH_SHEETS, extractTaxYearStart } from "../scenario-loader.js";
|
|
18
18
|
import { shiftMonths, periodShiftMonths } from "../period-shift.js";
|
|
19
|
-
import { standardReads, multiFileOptions, SE_YEAR_END_MONTH } from "../../products/se.js";
|
|
19
|
+
import { standardReads, multiFileOptions, SE_YEAR_END_MONTH, SBA_CLAIM_ROWS } from "../../products/se.js";
|
|
20
20
|
import { generateAdminDates, seVatPaymentDueDate, generatePayslipsCalendar } from "../generator.js";
|
|
21
21
|
import { calculateIncomeTax } from "../tax/income-tax.js";
|
|
22
22
|
import { calculateMileageAllowance } from "../tax/mileage.js";
|
|
@@ -632,6 +632,62 @@ function buildSchedule(scenario, taxData, rate) {
|
|
|
632
632
|
return { existing, additions, totals: addScheduleTotals(existing, additions), motorRowCells };
|
|
633
633
|
}
|
|
634
634
|
|
|
635
|
+
// ── Structures and Buildings Allowance (SA103F boxes 53 and 53.1) ──────────
|
|
636
|
+
//
|
|
637
|
+
// Fixedassets.xlsx!Schedule rows 115 to 119, below the fixed asset register.
|
|
638
|
+
// The book states each claim's inputs; the sheet computes the year's
|
|
639
|
+
// allowance from the year file's rate over the days of the chargeable
|
|
640
|
+
// period the claim covers. Verified against the template:
|
|
641
|
+
// H115 = IF(E115>0,IF(G115="F",[1]Admin!$G$10,[1]Admin!$G$9)," ")
|
|
642
|
+
// J115 = IF(E115>0,MAX(0,MIN($S$4,IF(N(I115)>0,I115,$S$4),
|
|
643
|
+
// EDATE(B115,IF(G115="F",120,400))-1)-MAX($D$6,B115)+1)," ")
|
|
644
|
+
// K115 = IF(E115>0,E115*H115*J115/($S$4-$D$6+1)," ")
|
|
645
|
+
// $D$6 = [1]Admin!$B$4 (period start) and $S$4 = [1]Admin!$B$17 (period
|
|
646
|
+
// end); 400 and 120 months are the 33 1/3 and 10 year limits. K120 =
|
|
647
|
+
// SUMIF(G115:G119,"<>F",K115:K119) (box 53), K121 the same with "F"
|
|
648
|
+
// (box 53.1). A claim's dates shift by the same whole-year offset as every
|
|
649
|
+
// other scenario date, so every package year sees the same day counts.
|
|
650
|
+
function buildStructuresAndBuildings(scenario, admin, monthOffset) {
|
|
651
|
+
const periodStart = admin.B4;
|
|
652
|
+
const periodEnd = admin.B17;
|
|
653
|
+
const claims = scenario.sba_claims || [];
|
|
654
|
+
const cells = {};
|
|
655
|
+
let standardTotal = 0;
|
|
656
|
+
let enhancedTotal = 0;
|
|
657
|
+
|
|
658
|
+
SBA_CLAIM_ROWS.forEach((row, index) => {
|
|
659
|
+
const claim = claims[index];
|
|
660
|
+
if (!claim) return;
|
|
661
|
+
const enhanced = claim.enhanced === true;
|
|
662
|
+
const qualifyingDate = excelSerial(shiftMonths(new Date(claim.qualifyingDate), monthOffset));
|
|
663
|
+
cells[`B${row}`] = qualifyingDate;
|
|
664
|
+
if (claim.building?.name) cells[`C${row}`] = claim.building.name;
|
|
665
|
+
if (claim.building?.number) cells[`D${row}`] = claim.building.number;
|
|
666
|
+
cells[`E${row}`] = claim.qualifyingAmountExpenditure;
|
|
667
|
+
cells[`F${row}`] = claim.building.postcode;
|
|
668
|
+
if (enhanced) cells[`G${row}`] = "F";
|
|
669
|
+
let ceasedDate;
|
|
670
|
+
if (claim.ceasedDate) {
|
|
671
|
+
ceasedDate = excelSerial(shiftMonths(new Date(claim.ceasedDate), monthOffset));
|
|
672
|
+
cells[`I${row}`] = ceasedDate;
|
|
673
|
+
}
|
|
674
|
+
const rate = enhanced ? admin.G10 : admin.G9;
|
|
675
|
+
cells[`H${row}`] = rate;
|
|
676
|
+
const limitMonths = enhanced ? 120 : 400;
|
|
677
|
+
const limitEndSerial = excelSerial(shiftMonths(dateFromExcelSerial(qualifyingDate), limitMonths)) - 1;
|
|
678
|
+
const upperBound = Math.min(periodEnd, ceasedDate !== undefined ? ceasedDate : periodEnd, limitEndSerial);
|
|
679
|
+
const lowerBound = Math.max(periodStart, qualifyingDate);
|
|
680
|
+
const days = Math.max(0, upperBound - lowerBound + 1);
|
|
681
|
+
cells[`J${row}`] = days;
|
|
682
|
+
const allowance = (claim.qualifyingAmountExpenditure * rate * days) / (periodEnd - periodStart + 1);
|
|
683
|
+
cells[`K${row}`] = allowance;
|
|
684
|
+
if (enhanced) enhancedTotal += allowance;
|
|
685
|
+
else standardTotal += allowance;
|
|
686
|
+
});
|
|
687
|
+
|
|
688
|
+
return { cells, K120: standardTotal, K121: enhancedTotal };
|
|
689
|
+
}
|
|
690
|
+
|
|
635
691
|
// ── Hire purchase ──────────────────────────────────────────────────────────
|
|
636
692
|
|
|
637
693
|
function buildHpFinance(scenario) {
|
|
@@ -750,6 +806,8 @@ function buildAdmin(taxData, dateSerials) {
|
|
|
750
806
|
cells.G4 = ca.annual_investment_allowance;
|
|
751
807
|
cells.G5 = ca.writing_down_allowance;
|
|
752
808
|
cells.G6 = ca.writing_down_allowance_special;
|
|
809
|
+
cells.G9 = ca.structures_and_buildings_allowance;
|
|
810
|
+
cells.G10 = ca.structures_and_buildings_allowance_enhanced;
|
|
753
811
|
cells.G13 = dep.land_and_property;
|
|
754
812
|
cells.G14 = dep.plant_and_machinery;
|
|
755
813
|
cells.G15 = dep.fixtures_and_fittings;
|
|
@@ -824,6 +882,7 @@ export function calculateSeCells(book, lines, taxData, scenario = {}) {
|
|
|
824
882
|
const payroll = payrollMonths(scenario.payroll);
|
|
825
883
|
const schedule = buildSchedule(scenario, taxData, rate);
|
|
826
884
|
const scheduleNumber = (column) => sheetNumber(schedule.totals[column]);
|
|
885
|
+
const sba = buildStructuresAndBuildings(scenario, admin, monthOffset);
|
|
827
886
|
|
|
828
887
|
// The twelve monthly stock cells telescope, so whatever is counted between
|
|
829
888
|
// them the year's movement is the difference between its two ends. A count at
|
|
@@ -1020,7 +1079,15 @@ export function calculateSeCells(book, lines, taxData, scenario = {}) {
|
|
|
1020
1079
|
const boxes32to45Total = sheetSum(Object.values(seFullDisallowable)) + pl.B34;
|
|
1021
1080
|
|
|
1022
1081
|
// ── The fixed asset workbook ──
|
|
1023
|
-
const scheduleCells = {
|
|
1082
|
+
const scheduleCells = {
|
|
1083
|
+
E57: schedule.existing.E,
|
|
1084
|
+
E110: schedule.additions.E,
|
|
1085
|
+
AC4: admin.G6,
|
|
1086
|
+
...schedule.motorRowCells,
|
|
1087
|
+
...sba.cells,
|
|
1088
|
+
K120: sba.K120,
|
|
1089
|
+
K121: sba.K121,
|
|
1090
|
+
};
|
|
1024
1091
|
for (const column of SCHEDULE_TOTAL_COLUMNS) scheduleCells[`${column}1`] = schedule.totals[column];
|
|
1025
1092
|
const faReconciliation = {
|
|
1026
1093
|
E11: schedule.additions.E,
|
|
@@ -1221,18 +1288,31 @@ export function calculateSeCells(book, lines, taxData, scenario = {}) {
|
|
|
1221
1288
|
seFull.D147 = carry([scheduleAC], () => scheduleAC);
|
|
1222
1289
|
// Boxes with no formula behind them, carrying whatever figure the book
|
|
1223
1290
|
// states and blank otherwise.
|
|
1224
|
-
seFull.
|
|
1225
|
-
seFull.
|
|
1226
|
-
seFull.D160 = stated(annualAllowances.structuredBuildingAllowance);
|
|
1291
|
+
seFull.D150 = stated(annualAllowances.zeroEmissionsGoodsVehicleAllowance);
|
|
1292
|
+
seFull.D152 = stated(annualAllowances.zeroEmissionsCarAllowance);
|
|
1227
1293
|
seFull.O139 = stated(annualAllowances.electricChargePointAllowance);
|
|
1228
1294
|
seFull.D179 = stated(annualAdjustments.includedNonTaxableProfits);
|
|
1229
1295
|
seFull.D210 = stated(annualAdjustments.accountingAdjustment);
|
|
1296
|
+
// Boxes 53 and 53.1: the Schedule's SBA block computes them, not the book.
|
|
1297
|
+
seFull.D156 = sba.K120;
|
|
1298
|
+
seFull.D160 = sba.K121;
|
|
1230
1299
|
// Box 50 carries the whole writing down allowance the schedule claims.
|
|
1231
1300
|
seFull.D144 = carry([scheduleR], () => scheduleR);
|
|
1232
1301
|
seFull.O144 = smallPoolsWriteOff;
|
|
1233
1302
|
seFull.O149 = scheduleY;
|
|
1234
1303
|
seFull.O154 = carry([seFull.D139, seFull.D144, seFull.O144, seFull.O149], () =>
|
|
1235
|
-
sheetSum([
|
|
1304
|
+
sheetSum([
|
|
1305
|
+
seFull.D139,
|
|
1306
|
+
seFull.D144,
|
|
1307
|
+
seFull.D147,
|
|
1308
|
+
seFull.D150,
|
|
1309
|
+
seFull.D152,
|
|
1310
|
+
seFull.D156,
|
|
1311
|
+
seFull.D160,
|
|
1312
|
+
seFull.O139,
|
|
1313
|
+
seFull.O144,
|
|
1314
|
+
seFull.O149,
|
|
1315
|
+
]),
|
|
1236
1316
|
);
|
|
1237
1317
|
seFull.O160 = scheduleZ;
|
|
1238
1318
|
seFull.D169 = goodsForOwnUse;
|
|
@@ -265,16 +265,20 @@ function renderAccounts(bookSchema, accounts, lines) {
|
|
|
265
265
|
// A plain object table (documentInfo, entityInformation, stock, tax's own
|
|
266
266
|
// sub-sections, openingBalances' assetClassAmounts): every property in
|
|
267
267
|
// schema order, scalars as `key = value`, a nested object recursed as
|
|
268
|
-
// `[header.key]`,
|
|
269
|
-
//
|
|
268
|
+
// `[header.key]`, an array as `[[header.key]]` blocks (structuresBuildings
|
|
269
|
+
// AllowanceClaim, tax.selfEmployment.allowances' own claim arrays), and a
|
|
270
|
+
// patternProperties dict (only openingBalances.bankAccounts is one) as a
|
|
271
|
+
// table of bare account-code keys.
|
|
270
272
|
function renderObjectTable(bookSchema, header, value, objectSchema, lines) {
|
|
271
273
|
const props = objectSchema?.properties || {};
|
|
272
274
|
const scalarKeys = [];
|
|
273
275
|
const nestedKeys = [];
|
|
276
|
+
const arrayKeys = [];
|
|
274
277
|
for (const key of Object.keys(props)) {
|
|
275
278
|
if (value[key] === undefined) continue;
|
|
276
279
|
const propSchema = resolveRef(bookSchema, props[key]);
|
|
277
|
-
if (propSchema.type === "
|
|
280
|
+
if (propSchema.type === "array") arrayKeys.push(key);
|
|
281
|
+
else if (propSchema.type === "object") nestedKeys.push(key);
|
|
278
282
|
else scalarKeys.push(key);
|
|
279
283
|
}
|
|
280
284
|
if (scalarKeys.length > 0) {
|
|
@@ -292,16 +296,34 @@ function renderObjectTable(bookSchema, header, value, objectSchema, lines) {
|
|
|
292
296
|
renderObjectTable(bookSchema, `${header}.${key}`, value[key], propSchema, lines);
|
|
293
297
|
}
|
|
294
298
|
}
|
|
299
|
+
for (const key of arrayKeys) {
|
|
300
|
+
const propSchema = resolveRef(bookSchema, props[key]);
|
|
301
|
+
renderArrayOfTables(bookSchema, `${header}.${key}`, value[key], resolveRef(bookSchema, propSchema.items), lines);
|
|
302
|
+
}
|
|
295
303
|
}
|
|
296
304
|
|
|
297
|
-
|
|
305
|
+
// items is an array-of-tables ([[key]] blocks); an item field whose own
|
|
306
|
+
// schema is an object (structuresBuildingsAllowanceClaim's building) prints
|
|
307
|
+
// as a [key.field] table straight after that item's own [[key]] block,
|
|
308
|
+
// rather than as a scalar -- the one shape "[[key]]" plus a following
|
|
309
|
+
// object header can express without a nesting level of its own.
|
|
310
|
+
function renderArrayOfTables(bookSchema, key, items, itemSchema, lines) {
|
|
298
311
|
for (const item of sortById(items, itemSchema)) {
|
|
299
312
|
lines.push(`[[${key}]]`);
|
|
313
|
+
const nestedFields = [];
|
|
300
314
|
for (const field of Object.keys(itemSchema.properties)) {
|
|
301
315
|
if (item[field] === undefined) continue;
|
|
302
|
-
|
|
316
|
+
const fieldSchema = resolveRef(bookSchema, itemSchema.properties[field]);
|
|
317
|
+
if (fieldSchema.type === "object") {
|
|
318
|
+
nestedFields.push(field);
|
|
319
|
+
continue;
|
|
320
|
+
}
|
|
321
|
+
lines.push(`${tomlKey(field)} = ${tomlScalar(item[field], fieldSchema)}`);
|
|
303
322
|
}
|
|
304
323
|
lines.push("");
|
|
324
|
+
for (const field of nestedFields) {
|
|
325
|
+
renderObjectTable(bookSchema, `${key}.${field}`, item[field], resolveRef(bookSchema, itemSchema.properties[field]), lines);
|
|
326
|
+
}
|
|
305
327
|
}
|
|
306
328
|
}
|
|
307
329
|
|
|
@@ -326,7 +348,7 @@ export function canonicalBookToml(book) {
|
|
|
326
348
|
}
|
|
327
349
|
const propSchema = resolveRef(bookSchema, bookSchema.properties[key]);
|
|
328
350
|
if (propSchema.type === "array") {
|
|
329
|
-
renderArrayOfTables(key, book[key], resolveRef(bookSchema, propSchema.items), lines);
|
|
351
|
+
renderArrayOfTables(bookSchema, key, book[key], resolveRef(bookSchema, propSchema.items), lines);
|
|
330
352
|
} else {
|
|
331
353
|
renderObjectTable(bookSchema, key, book[key], propSchema, lines);
|
|
332
354
|
}
|
|
@@ -457,7 +457,18 @@ export function diyaGlToScenario(book, lines, product) {
|
|
|
457
457
|
// The annual SA103F figures the trader states by hand, keyed by HMRC's
|
|
458
458
|
// own field names: the writer puts each on its SE Full box and the
|
|
459
459
|
// derivation files it from there.
|
|
460
|
-
if (allowances)
|
|
460
|
+
if (allowances) {
|
|
461
|
+
const { structuredBuildingAllowance, enhancedStructuredBuildingAllowance, ...restAllowances } = allowances;
|
|
462
|
+
if (Object.keys(restAllowances).length > 0) scenario.annual_allowances = { ...restAllowances };
|
|
463
|
+
// Structures and Buildings Allowance claims are inputs the Schedule's
|
|
464
|
+
// own SBA block computes the year's allowance from, not a stated
|
|
465
|
+
// figure, so they carry as claims rather than joining annual_allowances.
|
|
466
|
+
const sbaClaims = [
|
|
467
|
+
...(structuredBuildingAllowance || []).map((claim) => ({ ...claim, enhanced: false })),
|
|
468
|
+
...(enhancedStructuredBuildingAllowance || []).map((claim) => ({ ...claim, enhanced: true })),
|
|
469
|
+
];
|
|
470
|
+
if (sbaClaims.length > 0) scenario.sba_claims = sbaClaims;
|
|
471
|
+
}
|
|
461
472
|
if (adjustments) scenario.annual_adjustments = { ...adjustments };
|
|
462
473
|
}
|
|
463
474
|
if (book.debtors) {
|
|
@@ -825,7 +836,11 @@ export function extractTaxDataFromBook(book, product) {
|
|
|
825
836
|
annual_investment_allowance: ca.annualInvestmentAllowance ? ca.annualInvestmentAllowance / 1000000 : 1.0,
|
|
826
837
|
writing_down_allowance: ca.mainRateWDA || 0.18,
|
|
827
838
|
};
|
|
828
|
-
if (product === "se")
|
|
839
|
+
if (product === "se") {
|
|
840
|
+
baseTaxData.capital_allowances.writing_down_allowance_special = ca.specialRateWDA || 0.06;
|
|
841
|
+
baseTaxData.capital_allowances.structures_and_buildings_allowance = ca.structuresAndBuildingsAllowance || 0.03;
|
|
842
|
+
baseTaxData.capital_allowances.structures_and_buildings_allowance_enhanced = ca.structuresAndBuildingsAllowanceEnhanced || 0.1;
|
|
843
|
+
}
|
|
829
844
|
}
|
|
830
845
|
const taxYearFile = taxYearFileForBook(book, product === "ltd" ? "ltd" : "se");
|
|
831
846
|
baseTaxData.depreciation = taxYearFile.depreciation;
|
|
@@ -462,10 +462,14 @@ export function buildSeCellEdits(taxData, startYear) {
|
|
|
462
462
|
|
|
463
463
|
// Capital allowances — G4 and G5 as BST; G6 is the special rate pool's
|
|
464
464
|
// writing down rate, which only the Self Employed schedule keeps
|
|
465
|
-
// (Fixedassets.xlsx Schedule!AC4 reads it).
|
|
465
|
+
// (Fixedassets.xlsx Schedule!AC4 reads it). G9 and G10 are the Structures
|
|
466
|
+
// and Buildings Allowance rates, which Fixedassets.xlsx Schedule's SBA
|
|
467
|
+
// block reads across the link ($G$9 and $G$10).
|
|
466
468
|
numericEdits.G4 = ca.annual_investment_allowance;
|
|
467
469
|
numericEdits.G5 = ca.writing_down_allowance;
|
|
468
470
|
numericEdits.G6 = ca.writing_down_allowance_special;
|
|
471
|
+
numericEdits.G9 = ca.structures_and_buildings_allowance;
|
|
472
|
+
numericEdits.G10 = ca.structures_and_buildings_allowance_enhanced;
|
|
469
473
|
|
|
470
474
|
// Depreciation — same as BST
|
|
471
475
|
numericEdits.G13 = dep.land_and_property;
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
|
|
13
13
|
export const PROVENANCE_DATA = {
|
|
14
14
|
formatVersion: "diya-gl/1",
|
|
15
|
-
engineVersion: "1.2.
|
|
16
|
-
taxDataHash: "
|
|
15
|
+
engineVersion: "1.2.17+67e3da11",
|
|
16
|
+
taxDataHash: "3221a7c2f39c",
|
|
17
17
|
reconciledCommit: "54e8731a91279975e61b1a232fbb67fda89515f0",
|
|
18
18
|
templates: {
|
|
19
19
|
bst: {
|
|
@@ -25,8 +25,8 @@ export const PROVENANCE_DATA = {
|
|
|
25
25
|
scorecard: "686 passed, 0 warnings, 0 failed",
|
|
26
26
|
},
|
|
27
27
|
se: {
|
|
28
|
-
hash: "
|
|
29
|
-
scorecard: "
|
|
28
|
+
hash: "107ff1b5c94a",
|
|
29
|
+
scorecard: "7969 passed, 0 warnings, 0 failed",
|
|
30
30
|
},
|
|
31
31
|
ltd: {
|
|
32
32
|
hash: "caa14632083b",
|
|
@@ -1159,6 +1159,26 @@ export function formatScenarioToml(metadata, grouped, expected) {
|
|
|
1159
1159
|
parts.push("");
|
|
1160
1160
|
}
|
|
1161
1161
|
|
|
1162
|
+
// Structures and Buildings Allowance claims (boxes 53 and 53.1), the
|
|
1163
|
+
// book's own two arrays merged with an enhanced flag the way
|
|
1164
|
+
// diyaGlToScenario merges them. The Schedule's SBA block computes the
|
|
1165
|
+
// year's allowance from these inputs; no amount is stated here.
|
|
1166
|
+
if (expected.sba_claims) {
|
|
1167
|
+
for (const claim of expected.sba_claims) {
|
|
1168
|
+
parts.push("[[sba_claims]]");
|
|
1169
|
+
parts.push(`qualifyingDate = ${claim.qualifyingDate}`);
|
|
1170
|
+
parts.push(`qualifyingAmountExpenditure = ${claim.qualifyingAmountExpenditure}`);
|
|
1171
|
+
if (claim.ceasedDate) parts.push(`ceasedDate = ${claim.ceasedDate}`);
|
|
1172
|
+
if (claim.enhanced) parts.push(`enhanced = true`);
|
|
1173
|
+
parts.push("");
|
|
1174
|
+
parts.push("[sba_claims.building]");
|
|
1175
|
+
if (claim.building?.name) parts.push(`name = "${escapeTomlString(claim.building.name)}"`);
|
|
1176
|
+
if (claim.building?.number) parts.push(`number = "${escapeTomlString(claim.building.number)}"`);
|
|
1177
|
+
parts.push(`postcode = "${escapeTomlString(claim.building.postcode)}"`);
|
|
1178
|
+
parts.push("");
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1181
|
+
|
|
1162
1182
|
// Charges and debentures registered over the company's assets (Ltd). Each
|
|
1163
1183
|
// one secures a creditor falling due after more than one year.
|
|
1164
1184
|
if (expected.charges) {
|
|
@@ -1703,15 +1703,22 @@ const SE_DISALLOWABLE_PERCENT_CELLS = {
|
|
|
1703
1703
|
// se.js writes from ANNUAL_ALLOWANCE_CELLS and ANNUAL_ADJUSTMENT_CELLS, and
|
|
1704
1704
|
// the Business Details cell both returns read box 60 from.
|
|
1705
1705
|
const SE_ANNUAL_ALLOWANCE_CELLS = {
|
|
1706
|
-
zeroEmissionsGoodsVehicleAllowance: "
|
|
1707
|
-
zeroEmissionsCarAllowance: "
|
|
1708
|
-
structuredBuildingAllowance: "D160",
|
|
1706
|
+
zeroEmissionsGoodsVehicleAllowance: "D150",
|
|
1707
|
+
zeroEmissionsCarAllowance: "D152",
|
|
1709
1708
|
electricChargePointAllowance: "O139",
|
|
1710
1709
|
};
|
|
1711
1710
|
const SE_ANNUAL_ADJUSTMENT_CELLS = {
|
|
1712
1711
|
includedNonTaxableProfits: "D179",
|
|
1713
1712
|
accountingAdjustment: "D210",
|
|
1714
1713
|
};
|
|
1714
|
+
|
|
1715
|
+
// Fixedassets.xlsx!Schedule rows 115 to 119, the Structures and Buildings
|
|
1716
|
+
// Allowance claims below the register (SA103F boxes 53 and 53.1); the same
|
|
1717
|
+
// rows and columns app/products/se.js writes from SBA_CLAIM_ROWS and
|
|
1718
|
+
// SBA_CLAIM_COLUMNS. E above nil is a claim; G = "F" puts it in the
|
|
1719
|
+
// enhanced (Freeport or Investment Zone) array, otherwise the standard one.
|
|
1720
|
+
const SCHEDULE_SBA_CLAIM_ROWS = [115, 116, 117, 118, 119];
|
|
1721
|
+
const SCHEDULE_SBA_ENHANCED_MARKER = "F";
|
|
1715
1722
|
const SE_GOODS_FOR_OWN_USE_CELL = "O50";
|
|
1716
1723
|
|
|
1717
1724
|
const ENTITY_CELLS = {
|
|
@@ -2568,6 +2575,31 @@ export async function extractBook(set, product, lines, cellMap, options = {}) {
|
|
|
2568
2575
|
const allowances = readStated(seFull, SE_ANNUAL_ALLOWANCE_CELLS);
|
|
2569
2576
|
const adjustments = readStated(seFull, SE_ANNUAL_ADJUSTMENT_CELLS);
|
|
2570
2577
|
if (entitySheet) Object.assign(adjustments, readStated(entitySheet, { goodsAndServicesOwnUse: SE_GOODS_FOR_OWN_USE_CELL }));
|
|
2578
|
+
// The Structures and Buildings Allowance claims (boxes 53 and 53.1)
|
|
2579
|
+
// are not stated on SE Full: the Schedule's own claim rows carry them.
|
|
2580
|
+
const scheduleForSba = await scheduleSheet(set);
|
|
2581
|
+
if (scheduleForSba) {
|
|
2582
|
+
const { xml: sbaXml, sharedStrings: sbaStrings } = scheduleForSba;
|
|
2583
|
+
const structuredBuildingAllowance = [];
|
|
2584
|
+
const enhancedStructuredBuildingAllowance = [];
|
|
2585
|
+
for (const row of SCHEDULE_SBA_CLAIM_ROWS) {
|
|
2586
|
+
const qualifyingAmountExpenditure = numberAt(sbaXml, `E${row}`, sbaStrings);
|
|
2587
|
+
if (qualifyingAmountExpenditure === undefined || qualifyingAmountExpenditure === 0) continue;
|
|
2588
|
+
const claim = { qualifyingAmountExpenditure };
|
|
2589
|
+
assign(claim, "qualifyingDate", dateAt(sbaXml, `B${row}`, sbaStrings));
|
|
2590
|
+
assign(claim, "ceasedDate", dateAt(sbaXml, `I${row}`, sbaStrings));
|
|
2591
|
+
const building = {};
|
|
2592
|
+
assign(building, "name", textAt(sbaXml, `C${row}`, sbaStrings));
|
|
2593
|
+
assign(building, "number", textAt(sbaXml, `D${row}`, sbaStrings));
|
|
2594
|
+
assign(building, "postcode", textAt(sbaXml, `F${row}`, sbaStrings));
|
|
2595
|
+
claim.building = building;
|
|
2596
|
+
const enhanced = textAt(sbaXml, `G${row}`, sbaStrings) === SCHEDULE_SBA_ENHANCED_MARKER;
|
|
2597
|
+
(enhanced ? enhancedStructuredBuildingAllowance : structuredBuildingAllowance).push(claim);
|
|
2598
|
+
}
|
|
2599
|
+
if (structuredBuildingAllowance.length > 0) allowances.structuredBuildingAllowance = structuredBuildingAllowance;
|
|
2600
|
+
if (enhancedStructuredBuildingAllowance.length > 0)
|
|
2601
|
+
allowances.enhancedStructuredBuildingAllowance = enhancedStructuredBuildingAllowance;
|
|
2602
|
+
}
|
|
2571
2603
|
if (Object.keys(allowances).length > 0) selfEmployment.allowances = allowances;
|
|
2572
2604
|
if (Object.keys(adjustments).length > 0) selfEmployment.adjustments = adjustments;
|
|
2573
2605
|
}
|
package/dist/app/products/se.js
CHANGED
|
@@ -229,17 +229,18 @@ export const DISALLOWABLE_PERCENT_CELLS = {
|
|
|
229
229
|
|
|
230
230
|
// The SA103F boxes the trader states by hand, keyed by HMRC's own API field
|
|
231
231
|
// names. Verified against the template: SE Full!O154 (box 57) reads
|
|
232
|
-
// D139+D144+D147+D152+D156+D160+O139+O144+O149, so every allowance cell
|
|
233
|
-
// is a term of the total; O169 (box 63) reads O154+D179; O194 (box 73)
|
|
234
|
-
// D219 (box 77) each floor the working sheet's one figure,
|
|
232
|
+
// D139+D144+D147+D150+D152+D156+D160+O139+O144+O149, so every allowance cell
|
|
233
|
+
// here is a term of the total; O169 (box 63) reads O154+D179; O194 (box 73)
|
|
234
|
+
// and D219 (box 77) each floor the working sheet's one figure,
|
|
235
235
|
// O174-O179+N(D197)+D210+N(O190), at nil from its own side. Box 54's caption
|
|
236
236
|
// at N136 is "Electric charge-point allowance" (L136 = 54); box 55's cell
|
|
237
237
|
// O144 is the small pools formula, so the enhanced-allowance figure has no
|
|
238
|
-
// input cell of its own.
|
|
238
|
+
// input cell of its own. Boxes 53 and 53.1 (D156, D160) are not stated here:
|
|
239
|
+
// the Schedule's SBA block computes them from scenario.sba_claims, so they
|
|
240
|
+
// carry no entry in this table.
|
|
239
241
|
export const ANNUAL_ALLOWANCE_CELLS = {
|
|
240
|
-
zeroEmissionsGoodsVehicleAllowance: "
|
|
241
|
-
zeroEmissionsCarAllowance: "
|
|
242
|
-
structuredBuildingAllowance: "D160",
|
|
242
|
+
zeroEmissionsGoodsVehicleAllowance: "D150",
|
|
243
|
+
zeroEmissionsCarAllowance: "D152",
|
|
243
244
|
electricChargePointAllowance: "O139",
|
|
244
245
|
};
|
|
245
246
|
export const ANNUAL_ADJUSTMENT_CELLS = {
|
|
@@ -289,6 +290,28 @@ export const SINGLE_ASSET_POOL_MARKER_COLUMN = "AD";
|
|
|
289
290
|
export const SINGLE_ASSET_POOL_MARKER = "P";
|
|
290
291
|
export const PRIVATE_USE_COLUMN = "M";
|
|
291
292
|
|
|
293
|
+
// Structures and Buildings Allowance claims, Fixedassets.xlsx Schedule rows
|
|
294
|
+
// 115 to 119, below the register (SA103F boxes 53 and 53.1). Written left
|
|
295
|
+
// to right: B the date first in qualifying use, C the building name, D its
|
|
296
|
+
// number, E the qualifying expenditure, F the postcode, G "F" for a Freeport
|
|
297
|
+
// or Investment Zone tax site, I the date qualifying use ceased. H (the
|
|
298
|
+
// year's rate), J (days claimed) and K (the year's allowance) are the
|
|
299
|
+
// sheet's own formulas. Verified against the template: H115 =
|
|
300
|
+
// IF(E115>0,IF(G115="F",[1]Admin!$G$10,[1]Admin!$G$9)," "), K120 =
|
|
301
|
+
// SUMIF(G115:G119,"<>F",K115:K119) (box 53), K121 the same with "F"
|
|
302
|
+
// (box 53.1).
|
|
303
|
+
export const SBA_CLAIM_ROWS = [115, 116, 117, 118, 119];
|
|
304
|
+
export const SBA_CLAIM_COLUMNS = {
|
|
305
|
+
qualifyingDate: "B",
|
|
306
|
+
name: "C",
|
|
307
|
+
number: "D",
|
|
308
|
+
qualifyingAmountExpenditure: "E",
|
|
309
|
+
postcode: "F",
|
|
310
|
+
enhanced: "G",
|
|
311
|
+
ceasedDate: "I",
|
|
312
|
+
};
|
|
313
|
+
export const SBA_ENHANCED_MARKER = "F";
|
|
314
|
+
|
|
292
315
|
// Hire purchase agreements (Fixedassets.xlsx HPfinance sheet). Only two
|
|
293
316
|
// rows are available for scenario agreements before the sheet's own
|
|
294
317
|
// layout runs out: row 8 (the "New" block's working master, whose
|
|
@@ -764,6 +787,45 @@ function composeWrites(scenario, targetStartYear) {
|
|
|
764
787
|
});
|
|
765
788
|
}
|
|
766
789
|
|
|
790
|
+
// Structures and Buildings Allowance claims (SA103F boxes 53 and 53.1).
|
|
791
|
+
if (scenario.sba_claims) {
|
|
792
|
+
if (!fixedAssetsWrites.Schedule) fixedAssetsWrites.Schedule = {};
|
|
793
|
+
const fa = fixedAssetsWrites.Schedule;
|
|
794
|
+
for (const claim of scenario.sba_claims.slice(SBA_CLAIM_ROWS.length)) {
|
|
795
|
+
skips.push(
|
|
796
|
+
skipped(
|
|
797
|
+
"structuresBuildingsAllowanceClaim",
|
|
798
|
+
{ date: claim.qualifyingDate, code: claim.enhanced ? "enhanced" : "standard", amount: claim.qualifyingAmountExpenditure },
|
|
799
|
+
`the Schedule holds ${SBA_CLAIM_ROWS.length} Structures and Buildings Allowance claims`,
|
|
800
|
+
),
|
|
801
|
+
);
|
|
802
|
+
}
|
|
803
|
+
scenario.sba_claims.slice(0, SBA_CLAIM_ROWS.length).forEach((claim, i) => {
|
|
804
|
+
const row = SBA_CLAIM_ROWS[i];
|
|
805
|
+
const qualifyingDate = shiftDate(parseDate(claim.qualifyingDate));
|
|
806
|
+
// Left to right: B, C, D, E, F, G, I -- see the opening asset writer
|
|
807
|
+
// above for why the order matters. H and J are the sheet's formulas.
|
|
808
|
+
fa[`${SBA_CLAIM_COLUMNS.qualifyingDate}${row}`] = toExcelSerial(
|
|
809
|
+
qualifyingDate.getUTCFullYear(),
|
|
810
|
+
qualifyingDate.getUTCMonth() + 1,
|
|
811
|
+
qualifyingDate.getUTCDate(),
|
|
812
|
+
);
|
|
813
|
+
if (claim.building?.name) fa[`${SBA_CLAIM_COLUMNS.name}${row}`] = claim.building.name;
|
|
814
|
+
if (claim.building?.number) fa[`${SBA_CLAIM_COLUMNS.number}${row}`] = claim.building.number;
|
|
815
|
+
fa[`${SBA_CLAIM_COLUMNS.qualifyingAmountExpenditure}${row}`] = claim.qualifyingAmountExpenditure;
|
|
816
|
+
fa[`${SBA_CLAIM_COLUMNS.postcode}${row}`] = claim.building.postcode;
|
|
817
|
+
if (claim.enhanced) fa[`${SBA_CLAIM_COLUMNS.enhanced}${row}`] = SBA_ENHANCED_MARKER;
|
|
818
|
+
if (claim.ceasedDate) {
|
|
819
|
+
const ceasedDate = shiftDate(parseDate(claim.ceasedDate));
|
|
820
|
+
fa[`${SBA_CLAIM_COLUMNS.ceasedDate}${row}`] = toExcelSerial(
|
|
821
|
+
ceasedDate.getUTCFullYear(),
|
|
822
|
+
ceasedDate.getUTCMonth() + 1,
|
|
823
|
+
ceasedDate.getUTCDate(),
|
|
824
|
+
);
|
|
825
|
+
}
|
|
826
|
+
});
|
|
827
|
+
}
|
|
828
|
+
|
|
767
829
|
if (scenario.hp_agreements) {
|
|
768
830
|
if (!fixedAssetsWrites.HPfinance) fixedAssetsWrites.HPfinance = {};
|
|
769
831
|
const hp = fixedAssetsWrites.HPfinance;
|
|
@@ -1042,9 +1104,10 @@ export const CELL_MAP = [
|
|
|
1042
1104
|
["SE Full", "D139", "Annual investment allowance (box 49)", "tax.capitalAllowances.aia (sa103f)", "Self Assessment (SA103F)", 1],
|
|
1043
1105
|
["SE Full", "D144", "Capital allowances at 18% (box 50)", "tax.capitalAllowances.wda (sa103f)", "Self Assessment (SA103F)", 1],
|
|
1044
1106
|
["SE Full", "D147", "Capital allowances at 6% (box 51)", "tax.capitalAllowances.specialRateWDA (sa103f)", "Self Assessment (SA103F)", 1],
|
|
1045
|
-
["SE Full", "
|
|
1046
|
-
["SE Full", "
|
|
1047
|
-
["SE Full", "
|
|
1107
|
+
["SE Full", "D150", "Zero-emission goods vehicle allowance (box 52)", "tax.selfEmployment.allowances.zeroEmissionsGoodsVehicleAllowance", "Self Assessment (SA103F)", 1],
|
|
1108
|
+
["SE Full", "D152", "Zero-emission car allowance (box 52.1)", "tax.selfEmployment.allowances.zeroEmissionsCarAllowance", "Self Assessment (SA103F)", 1],
|
|
1109
|
+
["SE Full", "D156", "Structures and Buildings Allowance (box 53)", "tax.capitalAllowances.structuresAndBuildingsAllowance (sa103f)", "Self Assessment (SA103F)", 1],
|
|
1110
|
+
["SE Full", "D160", "Freeport and Investment Zones Structures and Buildings Allowance (box 53.1)", "tax.capitalAllowances.structuresAndBuildingsAllowanceEnhanced (sa103f)", "Self Assessment (SA103F)", 1],
|
|
1048
1111
|
["SE Full", "O139", "Electric charge-point allowance (box 54)", "tax.selfEmployment.allowances.electricChargePointAllowance", "Self Assessment (SA103F)", 1],
|
|
1049
1112
|
["SE Full", "O144", "100% and other enhanced capital allowances (box 55)", "tax.capitalAllowances.enhanced (sa103f)", "Self Assessment (SA103F)", 1],
|
|
1050
1113
|
["SE Full", "O149", "Allowances on sale or cessation (box 56)", "tax.capitalAllowances.balancingAllowance (sa103f)", "Self Assessment (SA103F)", 1],
|
|
@@ -1118,6 +1181,8 @@ export const CELL_MAP = [
|
|
|
1118
1181
|
["Admin", "G4", "Annual Investment Allowance Rate", "", "Admin (Generator Injected)", 0],
|
|
1119
1182
|
["Admin", "G5", "Writing Down Allowance Rate", "tax.capitalAllowances.mainRateWDA", "Admin (Generator Injected)", 0],
|
|
1120
1183
|
["Admin", "G6", "Special Rate Writing Down Allowance Rate", "tax.capitalAllowances.specialRateWDA", "Admin (Generator Injected)", 0],
|
|
1184
|
+
["Admin", "G9", "Structures and Buildings Allowance Rate", "tax.capitalAllowances.structuresAndBuildingsAllowance", "Admin (Generator Injected)", 0],
|
|
1185
|
+
["Admin", "G10", "Freeport and Investment Zone SBA Rate", "tax.capitalAllowances.structuresAndBuildingsAllowanceEnhanced", "Admin (Generator Injected)", 0],
|
|
1121
1186
|
["Admin", "F21", "Mileage Higher Rate Limit", "", "Admin (Generator Injected)", 0],
|
|
1122
1187
|
["Admin", "G21", "Mileage Higher Rate Pence", "tax.mileage.carFirst10000", "Admin (Generator Injected)", 0],
|
|
1123
1188
|
["Admin", "F22", "Mileage Lower Rate Start", "", "Admin (Generator Injected)", 0],
|
|
@@ -1281,7 +1346,9 @@ export function multiFileOptions() {
|
|
|
1281
1346
|
// pooled written-down value by rate pool, which the small pools test
|
|
1282
1347
|
// now runs over per pool; M40, AD40, AE40 and AG40 are the fixture's
|
|
1283
1348
|
// marked car row (van 38, estate car 39, hatchback 40), read so its
|
|
1284
|
-
// marker and private use share are proved on the row itself.
|
|
1349
|
+
// marker and private use share are proved on the row itself. B115 to
|
|
1350
|
+
// K116 are the fixture's two SBA claim rows; K120 and K121 the SBA
|
|
1351
|
+
// block's box 53 and box 53.1 totals.
|
|
1285
1352
|
Schedule: [
|
|
1286
1353
|
"E1",
|
|
1287
1354
|
"F1",
|
|
@@ -1310,6 +1377,23 @@ export function multiFileOptions() {
|
|
|
1310
1377
|
"AD40",
|
|
1311
1378
|
"AE40",
|
|
1312
1379
|
"AG40",
|
|
1380
|
+
"B115",
|
|
1381
|
+
"C115",
|
|
1382
|
+
"E115",
|
|
1383
|
+
"F115",
|
|
1384
|
+
"H115",
|
|
1385
|
+
"J115",
|
|
1386
|
+
"K115",
|
|
1387
|
+
"B116",
|
|
1388
|
+
"D116",
|
|
1389
|
+
"E116",
|
|
1390
|
+
"F116",
|
|
1391
|
+
"G116",
|
|
1392
|
+
"H116",
|
|
1393
|
+
"J116",
|
|
1394
|
+
"K116",
|
|
1395
|
+
"K120",
|
|
1396
|
+
"K121",
|
|
1313
1397
|
],
|
|
1314
1398
|
FAreconciliation: ["E11", "E13", "E15", "K11", "K13", "K15"],
|
|
1315
1399
|
// E2 is the long-term-creditors total for the "New Hire Purchase
|
|
@@ -1714,6 +1798,23 @@ const FIXED_ASSET_CELL_LABELS = {
|
|
|
1714
1798
|
AG40: "Single asset pool tax written down value on the third motor vehicle brought forward",
|
|
1715
1799
|
E57: "Cost of the assets owned at the start of the year",
|
|
1716
1800
|
E110: "Cost of the assets bought during the year",
|
|
1801
|
+
B115: "Date first in qualifying use, the fixture's standard-rate SBA claim",
|
|
1802
|
+
C115: "Building name, the fixture's standard-rate SBA claim",
|
|
1803
|
+
E115: "Qualifying expenditure, the fixture's standard-rate SBA claim",
|
|
1804
|
+
F115: "Postcode, the fixture's standard-rate SBA claim",
|
|
1805
|
+
H115: "Structures and Buildings Allowance rate applied to the standard-rate claim",
|
|
1806
|
+
J115: "Days claimed this year, the fixture's standard-rate SBA claim",
|
|
1807
|
+
K115: "Structures and Buildings Allowance claimed this year, the fixture's standard-rate claim",
|
|
1808
|
+
B116: "Date first in qualifying use, the fixture's Freeport SBA claim",
|
|
1809
|
+
D116: "Building number, the fixture's Freeport SBA claim",
|
|
1810
|
+
E116: "Qualifying expenditure, the fixture's Freeport SBA claim",
|
|
1811
|
+
F116: "Postcode, the fixture's Freeport SBA claim",
|
|
1812
|
+
G116: "Tax site marker, the fixture's Freeport SBA claim (F)",
|
|
1813
|
+
H116: "Structures and Buildings Allowance rate applied to the Freeport claim",
|
|
1814
|
+
J116: "Days claimed this year, the fixture's Freeport SBA claim",
|
|
1815
|
+
K116: "Structures and Buildings Allowance claimed this year, the fixture's Freeport claim",
|
|
1816
|
+
K120: "Structures and Buildings Allowance (SA103F box 53), the non-Freeport claims summed",
|
|
1817
|
+
K121: "Freeport and Investment Zone Structures and Buildings Allowance (SA103F box 53.1), the Freeport claims summed",
|
|
1717
1818
|
},
|
|
1718
1819
|
"Fixedassets.xlsx!FAreconciliation": {
|
|
1719
1820
|
E11: "Additions the schedule lists, net of VAT",
|
|
@@ -1746,6 +1847,9 @@ const ADMIN_RATE_CELLS = new Set([
|
|
|
1746
1847
|
"L23",
|
|
1747
1848
|
"G4",
|
|
1748
1849
|
"G5",
|
|
1850
|
+
"G6",
|
|
1851
|
+
"G9",
|
|
1852
|
+
"G10",
|
|
1749
1853
|
"G13",
|
|
1750
1854
|
"G14",
|
|
1751
1855
|
"G15",
|
|
@@ -1898,9 +2002,14 @@ export function profitBridge(results) {
|
|
|
1898
2002
|
{ label: "Less other capital allowances (box 25)", cell: "SE Short!O80", value: -num(seShort.O80) },
|
|
1899
2003
|
{ label: "Add balancing charges (box 26)", cell: "SE Short!O85", value: num(seShort.O85) },
|
|
1900
2004
|
{ label: "Add goods and services for own use (box 27)", cell: "SE Short!D94", value: num(seShort.D94) },
|
|
1901
|
-
{ label: "Less the full return's own zero-emission goods vehicle allowance (box 52)", cell: "SE Full!
|
|
1902
|
-
{ label: "Less the full return's own zero-emission car allowance (box 52.1)", cell: "SE Full!
|
|
1903
|
-
{ label: "Less the full return's own Structures and Buildings Allowance (box 53)", cell: "SE Full!
|
|
2005
|
+
{ label: "Less the full return's own zero-emission goods vehicle allowance (box 52)", cell: "SE Full!D150", value: -num(seFull?.D150) },
|
|
2006
|
+
{ label: "Less the full return's own zero-emission car allowance (box 52.1)", cell: "SE Full!D152", value: -num(seFull?.D152) },
|
|
2007
|
+
{ label: "Less the full return's own Structures and Buildings Allowance (box 53)", cell: "SE Full!D156", value: -num(seFull?.D156) },
|
|
2008
|
+
{
|
|
2009
|
+
label: "Less the full return's own Freeport and Investment Zone Structures and Buildings Allowance (box 53.1)",
|
|
2010
|
+
cell: "SE Full!D160",
|
|
2011
|
+
value: -num(seFull?.D160),
|
|
2012
|
+
},
|
|
1904
2013
|
{ label: "Less the full return's own electric charge-point allowance (box 54)", cell: "SE Full!O139", value: -num(seFull?.O139) },
|
|
1905
2014
|
{ label: "Less the full return's own box 62 adjustment", cell: "SE Full!D179", value: -num(seFull?.D179) },
|
|
1906
2015
|
{
|
|
@@ -1975,6 +2084,40 @@ function fixtureSmallPools(expected, taxData, rate) {
|
|
|
1975
2084
|
return { ...pools, writeOff: writeOff(pools.main) + writeOff(pools.special) };
|
|
1976
2085
|
}
|
|
1977
2086
|
|
|
2087
|
+
// SA103F boxes 53 and 53.1 the way Fixedassets.xlsx!Schedule!K120 and K121
|
|
2088
|
+
// state them (Structures and Buildings Allowance), from the fixture's own
|
|
2089
|
+
// claims rather than from the sheet: each claim's expenditure at its own
|
|
2090
|
+
// year's rate (standard or the enhanced Freeport/Investment Zone rate),
|
|
2091
|
+
// over the days of the chargeable period it covers -- the later of the
|
|
2092
|
+
// period's own start and the claim's qualifying date, to the earlier of the
|
|
2093
|
+
// period's end, the claim's ceased date and the 33 1/3 (or 10) year limit.
|
|
2094
|
+
const EXCEL_EPOCH_MS = Date.UTC(1899, 11, 30);
|
|
2095
|
+
function toExcelSerialDate(date) {
|
|
2096
|
+
return Math.round((date.getTime() - EXCEL_EPOCH_MS) / 86400000);
|
|
2097
|
+
}
|
|
2098
|
+
function fixtureStructuresAndBuildings(expected, taxData, periodStartSerial, periodEndSerial, shiftDate) {
|
|
2099
|
+
const rateStandard = taxData.capital_allowances.structures_and_buildings_allowance ?? 0;
|
|
2100
|
+
const rateEnhanced = taxData.capital_allowances.structures_and_buildings_allowance_enhanced ?? 0;
|
|
2101
|
+
const periodDays = periodEndSerial - periodStartSerial + 1;
|
|
2102
|
+
let box53 = 0;
|
|
2103
|
+
let box53_1 = 0;
|
|
2104
|
+
for (const claim of expected.sba_claims || []) {
|
|
2105
|
+
const enhanced = claim.enhanced === true;
|
|
2106
|
+
const qualifyingDate = shiftDate(parseDate(claim.qualifyingDate));
|
|
2107
|
+
const qualifyingSerial = toExcelSerialDate(qualifyingDate);
|
|
2108
|
+
const rate = enhanced ? rateEnhanced : rateStandard;
|
|
2109
|
+
const limitMonths = enhanced ? 120 : 400;
|
|
2110
|
+
let upperBound = Math.min(periodEndSerial, toExcelSerialDate(shiftMonths(qualifyingDate, limitMonths)) - 1);
|
|
2111
|
+
if (claim.ceasedDate) upperBound = Math.min(upperBound, toExcelSerialDate(shiftDate(parseDate(claim.ceasedDate))));
|
|
2112
|
+
const lowerBound = Math.max(periodStartSerial, qualifyingSerial);
|
|
2113
|
+
const days = Math.max(0, upperBound - lowerBound + 1);
|
|
2114
|
+
const allowance = (claim.qualifyingAmountExpenditure * rate * days) / periodDays;
|
|
2115
|
+
if (enhanced) box53_1 += allowance;
|
|
2116
|
+
else box53 += allowance;
|
|
2117
|
+
}
|
|
2118
|
+
return { box53, box53_1 };
|
|
2119
|
+
}
|
|
2120
|
+
|
|
1978
2121
|
// ── Journal category VAT netting ───────────────────────────────────────────
|
|
1979
2122
|
|
|
1980
2123
|
// A journal row takes its own VAT off its own gross and rounds nothing
|
|
@@ -2399,14 +2542,21 @@ export function checkCompliance(results, expected, taxData, calculateExpectedTax
|
|
|
2399
2542
|
);
|
|
2400
2543
|
// Income Tax!E5 reads 'SE Full'!O210, so the short return's box 31
|
|
2401
2544
|
// reaches it only through the full return: the two agree exactly when
|
|
2402
|
-
// no box the trader states on SE Full alone (52, 52.1, 53,
|
|
2403
|
-
// 71) carries a figure, and stand apart by those
|
|
2545
|
+
// no box the trader states or claims on SE Full alone (52, 52.1, 53,
|
|
2546
|
+
// 53.1, 54, 62 and 71) carries a figure, and stand apart by those
|
|
2547
|
+
// figures otherwise.
|
|
2404
2548
|
const fullOnly = results["SE Full"] || {};
|
|
2405
2549
|
const fullReturnOnlyBoxes =
|
|
2406
|
-
num(fullOnly.
|
|
2550
|
+
num(fullOnly.D150) +
|
|
2551
|
+
num(fullOnly.D152) +
|
|
2552
|
+
num(fullOnly.D156) +
|
|
2553
|
+
num(fullOnly.D160) +
|
|
2554
|
+
num(fullOnly.O139) +
|
|
2555
|
+
num(fullOnly.D179) -
|
|
2556
|
+
num(fullOnly.D210);
|
|
2407
2557
|
if (seShort.D106) {
|
|
2408
2558
|
check(
|
|
2409
|
-
"SA103S: Profit for tax (D106) less the SE Full-only boxes 52, 52.1, 53, 54 and 62 plus box 71 = Income Tax E5",
|
|
2559
|
+
"SA103S: Profit for tax (D106) less the SE Full-only boxes 52, 52.1, 53, 53.1, 54 and 62 plus box 71 = Income Tax E5",
|
|
2410
2560
|
Math.max(0, num(seShort.D106) - fullReturnOnlyBoxes),
|
|
2411
2561
|
tax.E5,
|
|
2412
2562
|
);
|
|
@@ -2602,6 +2752,7 @@ export function checkCompliance(results, expected, taxData, calculateExpectedTax
|
|
|
2602
2752
|
num(seFull.D139) +
|
|
2603
2753
|
num(seFull.D144) +
|
|
2604
2754
|
num(seFull.D147) +
|
|
2755
|
+
num(seFull.D150) +
|
|
2605
2756
|
num(seFull.D152) +
|
|
2606
2757
|
num(seFull.D156) +
|
|
2607
2758
|
num(seFull.D160) +
|
|
@@ -2667,6 +2818,12 @@ export function checkCompliance(results, expected, taxData, calculateExpectedTax
|
|
|
2667
2818
|
);
|
|
2668
2819
|
check("SA103F box 56 allowances on sale or cessation (O149) = Schedule Y1", num(seFull.O149), num(returnSchedule.Y1));
|
|
2669
2820
|
check("SA103F box 59 balancing charge (O160) = Schedule Z1", num(seFull.O160), num(returnSchedule.Z1));
|
|
2821
|
+
check("SA103F box 53 Structures and Buildings Allowance (D156) = Schedule K120", num(seFull.D156), num(returnSchedule.K120));
|
|
2822
|
+
check(
|
|
2823
|
+
"SA103F box 53.1 Freeport and Investment Zone Structures and Buildings Allowance (D160) = Schedule K121",
|
|
2824
|
+
num(seFull.D160),
|
|
2825
|
+
num(returnSchedule.K121),
|
|
2826
|
+
);
|
|
2670
2827
|
}
|
|
2671
2828
|
|
|
2672
2829
|
// Box 50 against the scenario's own assets and the year's own rate,
|
|
@@ -2709,9 +2866,8 @@ export function checkCompliance(results, expected, taxData, calculateExpectedTax
|
|
|
2709
2866
|
const statedAllowances = expected.annual_allowances || {};
|
|
2710
2867
|
const statedAdjustments = expected.annual_adjustments || {};
|
|
2711
2868
|
const annualBoxes = [
|
|
2712
|
-
["52", "zero-emission goods vehicle allowance", "
|
|
2713
|
-
["52.1", "zero-emission car allowance", "
|
|
2714
|
-
["53", "Structures and Buildings Allowance", "D160", statedAllowances.structuredBuildingAllowance],
|
|
2869
|
+
["52", "zero-emission goods vehicle allowance", "D150", statedAllowances.zeroEmissionsGoodsVehicleAllowance],
|
|
2870
|
+
["52.1", "zero-emission car allowance", "D152", statedAllowances.zeroEmissionsCarAllowance],
|
|
2715
2871
|
["54", "electric charge-point allowance", "O139", statedAllowances.electricChargePointAllowance],
|
|
2716
2872
|
["62", "income included but not taxable as business profits", "D179", statedAdjustments.includedNonTaxableProfits],
|
|
2717
2873
|
["71", "adjustment for change of accounting practice", "D210", statedAdjustments.accountingAdjustment],
|
|
@@ -2719,6 +2875,24 @@ export function checkCompliance(results, expected, taxData, calculateExpectedTax
|
|
|
2719
2875
|
for (const [box, caption, cell, stated] of annualBoxes) {
|
|
2720
2876
|
check(`SA103F box ${box} ${caption} (${cell}) = the figure the book states`, num(seFull[cell]), stated || 0);
|
|
2721
2877
|
}
|
|
2878
|
+
// Boxes 53 and 53.1 are not stated: the Schedule's SBA block computes
|
|
2879
|
+
// them from the fixture's own claims, each priced at its own rate over
|
|
2880
|
+
// the days it covers within the package's period. Only when a rate
|
|
2881
|
+
// year's own tax data is in hand -- some callers check an isolated
|
|
2882
|
+
// cell with none, and the rate is what fixes the fixture's own figure.
|
|
2883
|
+
if (taxData?.capital_allowances) {
|
|
2884
|
+
const sba = fixtureStructuresAndBuildings(expected, taxData, num(seFull.Q2), num(seFull.V2), shiftDate);
|
|
2885
|
+
check(
|
|
2886
|
+
"SA103F box 53 Structures and Buildings Allowance (D156) = the fixture's own claims at the year's rate",
|
|
2887
|
+
num(seFull.D156),
|
|
2888
|
+
sba.box53,
|
|
2889
|
+
);
|
|
2890
|
+
check(
|
|
2891
|
+
"SA103F box 53.1 Freeport and Investment Zone Structures and Buildings Allowance (D160) = the fixture's own claims at the year's enhanced rate",
|
|
2892
|
+
num(seFull.D160),
|
|
2893
|
+
sba.box53_1,
|
|
2894
|
+
);
|
|
2895
|
+
}
|
|
2722
2896
|
const ownUseStated = statedAdjustments.goodsAndServicesOwnUse || 0;
|
|
2723
2897
|
check(
|
|
2724
2898
|
"SA103F box 60 goods and services for own use (D169) = the figure the book states on Business Details!O50",
|
|
@@ -2736,8 +2910,15 @@ export function checkCompliance(results, expected, taxData, calculateExpectedTax
|
|
|
2736
2910
|
.filter(([box]) => box !== "62" && box !== "71")
|
|
2737
2911
|
.reduce((total, [, , , stated]) => total + (stated || 0), 0);
|
|
2738
2912
|
check(
|
|
2739
|
-
"SA103F box 57 total capital allowances (O154) less the schedule-fed boxes 49, 50, 51, 55 and 56 = the allowances the book states (boxes 52, 52.1
|
|
2740
|
-
num(seFull.O154) -
|
|
2913
|
+
"SA103F box 57 total capital allowances (O154) less the schedule-fed boxes 49, 50, 51, 53, 53.1, 55 and 56 = the allowances the book states (boxes 52, 52.1 and 54)",
|
|
2914
|
+
num(seFull.O154) -
|
|
2915
|
+
num(seFull.D139) -
|
|
2916
|
+
num(seFull.D144) -
|
|
2917
|
+
num(seFull.D147) -
|
|
2918
|
+
num(seFull.D156) -
|
|
2919
|
+
num(seFull.D160) -
|
|
2920
|
+
num(seFull.O144) -
|
|
2921
|
+
num(seFull.O149),
|
|
2741
2922
|
statedAllowanceTotal,
|
|
2742
2923
|
);
|
|
2743
2924
|
check(
|
|
@@ -2781,19 +2962,20 @@ export function checkCompliance(results, expected, taxData, calculateExpectedTax
|
|
|
2781
2962
|
["D231", "O124", "box 81 contractor deductions taken off"],
|
|
2782
2963
|
];
|
|
2783
2964
|
// The short return reads the fixed asset schedule and Business Details
|
|
2784
|
-
// directly, so the boxes the trader states on SE Full alone
|
|
2785
|
-
// 53, 54 and 62) never reach it: its taxable profit
|
|
2786
|
-
// the full return's by exactly those figures.
|
|
2787
|
-
const fullReturnOnlyDeductions =
|
|
2965
|
+
// directly, so the boxes the trader states or claims on SE Full alone
|
|
2966
|
+
// (52, 52.1, 53, 53.1, 54 and 62) never reach it: its taxable profit
|
|
2967
|
+
// stands higher than the full return's by exactly those figures.
|
|
2968
|
+
const fullReturnOnlyDeductions =
|
|
2969
|
+
num(seFull.D150) + num(seFull.D152) + num(seFull.D156) + num(seFull.D160) + num(seFull.O139) + num(seFull.D179);
|
|
2788
2970
|
check(
|
|
2789
|
-
"SA103F box 64 net business profit for tax purposes: full return (O174) = short return (D99) less the SE Full-only boxes 52, 52.1, 53, 54 and 62",
|
|
2971
|
+
"SA103F box 64 net business profit for tax purposes: full return (O174) = short return (D99) less the SE Full-only boxes 52, 52.1, 53, 53.1, 54 and 62",
|
|
2790
2972
|
num(seFull.O174),
|
|
2791
2973
|
Math.max(0, num(sa103s.D99) - fullReturnOnlyDeductions),
|
|
2792
2974
|
);
|
|
2793
2975
|
// Box 71 is the one SE Full-only figure that adds to the taxable
|
|
2794
2976
|
// profit; the short return has no box for it either.
|
|
2795
2977
|
check(
|
|
2796
|
-
"SA103F box 76 total taxable profits: full return (O210) = short return (D106) less the SE Full-only boxes 52, 52.1, 53, 54 and 62 plus box 71, with each return's own loss set-off",
|
|
2978
|
+
"SA103F box 76 total taxable profits: full return (O210) = short return (D106) less the SE Full-only boxes 52, 52.1, 53, 53.1, 54 and 62 plus box 71, with each return's own loss set-off",
|
|
2797
2979
|
num(seFull.O210),
|
|
2798
2980
|
Math.max(0, num(sa103s.D106) - fullReturnOnlyDeductions + num(seFull.D210) + num(sa103s.O94) - num(seFull.O199)),
|
|
2799
2981
|
);
|
|
@@ -2851,12 +3033,19 @@ export function checkCompliance(results, expected, taxData, calculateExpectedTax
|
|
|
2851
3033
|
num(sa103s.D71) - num(seFull.O122),
|
|
2852
3034
|
);
|
|
2853
3035
|
check(
|
|
2854
|
-
"SA103F box 57 total capital allowances (O154) = the short return's allowance boxes 23, 24 and 25 plus the SE Full-only boxes 52, 52.1, 53 and 54",
|
|
3036
|
+
"SA103F box 57 total capital allowances (O154) = the short return's allowance boxes 23, 24 and 25 plus the SE Full-only boxes 52, 52.1, 53, 53.1 and 54",
|
|
2855
3037
|
num(seFull.O154),
|
|
2856
|
-
num(sa103s.D80) +
|
|
3038
|
+
num(sa103s.D80) +
|
|
3039
|
+
num(sa103s.D85) +
|
|
3040
|
+
num(sa103s.O80) +
|
|
3041
|
+
num(seFull.D150) +
|
|
3042
|
+
num(seFull.D152) +
|
|
3043
|
+
num(seFull.D156) +
|
|
3044
|
+
num(seFull.D160) +
|
|
3045
|
+
num(seFull.O139),
|
|
2857
3046
|
);
|
|
2858
3047
|
check(
|
|
2859
|
-
"SA103S box 25 other capital allowances (O80) leaves out the allowances the trader states on SE Full alone (boxes 52, 52.1, 53 and 54)",
|
|
3048
|
+
"SA103S box 25 other capital allowances (O80) leaves out the allowances the trader states or claims on SE Full alone (boxes 52, 52.1, 53, 53.1 and 54)",
|
|
2860
3049
|
num(sa103s.O80),
|
|
2861
3050
|
num(seFull.O154) - num(sa103s.D80) - num(sa103s.D85),
|
|
2862
3051
|
0.01,
|
|
@@ -854,7 +854,7 @@
|
|
|
854
854
|
"properties": {
|
|
855
855
|
"allowances": {
|
|
856
856
|
"type": "object",
|
|
857
|
-
"description": "Capital allowance claims the fixed asset schedule does not compute, written to the SA103F boxes the trader would otherwise fill by hand: box 52 (zeroEmissionsGoodsVehicleAllowance, SE Full!
|
|
857
|
+
"description": "Capital allowance claims the fixed asset schedule does not compute, written to the SA103F boxes the trader would otherwise fill by hand: box 52 (zeroEmissionsGoodsVehicleAllowance, SE Full!D150), box 52.1 (zeroEmissionsCarAllowance, D152), box 53 (structuredBuildingAllowance[], the Schedule's SBA block sums into D156) and box 53.1 (enhancedStructuredBuildingAllowance[], D160) and box 54 (electricChargePointAllowance, O139). Box 57 totals them. HMRC's schema dropped the box 52 and box 54 fields from 2025-26; the sheet still totals a stated figure, and the derivation warns.",
|
|
858
858
|
"additionalProperties": false,
|
|
859
859
|
"properties": {
|
|
860
860
|
"zeroEmissionsGoodsVehicleAllowance": {
|
|
@@ -866,8 +866,12 @@
|
|
|
866
866
|
"minimum": 0
|
|
867
867
|
},
|
|
868
868
|
"structuredBuildingAllowance": {
|
|
869
|
-
"type": "
|
|
870
|
-
"
|
|
869
|
+
"type": "array",
|
|
870
|
+
"items": { "$ref": "#/$defs/structuresBuildingsAllowanceClaim" }
|
|
871
|
+
},
|
|
872
|
+
"enhancedStructuredBuildingAllowance": {
|
|
873
|
+
"type": "array",
|
|
874
|
+
"items": { "$ref": "#/$defs/structuresBuildingsAllowanceClaim" }
|
|
871
875
|
},
|
|
872
876
|
"electricChargePointAllowance": {
|
|
873
877
|
"type": "number",
|
|
@@ -979,6 +983,16 @@
|
|
|
979
983
|
"minimum": 0,
|
|
980
984
|
"maximum": 1
|
|
981
985
|
},
|
|
986
|
+
"structuresAndBuildingsAllowance": {
|
|
987
|
+
"type": "number",
|
|
988
|
+
"minimum": 0,
|
|
989
|
+
"maximum": 1
|
|
990
|
+
},
|
|
991
|
+
"structuresAndBuildingsAllowanceEnhanced": {
|
|
992
|
+
"type": "number",
|
|
993
|
+
"minimum": 0,
|
|
994
|
+
"maximum": 1
|
|
995
|
+
},
|
|
982
996
|
"firstYearAllowanceRate": {
|
|
983
997
|
"type": "number",
|
|
984
998
|
"minimum": 0,
|
|
@@ -1106,6 +1120,44 @@
|
|
|
1106
1120
|
}
|
|
1107
1121
|
}
|
|
1108
1122
|
},
|
|
1123
|
+
"structuresBuildingsAllowanceClaim": {
|
|
1124
|
+
"type": "object",
|
|
1125
|
+
"description": "One Structures and Buildings Allowance claim (CAA 2001 s.270AA onwards), SA103F boxes 53 and 53.1. The Self Employed Schedule computes the year's allowance from these inputs at the year file's rate (3%, or 10% for a Freeport or Investment Zone tax site in the enhanced array) over the days of the chargeable period the claim covers -- a stated amount is never carried here.",
|
|
1126
|
+
"required": ["qualifyingAmountExpenditure", "qualifyingDate", "building"],
|
|
1127
|
+
"additionalProperties": false,
|
|
1128
|
+
"properties": {
|
|
1129
|
+
"qualifyingDate": {
|
|
1130
|
+
"type": "string",
|
|
1131
|
+
"format": "date",
|
|
1132
|
+
"description": "The later of the building's first qualifying use and the qualifying expenditure being incurred."
|
|
1133
|
+
},
|
|
1134
|
+
"qualifyingAmountExpenditure": {
|
|
1135
|
+
"type": "number",
|
|
1136
|
+
"minimum": 0
|
|
1137
|
+
},
|
|
1138
|
+
"ceasedDate": {
|
|
1139
|
+
"type": "string",
|
|
1140
|
+
"format": "date",
|
|
1141
|
+
"description": "The day qualifying use or the claimant's relevant interest ended, when it did so within the allowance's period."
|
|
1142
|
+
},
|
|
1143
|
+
"building": {
|
|
1144
|
+
"type": "object",
|
|
1145
|
+
"required": ["postcode"],
|
|
1146
|
+
"additionalProperties": false,
|
|
1147
|
+
"properties": {
|
|
1148
|
+
"name": {
|
|
1149
|
+
"type": "string"
|
|
1150
|
+
},
|
|
1151
|
+
"number": {
|
|
1152
|
+
"type": "string"
|
|
1153
|
+
},
|
|
1154
|
+
"postcode": {
|
|
1155
|
+
"type": "string"
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
},
|
|
1109
1161
|
"ledgerListing": {
|
|
1110
1162
|
"type": "object",
|
|
1111
1163
|
"description": "One named debtor or creditor balance.",
|