@accounter/shaam-uniform-format-generator 0.1.0 → 0.1.1
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 +366 -13
- package/dist/README.md +476 -0
- package/dist/cjs/api/generate-report-legacy.js +6 -0
- package/dist/cjs/api/generate-report.js +328 -0
- package/dist/cjs/constants.js +11 -0
- package/dist/cjs/generator/format/encoder.js +86 -0
- package/dist/cjs/generator/records/a000-sum.js +66 -0
- package/dist/cjs/generator/records/a000.js +349 -0
- package/dist/cjs/generator/records/a100.js +107 -0
- package/dist/cjs/generator/records/b100.js +305 -0
- package/dist/cjs/generator/records/b110.js +255 -0
- package/dist/cjs/generator/records/c100.js +338 -0
- package/dist/cjs/generator/records/d110.js +272 -0
- package/dist/cjs/generator/records/d120.js +278 -0
- package/{cjs → dist/cjs}/generator/records/index.js +1 -0
- package/dist/cjs/generator/records/m100.js +177 -0
- package/dist/cjs/generator/records/z900.js +93 -0
- package/{cjs → dist/cjs}/index.js +3 -0
- package/dist/cjs/records/a100.js +78 -0
- package/dist/cjs/records/index.js +20 -0
- package/dist/cjs/records/z900.js +82 -0
- package/dist/cjs/types/enums.js +457 -0
- package/{cjs → dist/cjs}/types/index.js +6 -1
- package/dist/cjs/utils/file-helpers.js +198 -0
- package/dist/cjs/utils/index.js +8 -0
- package/dist/cjs/utils/key-generator.js +71 -0
- package/dist/esm/api/generate-report-legacy.js +2 -0
- package/dist/esm/api/generate-report.js +325 -0
- package/dist/esm/constants.js +8 -0
- package/dist/esm/generator/format/encoder.js +77 -0
- package/dist/esm/generator/records/a000-sum.js +61 -0
- package/dist/esm/generator/records/a000.js +344 -0
- package/dist/esm/generator/records/a100.js +102 -0
- package/dist/esm/generator/records/b100.js +300 -0
- package/dist/esm/generator/records/b110.js +250 -0
- package/dist/esm/generator/records/c100.js +333 -0
- package/dist/esm/generator/records/d110.js +267 -0
- package/dist/esm/generator/records/d120.js +273 -0
- package/{esm → dist/esm}/generator/records/index.js +1 -0
- package/dist/esm/generator/records/m100.js +172 -0
- package/dist/esm/generator/records/z900.js +88 -0
- package/{esm → dist/esm}/index.js +3 -0
- package/dist/esm/records/a100.js +73 -0
- package/dist/esm/records/index.js +11 -0
- package/dist/esm/records/z900.js +77 -0
- package/dist/esm/types/enums.js +454 -0
- package/{esm → dist/esm}/types/index.js +5 -1
- package/dist/esm/utils/file-helpers.js +188 -0
- package/dist/esm/utils/index.js +5 -0
- package/dist/esm/utils/key-generator.js +65 -0
- package/dist/package.json +54 -0
- package/dist/typings/api/generate-report-legacy.d.cts +1 -0
- package/dist/typings/api/generate-report-legacy.d.ts +1 -0
- package/dist/typings/constants.d.cts +8 -0
- package/dist/typings/constants.d.ts +8 -0
- package/dist/typings/generator/format/encoder.d.cts +57 -0
- package/dist/typings/generator/format/encoder.d.ts +57 -0
- package/dist/typings/generator/records/a000-sum.d.cts +40 -0
- package/dist/typings/generator/records/a000-sum.d.ts +40 -0
- package/dist/typings/generator/records/a000.d.cts +238 -0
- package/dist/typings/generator/records/a000.d.ts +238 -0
- package/dist/typings/generator/records/a100.d.cts +59 -0
- package/dist/typings/generator/records/a100.d.ts +59 -0
- package/dist/typings/generator/records/b100.d.cts +101 -0
- package/dist/typings/generator/records/b100.d.ts +101 -0
- package/dist/typings/generator/records/b110.d.cts +89 -0
- package/dist/typings/generator/records/b110.d.ts +89 -0
- package/dist/typings/generator/records/c100.d.cts +133 -0
- package/dist/typings/generator/records/c100.d.ts +133 -0
- package/dist/typings/generator/records/d110.d.cts +98 -0
- package/dist/typings/generator/records/d110.d.ts +98 -0
- package/dist/typings/generator/records/d120.d.cts +95 -0
- package/dist/typings/generator/records/d120.d.ts +95 -0
- package/{typings → dist/typings}/generator/records/index.d.cts +1 -0
- package/{typings → dist/typings}/generator/records/index.d.ts +1 -0
- package/dist/typings/generator/records/m100.d.cts +69 -0
- package/dist/typings/generator/records/m100.d.ts +69 -0
- package/dist/typings/generator/records/z900.d.cts +61 -0
- package/dist/typings/generator/records/z900.d.ts +61 -0
- package/{typings → dist/typings}/index.d.cts +3 -0
- package/{typings → dist/typings}/index.d.ts +3 -0
- package/dist/typings/records/a100.d.cts +35 -0
- package/dist/typings/records/a100.d.ts +35 -0
- package/dist/typings/records/index.d.cts +2 -0
- package/dist/typings/records/index.d.ts +2 -0
- package/dist/typings/records/z900.d.cts +38 -0
- package/dist/typings/records/z900.d.ts +38 -0
- package/dist/typings/types/enums.d.cts +162 -0
- package/dist/typings/types/enums.d.ts +162 -0
- package/{typings → dist/typings}/types/index.d.cts +17 -14
- package/{typings → dist/typings}/types/index.d.ts +17 -14
- package/dist/typings/utils/file-helpers.d.cts +131 -0
- package/dist/typings/utils/file-helpers.d.ts +131 -0
- package/dist/typings/utils/index.d.cts +5 -0
- package/dist/typings/utils/index.d.ts +5 -0
- package/dist/typings/utils/key-generator.d.cts +41 -0
- package/dist/typings/utils/key-generator.d.ts +41 -0
- package/documentation/IncomeTax_IncomeTaxSoftwareHousesInfo_horaot1.31_2_05.pdf +0 -0
- package/documentation/_4D6963726F736F667420576F7264202D20F8E5E0E9ED20F8E7E5F720F8E5E0E9ED20F9F7E5F32E646F63_.pdf +0 -0
- package/documentation/a000-sum.csv +3 -0
- package/documentation/a000.csv +37 -0
- package/documentation/a100.csv +7 -0
- package/documentation/b100.csv +29 -0
- package/documentation/b110.csv +26 -0
- package/documentation/c100.csv +37 -0
- package/documentation/d110.csv +27 -0
- package/documentation/d120.csv +26 -0
- package/documentation/m100.csv +17 -0
- package/documentation/z900.csv +8 -0
- package/package.json +50 -29
- package/prompt_plan.md +259 -0
- package/spec.md +206 -0
- package/src/api/generate-report.ts +366 -0
- package/src/api/parse-files.ts +33 -0
- package/src/constants.ts +9 -0
- package/src/format/index.ts +6 -0
- package/src/format/newline.ts +8 -0
- package/src/format/padding.ts +39 -0
- package/src/generator/format/decoder.ts +15 -0
- package/src/generator/format/encoder.ts +95 -0
- package/src/generator/format/index.ts +6 -0
- package/src/generator/index.ts +6 -0
- package/src/generator/records/a000-sum.ts +78 -0
- package/src/generator/records/a000.ts +373 -0
- package/src/generator/records/a100.ts +118 -0
- package/src/generator/records/b100.ts +317 -0
- package/src/generator/records/b110.ts +267 -0
- package/src/generator/records/c100.ts +347 -0
- package/src/generator/records/d110.ts +286 -0
- package/src/generator/records/d120.ts +293 -0
- package/src/generator/records/index.ts +14 -0
- package/src/generator/records/m100.ts +185 -0
- package/src/generator/records/z900.ts +104 -0
- package/src/index.ts +18 -0
- package/src/parser/data-parser.ts +14 -0
- package/src/parser/index.ts +6 -0
- package/src/parser/ini-parser.ts +14 -0
- package/src/types/enums.ts +531 -0
- package/src/types/index.ts +110 -0
- package/src/utils/file-helpers.ts +221 -0
- package/src/utils/index.ts +6 -0
- package/src/utils/key-generator.ts +75 -0
- package/src/validation/errors.ts +35 -0
- package/src/validation/index.ts +6 -0
- package/src/validation/validate-input.ts +67 -0
- package/tests/debug-output.test.ts +81 -0
- package/tests/format/crlf-join.test.ts +124 -0
- package/tests/format/encoder.test.ts +80 -0
- package/tests/format/newline.test.ts +19 -0
- package/tests/format/padding.test.ts +74 -0
- package/tests/index.test.ts +29 -0
- package/tests/ini-text.test.ts +122 -0
- package/tests/integration/comprehensive.integration.test.ts +350 -0
- package/tests/integration/roundtrip.integration.test.ts +377 -0
- package/tests/records/a000-sum.test.ts +278 -0
- package/tests/records/a000.test.ts +318 -0
- package/tests/records/a100.test.ts +239 -0
- package/tests/records/b100.test.ts +419 -0
- package/tests/records/b110.test.ts +445 -0
- package/tests/records/c100.test.ts +333 -0
- package/tests/records/d110.test.ts +93 -0
- package/tests/records/d120.test.ts +275 -0
- package/tests/records/m100.test.ts +437 -0
- package/tests/records/z900.test.ts +254 -0
- package/tests/types/enums.test.ts +290 -0
- package/tests/utils/file-helpers.test.ts +276 -0
- package/tests/utils/key-generator.test.ts +121 -0
- package/tests/validation/document-type-validation.test.ts +521 -0
- package/tests/validation/validate-input.test.ts +219 -0
- package/todo.md +203 -0
- package/tsconfig.json +10 -0
- package/vitest.config.ts +11 -0
- package/cjs/api/generate-report.js +0 -53
- package/cjs/generator/format/encoder.js +0 -46
- package/cjs/generator/records/a000.js +0 -8
- package/cjs/generator/records/a100.js +0 -8
- package/cjs/generator/records/b100.js +0 -8
- package/cjs/generator/records/b110.js +0 -8
- package/cjs/generator/records/c100.js +0 -8
- package/cjs/generator/records/d110.js +0 -8
- package/cjs/generator/records/d120.js +0 -8
- package/cjs/generator/records/m100.js +0 -8
- package/cjs/generator/records/z900.js +0 -8
- package/esm/api/generate-report.js +0 -50
- package/esm/generator/format/encoder.js +0 -42
- package/esm/generator/records/a000.js +0 -5
- package/esm/generator/records/a100.js +0 -5
- package/esm/generator/records/b100.js +0 -5
- package/esm/generator/records/b110.js +0 -5
- package/esm/generator/records/c100.js +0 -5
- package/esm/generator/records/d110.js +0 -5
- package/esm/generator/records/d120.js +0 -5
- package/esm/generator/records/m100.js +0 -5
- package/esm/generator/records/z900.js +0 -5
- package/typings/generator/format/encoder.d.cts +0 -33
- package/typings/generator/format/encoder.d.ts +0 -33
- package/typings/generator/records/a000.d.cts +0 -4
- package/typings/generator/records/a000.d.ts +0 -4
- package/typings/generator/records/a100.d.cts +0 -4
- package/typings/generator/records/a100.d.ts +0 -4
- package/typings/generator/records/b100.d.cts +0 -4
- package/typings/generator/records/b100.d.ts +0 -4
- package/typings/generator/records/b110.d.cts +0 -4
- package/typings/generator/records/b110.d.ts +0 -4
- package/typings/generator/records/c100.d.cts +0 -4
- package/typings/generator/records/c100.d.ts +0 -4
- package/typings/generator/records/d110.d.cts +0 -4
- package/typings/generator/records/d110.d.ts +0 -4
- package/typings/generator/records/d120.d.cts +0 -4
- package/typings/generator/records/d120.d.ts +0 -4
- package/typings/generator/records/m100.d.cts +0 -4
- package/typings/generator/records/m100.d.ts +0 -4
- package/typings/generator/records/z900.d.cts +0 -4
- package/typings/generator/records/z900.d.ts +0 -4
- /package/{cjs → dist/cjs}/api/parse-files.js +0 -0
- /package/{cjs → dist/cjs}/format/index.js +0 -0
- /package/{cjs → dist/cjs}/format/newline.js +0 -0
- /package/{cjs → dist/cjs}/format/padding.js +0 -0
- /package/{cjs → dist/cjs}/generator/format/decoder.js +0 -0
- /package/{cjs → dist/cjs}/generator/format/index.js +0 -0
- /package/{cjs → dist/cjs}/generator/index.js +0 -0
- /package/{cjs → dist/cjs}/package.json +0 -0
- /package/{cjs → dist/cjs}/parser/data-parser.js +0 -0
- /package/{cjs → dist/cjs}/parser/index.js +0 -0
- /package/{cjs → dist/cjs}/parser/ini-parser.js +0 -0
- /package/{cjs → dist/cjs}/validation/errors.js +0 -0
- /package/{cjs → dist/cjs}/validation/index.js +0 -0
- /package/{cjs → dist/cjs}/validation/validate-input.js +0 -0
- /package/{esm → dist/esm}/api/parse-files.js +0 -0
- /package/{esm → dist/esm}/format/index.js +0 -0
- /package/{esm → dist/esm}/format/newline.js +0 -0
- /package/{esm → dist/esm}/format/padding.js +0 -0
- /package/{esm → dist/esm}/generator/format/decoder.js +0 -0
- /package/{esm → dist/esm}/generator/format/index.js +0 -0
- /package/{esm → dist/esm}/generator/index.js +0 -0
- /package/{esm → dist/esm}/parser/data-parser.js +0 -0
- /package/{esm → dist/esm}/parser/index.js +0 -0
- /package/{esm → dist/esm}/parser/ini-parser.js +0 -0
- /package/{esm → dist/esm}/validation/errors.js +0 -0
- /package/{esm → dist/esm}/validation/index.js +0 -0
- /package/{esm → dist/esm}/validation/validate-input.js +0 -0
- /package/{typings → dist/typings}/api/generate-report.d.cts +0 -0
- /package/{typings → dist/typings}/api/generate-report.d.ts +0 -0
- /package/{typings → dist/typings}/api/parse-files.d.cts +0 -0
- /package/{typings → dist/typings}/api/parse-files.d.ts +0 -0
- /package/{typings → dist/typings}/format/index.d.cts +0 -0
- /package/{typings → dist/typings}/format/index.d.ts +0 -0
- /package/{typings → dist/typings}/format/newline.d.cts +0 -0
- /package/{typings → dist/typings}/format/newline.d.ts +0 -0
- /package/{typings → dist/typings}/format/padding.d.cts +0 -0
- /package/{typings → dist/typings}/format/padding.d.ts +0 -0
- /package/{typings → dist/typings}/generator/format/decoder.d.cts +0 -0
- /package/{typings → dist/typings}/generator/format/decoder.d.ts +0 -0
- /package/{typings → dist/typings}/generator/format/index.d.cts +0 -0
- /package/{typings → dist/typings}/generator/format/index.d.ts +0 -0
- /package/{typings → dist/typings}/generator/index.d.cts +0 -0
- /package/{typings → dist/typings}/generator/index.d.ts +0 -0
- /package/{typings → dist/typings}/parser/data-parser.d.cts +0 -0
- /package/{typings → dist/typings}/parser/data-parser.d.ts +0 -0
- /package/{typings → dist/typings}/parser/index.d.cts +0 -0
- /package/{typings → dist/typings}/parser/index.d.ts +0 -0
- /package/{typings → dist/typings}/parser/ini-parser.d.cts +0 -0
- /package/{typings → dist/typings}/parser/ini-parser.d.ts +0 -0
- /package/{typings → dist/typings}/validation/errors.d.cts +0 -0
- /package/{typings → dist/typings}/validation/errors.d.ts +0 -0
- /package/{typings → dist/typings}/validation/index.d.cts +0 -0
- /package/{typings → dist/typings}/validation/index.d.ts +0 -0
- /package/{typings → dist/typings}/validation/validate-input.d.cts +0 -0
- /package/{typings → dist/typings}/validation/validate-input.d.ts +0 -0
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.B100Schema = void 0;
|
|
4
|
+
exports.encodeB100 = encodeB100;
|
|
5
|
+
exports.parseB100 = parseB100;
|
|
6
|
+
const zod_1 = require("zod");
|
|
7
|
+
const index_js_1 = require("../../format/index.js");
|
|
8
|
+
const index_js_2 = require("../index.js");
|
|
9
|
+
/**
|
|
10
|
+
* B100 Record Schema - Journal entry line record
|
|
11
|
+
* Fields 1350-1377 based on SHAAM 1.31 specification table
|
|
12
|
+
*/
|
|
13
|
+
exports.B100Schema = zod_1.z.object({
|
|
14
|
+
// Field 1350: Record code (4) - Required - Alphanumeric
|
|
15
|
+
code: zod_1.z.literal('B100').describe('Record type code - always "B100"'),
|
|
16
|
+
// Field 1351: Record number in file (9) - Required - Numeric
|
|
17
|
+
recordNumber: zod_1.z
|
|
18
|
+
.string()
|
|
19
|
+
.min(1)
|
|
20
|
+
.max(9)
|
|
21
|
+
.regex(/^\d+$/)
|
|
22
|
+
.describe('Sequential record number in file'),
|
|
23
|
+
// Field 1352: Tax ID (9) - Required - Numeric
|
|
24
|
+
vatId: zod_1.z.string().min(1).max(9).regex(/^\d+$/).describe('Tax identification number'),
|
|
25
|
+
// Field 1353: Transaction number (10) - Required - Numeric
|
|
26
|
+
transactionNumber: zod_1.z
|
|
27
|
+
.string()
|
|
28
|
+
.min(1)
|
|
29
|
+
.max(10)
|
|
30
|
+
.regex(/^\d+$/)
|
|
31
|
+
.describe('Transaction number - see Note 7'),
|
|
32
|
+
// Field 1354: Transaction line number (5) - Required - Numeric
|
|
33
|
+
transactionLineNumber: zod_1.z
|
|
34
|
+
.string()
|
|
35
|
+
.min(1)
|
|
36
|
+
.max(5)
|
|
37
|
+
.regex(/^\d+$/)
|
|
38
|
+
.describe('Transaction line number'),
|
|
39
|
+
// Field 1355: Batch number (8) - Optional - Numeric
|
|
40
|
+
batchNumber: zod_1.z
|
|
41
|
+
.string()
|
|
42
|
+
.max(8)
|
|
43
|
+
.regex(/^$|^\d+$/)
|
|
44
|
+
.default('')
|
|
45
|
+
.describe('Batch number'),
|
|
46
|
+
// Field 1356: Transaction type (15) - Optional - Alphanumeric
|
|
47
|
+
transactionType: zod_1.z.string().max(15).default('').describe('Transaction type'),
|
|
48
|
+
// Field 1357: Reference document (20) - Optional - Alphanumeric
|
|
49
|
+
referenceDocument: zod_1.z.string().max(20).default('').describe('Reference document'),
|
|
50
|
+
// Field 1358: Reference document type (3) - Optional - Numeric
|
|
51
|
+
referenceDocumentType: zod_1.z
|
|
52
|
+
.string()
|
|
53
|
+
.max(3)
|
|
54
|
+
.regex(/^$|^\d+$/)
|
|
55
|
+
.default('')
|
|
56
|
+
.transform(val => (val === '' ? val : val))
|
|
57
|
+
.describe('Reference document type - see Appendix 1'),
|
|
58
|
+
// Field 1359: Reference document 2 (20) - Optional - Alphanumeric
|
|
59
|
+
referenceDocument2: zod_1.z.string().max(20).default('').describe('Reference document 2'),
|
|
60
|
+
// Field 1360: Reference document type 2 (3) - Optional - Numeric
|
|
61
|
+
referenceDocumentType2: zod_1.z
|
|
62
|
+
.string()
|
|
63
|
+
.max(3)
|
|
64
|
+
.regex(/^$|^\d+$/)
|
|
65
|
+
.default('')
|
|
66
|
+
.transform(val => (val === '' ? val : val))
|
|
67
|
+
.describe('Reference document type 2 - see Appendix 1'),
|
|
68
|
+
// Field 1361: Details (50) - Optional - Alphanumeric
|
|
69
|
+
details: zod_1.z.string().max(50).default('').describe('Details'),
|
|
70
|
+
// Field 1362: Date (8) - Required - Numeric - Format: YYYYMMDD
|
|
71
|
+
date: zod_1.z
|
|
72
|
+
.string()
|
|
73
|
+
.length(8)
|
|
74
|
+
.regex(/^\d{8}$/)
|
|
75
|
+
.describe('Date in YYYYMMDD format - see Note 12'),
|
|
76
|
+
// Field 1363: Value date (8) - Required - Numeric - Format: YYYYMMDD
|
|
77
|
+
valueDate: zod_1.z
|
|
78
|
+
.string()
|
|
79
|
+
.length(8)
|
|
80
|
+
.regex(/^\d{8}$/)
|
|
81
|
+
.describe('Value date in YYYYMMDD format - see Note 12'),
|
|
82
|
+
// Field 1364: Account key (15) - Required - Alphanumeric
|
|
83
|
+
accountKey: zod_1.z.string().min(1).max(15).describe('Account key - must match B110'),
|
|
84
|
+
// Field 1365: Counter account key (15) - Optional - Alphanumeric
|
|
85
|
+
counterAccountKey: zod_1.z
|
|
86
|
+
.string()
|
|
87
|
+
.max(15)
|
|
88
|
+
.default('')
|
|
89
|
+
.describe('Counter account key - required in single-entry bookkeeping'),
|
|
90
|
+
// Field 1366: Debit/Credit indicator (1) - Required - Numeric
|
|
91
|
+
debitCreditIndicator: zod_1.z
|
|
92
|
+
.enum(['1', '2'])
|
|
93
|
+
.describe('Debit/Credit indicator: 1 = Debit, 2 = Credit'),
|
|
94
|
+
// Field 1367: Currency code (3) - Optional - Alphanumeric
|
|
95
|
+
currencyCode: zod_1.z
|
|
96
|
+
.string()
|
|
97
|
+
.max(3)
|
|
98
|
+
.default('')
|
|
99
|
+
.describe('Currency code - refers to field 1369; see Appendix 2'),
|
|
100
|
+
// Field 1368: Transaction amount (15) - Required - Alphanumeric - Format: X9(12)V99
|
|
101
|
+
transactionAmount: zod_1.z.string().min(1).max(15).describe('Transaction amount in local currency'),
|
|
102
|
+
// Field 1369: Foreign currency amount (15) - Optional - Alphanumeric - Format: X9(12)V99
|
|
103
|
+
foreignCurrencyAmount: zod_1.z
|
|
104
|
+
.string()
|
|
105
|
+
.max(15)
|
|
106
|
+
.default('')
|
|
107
|
+
.describe('Transaction amount in foreign currency'),
|
|
108
|
+
// Field 1370: Quantity field (12) - Optional - Alphanumeric - Format: X9(9)V99
|
|
109
|
+
quantityField: zod_1.z
|
|
110
|
+
.string()
|
|
111
|
+
.max(12)
|
|
112
|
+
.default('')
|
|
113
|
+
.describe('Quantity field, e.g. quantity or cost code'),
|
|
114
|
+
// Field 1371: Matching field 1 (10) - Optional - Alphanumeric
|
|
115
|
+
matchingField1: zod_1.z
|
|
116
|
+
.string()
|
|
117
|
+
.max(10)
|
|
118
|
+
.default('')
|
|
119
|
+
.describe('Matching field 1 - used for internal row reconciliation'),
|
|
120
|
+
// Field 1372: Matching field 2 (10) - Optional - Alphanumeric
|
|
121
|
+
matchingField2: zod_1.z
|
|
122
|
+
.string()
|
|
123
|
+
.max(10)
|
|
124
|
+
.default('')
|
|
125
|
+
.describe('Matching field 2 - used for inter-card or external reconciliation'),
|
|
126
|
+
// Field 1373: Reserved field (0) - Deprecated - Alphanumeric
|
|
127
|
+
// Skipped as it has 0 length
|
|
128
|
+
// Field 1374: Branch ID (7) - Conditional - Alphanumeric
|
|
129
|
+
branchId: zod_1.z
|
|
130
|
+
.string()
|
|
131
|
+
.max(7)
|
|
132
|
+
.default('')
|
|
133
|
+
.describe('Branch ID - conditional if field 1034 = 1; see Note 3'),
|
|
134
|
+
// Field 1375: Entry date (8) - Required - Numeric - Format: YYYYMMDD
|
|
135
|
+
entryDate: zod_1.z
|
|
136
|
+
.string()
|
|
137
|
+
.length(8)
|
|
138
|
+
.regex(/^\d{8}$/)
|
|
139
|
+
.describe('Entry date in YYYYMMDD format - see Note 12'),
|
|
140
|
+
// Field 1376: Operator username (9) - Optional - Alphanumeric
|
|
141
|
+
operatorUsername: zod_1.z.string().max(9).default('').describe('Operator username'),
|
|
142
|
+
// Field 1377: Reserved field (25) - Optional - Alphanumeric
|
|
143
|
+
reserved: zod_1.z.string().max(25).default('').describe('Reserved field for future use'),
|
|
144
|
+
});
|
|
145
|
+
/**
|
|
146
|
+
* Encodes a B100 record to fixed-width string format
|
|
147
|
+
* Total line width: 317 characters + CRLF
|
|
148
|
+
*/
|
|
149
|
+
function encodeB100(input) {
|
|
150
|
+
const fields = [
|
|
151
|
+
(0, index_js_2.formatField)(input.code, 4, 'left'), // Field 1350: Record code (4)
|
|
152
|
+
(0, index_js_2.formatNumericField)(input.recordNumber, 9), // Field 1351: Record number (9)
|
|
153
|
+
(0, index_js_2.formatNumericField)(input.vatId, 9), // Field 1352: VAT ID (9)
|
|
154
|
+
(0, index_js_2.formatNumericField)(input.transactionNumber, 10), // Field 1353: Transaction number (10)
|
|
155
|
+
(0, index_js_2.formatNumericField)(input.transactionLineNumber, 5), // Field 1354: Transaction line number (5)
|
|
156
|
+
(0, index_js_2.formatNumericField)(input.batchNumber, 8), // Field 1355: Batch number (8)
|
|
157
|
+
(0, index_js_2.formatField)(input.transactionType, 15, 'left'), // Field 1356: Transaction type (15)
|
|
158
|
+
(0, index_js_2.formatField)(input.referenceDocument, 20, 'left'), // Field 1357: Reference document (20)
|
|
159
|
+
(0, index_js_2.formatNumericField)(input.referenceDocumentType, 3), // Field 1358: Reference document type (3)
|
|
160
|
+
(0, index_js_2.formatField)(input.referenceDocument2, 20, 'left'), // Field 1359: Reference document 2 (20)
|
|
161
|
+
(0, index_js_2.formatNumericField)(input.referenceDocumentType2, 3), // Field 1360: Reference document type 2 (3)
|
|
162
|
+
(0, index_js_2.formatField)(input.details, 50, 'left'), // Field 1361: Details (50)
|
|
163
|
+
(0, index_js_2.formatField)(input.date, 8, 'left'), // Field 1362: Date (8)
|
|
164
|
+
(0, index_js_2.formatField)(input.valueDate, 8, 'left'), // Field 1363: Value date (8)
|
|
165
|
+
(0, index_js_2.formatField)(input.accountKey, 15, 'left'), // Field 1364: Account key (15)
|
|
166
|
+
(0, index_js_2.formatField)(input.counterAccountKey, 15, 'left'), // Field 1365: Counter account key (15)
|
|
167
|
+
(0, index_js_2.formatField)(input.debitCreditIndicator, 1, 'left'), // Field 1366: Debit/Credit indicator (1)
|
|
168
|
+
(0, index_js_2.formatField)(input.currencyCode, 3, 'left'), // Field 1367: Currency code (3)
|
|
169
|
+
(0, index_js_2.formatField)(input.transactionAmount, 15, 'right'), // Field 1368: Transaction amount (15) - right-aligned for amount
|
|
170
|
+
(0, index_js_2.formatField)(input.foreignCurrencyAmount, 15, 'right'), // Field 1369: Foreign currency amount (15) - right-aligned for amount
|
|
171
|
+
(0, index_js_2.formatField)(input.quantityField, 12, 'right'), // Field 1370: Quantity field (12) - right-aligned for numeric
|
|
172
|
+
(0, index_js_2.formatField)(input.matchingField1, 10, 'left'), // Field 1371: Matching field 1 (10)
|
|
173
|
+
(0, index_js_2.formatField)(input.matchingField2, 10, 'left'), // Field 1372: Matching field 2 (10)
|
|
174
|
+
// Field 1373: Reserved field (0) - skipped as it has 0 length
|
|
175
|
+
(0, index_js_2.formatField)(input.branchId, 7, 'left'), // Field 1374: Branch ID (7)
|
|
176
|
+
(0, index_js_2.formatField)(input.entryDate, 8, 'left'), // Field 1375: Entry date (8)
|
|
177
|
+
(0, index_js_2.formatField)(input.operatorUsername, 9, 'left'), // Field 1376: Operator username (9)
|
|
178
|
+
(0, index_js_2.formatField)(input.reserved, 25, 'left'), // Field 1377: Reserved field (25)
|
|
179
|
+
];
|
|
180
|
+
return fields.join('') + index_js_1.CRLF;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Parses a fixed-width B100 record line back to object
|
|
184
|
+
* Expected line length: 317 characters (excluding CRLF)
|
|
185
|
+
*/
|
|
186
|
+
function parseB100(line) {
|
|
187
|
+
// Remove CRLF if present
|
|
188
|
+
const cleanLine = line.replace(/\r?\n$/, '');
|
|
189
|
+
if (cleanLine.length !== 317) {
|
|
190
|
+
throw new Error(`Invalid B100 record length: expected 317 characters, got ${cleanLine.length}`);
|
|
191
|
+
}
|
|
192
|
+
// Extract fields at their fixed positions
|
|
193
|
+
let pos = 0;
|
|
194
|
+
const code = cleanLine.slice(pos, pos + 4).trim();
|
|
195
|
+
pos += 4;
|
|
196
|
+
const recordNumber = cleanLine
|
|
197
|
+
.slice(pos, pos + 9)
|
|
198
|
+
.trim()
|
|
199
|
+
.replace(/^0+/, '') || '0';
|
|
200
|
+
pos += 9;
|
|
201
|
+
const vatId = cleanLine
|
|
202
|
+
.slice(pos, pos + 9)
|
|
203
|
+
.trim()
|
|
204
|
+
.replace(/^0+/, '') || '0';
|
|
205
|
+
pos += 9;
|
|
206
|
+
const transactionNumber = cleanLine
|
|
207
|
+
.slice(pos, pos + 10)
|
|
208
|
+
.trim()
|
|
209
|
+
.replace(/^0+/, '') || '0';
|
|
210
|
+
pos += 10;
|
|
211
|
+
const transactionLineNumber = cleanLine
|
|
212
|
+
.slice(pos, pos + 5)
|
|
213
|
+
.trim()
|
|
214
|
+
.replace(/^0+/, '') || '0';
|
|
215
|
+
pos += 5;
|
|
216
|
+
const batchNumber = cleanLine
|
|
217
|
+
.slice(pos, pos + 8)
|
|
218
|
+
.trim()
|
|
219
|
+
.replace(/^0+/, '') || '';
|
|
220
|
+
pos += 8;
|
|
221
|
+
const transactionType = cleanLine.slice(pos, pos + 15).trim();
|
|
222
|
+
pos += 15;
|
|
223
|
+
const referenceDocument = cleanLine.slice(pos, pos + 20).trim();
|
|
224
|
+
pos += 20;
|
|
225
|
+
const referenceDocumentType = (cleanLine
|
|
226
|
+
.slice(pos, pos + 3)
|
|
227
|
+
.trim()
|
|
228
|
+
.replace(/^0+/, '') || '');
|
|
229
|
+
pos += 3;
|
|
230
|
+
const referenceDocument2 = cleanLine.slice(pos, pos + 20).trim();
|
|
231
|
+
pos += 20;
|
|
232
|
+
const referenceDocumentType2 = (cleanLine
|
|
233
|
+
.slice(pos, pos + 3)
|
|
234
|
+
.trim()
|
|
235
|
+
.replace(/^0+/, '') || '');
|
|
236
|
+
pos += 3;
|
|
237
|
+
const details = cleanLine.slice(pos, pos + 50).trim();
|
|
238
|
+
pos += 50;
|
|
239
|
+
const date = cleanLine.slice(pos, pos + 8).trim();
|
|
240
|
+
pos += 8;
|
|
241
|
+
const valueDate = cleanLine.slice(pos, pos + 8).trim();
|
|
242
|
+
pos += 8;
|
|
243
|
+
const accountKey = cleanLine.slice(pos, pos + 15).trim();
|
|
244
|
+
pos += 15;
|
|
245
|
+
const counterAccountKey = cleanLine.slice(pos, pos + 15).trim();
|
|
246
|
+
pos += 15;
|
|
247
|
+
const debitCreditIndicator = cleanLine.slice(pos, pos + 1).trim();
|
|
248
|
+
pos += 1;
|
|
249
|
+
const currencyCode = cleanLine.slice(pos, pos + 3).trim();
|
|
250
|
+
pos += 3;
|
|
251
|
+
const transactionAmount = cleanLine.slice(pos, pos + 15).trim();
|
|
252
|
+
pos += 15;
|
|
253
|
+
const foreignCurrencyAmount = cleanLine.slice(pos, pos + 15).trim();
|
|
254
|
+
pos += 15;
|
|
255
|
+
const quantityField = cleanLine.slice(pos, pos + 12).trim();
|
|
256
|
+
pos += 12;
|
|
257
|
+
const matchingField1 = cleanLine.slice(pos, pos + 10).trim();
|
|
258
|
+
pos += 10;
|
|
259
|
+
const matchingField2 = cleanLine.slice(pos, pos + 10).trim();
|
|
260
|
+
pos += 10;
|
|
261
|
+
// Field 1373: Reserved field (0) - skipped as it has 0 length
|
|
262
|
+
const branchId = cleanLine.slice(pos, pos + 7).trim();
|
|
263
|
+
pos += 7;
|
|
264
|
+
const entryDate = cleanLine.slice(pos, pos + 8).trim();
|
|
265
|
+
pos += 8;
|
|
266
|
+
const operatorUsername = cleanLine.slice(pos, pos + 9).trim();
|
|
267
|
+
pos += 9;
|
|
268
|
+
const reserved = cleanLine.slice(pos, pos + 25).trim();
|
|
269
|
+
pos += 25;
|
|
270
|
+
// Validate the code field
|
|
271
|
+
if (code !== 'B100') {
|
|
272
|
+
throw new Error(`Invalid B100 record code: expected "B100", got "${code}"`);
|
|
273
|
+
}
|
|
274
|
+
const parsed = {
|
|
275
|
+
code,
|
|
276
|
+
recordNumber,
|
|
277
|
+
vatId,
|
|
278
|
+
transactionNumber,
|
|
279
|
+
transactionLineNumber,
|
|
280
|
+
batchNumber,
|
|
281
|
+
transactionType,
|
|
282
|
+
referenceDocument,
|
|
283
|
+
referenceDocumentType,
|
|
284
|
+
referenceDocument2,
|
|
285
|
+
referenceDocumentType2,
|
|
286
|
+
details,
|
|
287
|
+
date,
|
|
288
|
+
valueDate,
|
|
289
|
+
accountKey,
|
|
290
|
+
counterAccountKey,
|
|
291
|
+
debitCreditIndicator: debitCreditIndicator,
|
|
292
|
+
currencyCode,
|
|
293
|
+
transactionAmount,
|
|
294
|
+
foreignCurrencyAmount,
|
|
295
|
+
quantityField,
|
|
296
|
+
matchingField1,
|
|
297
|
+
matchingField2,
|
|
298
|
+
branchId,
|
|
299
|
+
entryDate,
|
|
300
|
+
operatorUsername,
|
|
301
|
+
reserved,
|
|
302
|
+
};
|
|
303
|
+
// Validate against schema
|
|
304
|
+
return exports.B100Schema.parse(parsed);
|
|
305
|
+
}
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.B110Schema = void 0;
|
|
4
|
+
exports.encodeB110 = encodeB110;
|
|
5
|
+
exports.parseB110 = parseB110;
|
|
6
|
+
const zod_1 = require("zod");
|
|
7
|
+
const index_js_1 = require("../../format/index.js");
|
|
8
|
+
const encoder_js_1 = require("../format/encoder.js");
|
|
9
|
+
/**
|
|
10
|
+
* B110 Record Schema - Account record
|
|
11
|
+
* Fields 1400-1424 based on SHAAM 1.31 specification table
|
|
12
|
+
*/
|
|
13
|
+
exports.B110Schema = zod_1.z.object({
|
|
14
|
+
// Field 1400: Record code (4) - Required - Alphanumeric
|
|
15
|
+
code: zod_1.z.literal('B110').describe('Record type code - always "B110"'),
|
|
16
|
+
// Field 1401: Record number in file (9) - Required - Numeric
|
|
17
|
+
recordNumber: zod_1.z
|
|
18
|
+
.string()
|
|
19
|
+
.min(1)
|
|
20
|
+
.max(9)
|
|
21
|
+
.regex(/^\d+$/)
|
|
22
|
+
.describe('Sequential record number in file'),
|
|
23
|
+
// Field 1402: Tax ID (9) - Required - Numeric
|
|
24
|
+
vatId: zod_1.z.string().min(1).max(9).regex(/^\d+$/).describe('Tax identification number'),
|
|
25
|
+
// Field 1403: Account key (15) - Required - Alphanumeric
|
|
26
|
+
accountKey: zod_1.z.string().min(1).max(15).describe('Account key - must be unique'),
|
|
27
|
+
// Field 1404: Account name (50) - Required - Alphanumeric
|
|
28
|
+
accountName: zod_1.z.string().min(1).max(50).describe('Account name'),
|
|
29
|
+
// Field 1405: Trial balance code (15) - Required - Alphanumeric
|
|
30
|
+
trialBalanceCode: zod_1.z.string().min(1).max(15).describe('Trial balance code'),
|
|
31
|
+
// Field 1406: Trial balance code description (30) - Required - Alphanumeric
|
|
32
|
+
trialBalanceCodeDescription: zod_1.z.string().min(1).max(30).describe('Trial balance code description'),
|
|
33
|
+
// Field 1407: Customer/Supplier address - street (50) - Optional - Alphanumeric
|
|
34
|
+
customerSupplierAddressStreet: zod_1.z
|
|
35
|
+
.string()
|
|
36
|
+
.max(50)
|
|
37
|
+
.default('')
|
|
38
|
+
.describe('Customer/Supplier address - street (only for customer/supplier accounts)'),
|
|
39
|
+
// Field 1408: Customer/Supplier address - house number (10) - Optional - Alphanumeric
|
|
40
|
+
customerSupplierAddressHouseNumber: zod_1.z
|
|
41
|
+
.string()
|
|
42
|
+
.max(10)
|
|
43
|
+
.default('')
|
|
44
|
+
.describe('Customer/Supplier address - house number (only for customer/supplier accounts)'),
|
|
45
|
+
// Field 1409: Customer/Supplier address - city (30) - Optional - Alphanumeric
|
|
46
|
+
customerSupplierAddressCity: zod_1.z
|
|
47
|
+
.string()
|
|
48
|
+
.max(30)
|
|
49
|
+
.default('')
|
|
50
|
+
.describe('Customer/Supplier address - city (only for customer/supplier accounts)'),
|
|
51
|
+
// Field 1410: Customer/Supplier address - ZIP (8) - Optional - Alphanumeric
|
|
52
|
+
customerSupplierAddressZip: zod_1.z
|
|
53
|
+
.string()
|
|
54
|
+
.max(8)
|
|
55
|
+
.default('')
|
|
56
|
+
.describe('Customer/Supplier address - ZIP (only for customer/supplier accounts)'),
|
|
57
|
+
// Field 1411: Customer/Supplier address - country (30) - Optional - Alphanumeric
|
|
58
|
+
customerSupplierAddressCountry: zod_1.z
|
|
59
|
+
.string()
|
|
60
|
+
.max(30)
|
|
61
|
+
.default('')
|
|
62
|
+
.describe('Customer/Supplier address - country (only for customer/supplier accounts)'),
|
|
63
|
+
// Field 1412: Country code (2) - Optional - Alphanumeric
|
|
64
|
+
countryCode: zod_1.z
|
|
65
|
+
.string()
|
|
66
|
+
.max(2)
|
|
67
|
+
.default('')
|
|
68
|
+
.describe('Country code (only for customer/supplier accounts, see Appendix 3)'),
|
|
69
|
+
// Field 1413: Parent account key (15) - Optional - Alphanumeric
|
|
70
|
+
parentAccountKey: zod_1.z.string().max(15).default('').describe('Parent account key'),
|
|
71
|
+
// Field 1414: Account opening balance (15) - Optional - Alphanumeric - Format: X9(12)V99
|
|
72
|
+
accountOpeningBalance: zod_1.z
|
|
73
|
+
.string()
|
|
74
|
+
.max(15)
|
|
75
|
+
.default('')
|
|
76
|
+
.describe('Account opening balance (positive = debit, negative = credit)'),
|
|
77
|
+
// Field 1415: Total debits (15) - Optional - Alphanumeric - Format: X9(12)V99
|
|
78
|
+
totalDebits: zod_1.z.string().max(15).default('').describe('Total debits (excludes opening balance)'),
|
|
79
|
+
// Field 1416: Total credits (15) - Optional - Alphanumeric - Format: X9(12)V99
|
|
80
|
+
totalCredits: zod_1.z.string().max(15).default('').describe('Total credits (excludes opening balance)'),
|
|
81
|
+
// Field 1417: Accounting classification code (4) - Conditional - Numeric
|
|
82
|
+
accountingClassificationCode: zod_1.z
|
|
83
|
+
.string()
|
|
84
|
+
.max(4)
|
|
85
|
+
.regex(/^$|^\d+$/)
|
|
86
|
+
.default('')
|
|
87
|
+
.describe('Accounting classification code (mandatory if 6111 report required)'),
|
|
88
|
+
// Field 1418: Reserved field (0) - Deprecated - Alphanumeric - Skipped as it has 0 length
|
|
89
|
+
// Field 1419: Supplier/Customer tax ID (9) - Conditional - Numeric
|
|
90
|
+
supplierCustomerTaxId: zod_1.z
|
|
91
|
+
.string()
|
|
92
|
+
.max(9)
|
|
93
|
+
.regex(/^$|^\d+$/)
|
|
94
|
+
.default('')
|
|
95
|
+
.describe('Supplier/Customer tax ID (required if double-entry bookkeeping, code 2 in field 1013)'),
|
|
96
|
+
// Field 1420: Reserved field (0) - Deprecated - Alphanumeric - Skipped as it has 0 length
|
|
97
|
+
// Field 1421: Branch ID (7) - Conditional - Alphanumeric
|
|
98
|
+
branchId: zod_1.z
|
|
99
|
+
.string()
|
|
100
|
+
.max(7)
|
|
101
|
+
.default('')
|
|
102
|
+
.describe('Branch ID (required if field 1034 = 1, see Note 3)'),
|
|
103
|
+
// Field 1422: Opening balance in foreign currency (15) - Optional - Alphanumeric - Format: X9(12)V99
|
|
104
|
+
openingBalanceForeignCurrency: zod_1.z
|
|
105
|
+
.string()
|
|
106
|
+
.max(15)
|
|
107
|
+
.default('')
|
|
108
|
+
.describe('Opening balance in foreign currency'),
|
|
109
|
+
// Field 1423: Foreign currency code (3) - Optional - Alphanumeric
|
|
110
|
+
foreignCurrencyCode: zod_1.z
|
|
111
|
+
.string()
|
|
112
|
+
.max(3)
|
|
113
|
+
.default('')
|
|
114
|
+
.describe('Foreign currency code (refers to field 1422, see Appendix 2)'),
|
|
115
|
+
// Field 1424: Reserved field (16) - Optional - Alphanumeric
|
|
116
|
+
reserved: zod_1.z.string().max(16).default('').describe('Reserved field for future use'),
|
|
117
|
+
});
|
|
118
|
+
/**
|
|
119
|
+
* Encodes a B110 record to fixed-width string format
|
|
120
|
+
* Total line width: 376 characters + CRLF
|
|
121
|
+
*/
|
|
122
|
+
function encodeB110(input) {
|
|
123
|
+
const fields = [
|
|
124
|
+
(0, encoder_js_1.formatField)(input.code, 4, 'left'), // Field 1400: Record code (4)
|
|
125
|
+
(0, encoder_js_1.formatNumericField)(input.recordNumber, 9), // Field 1401: Record number (9)
|
|
126
|
+
(0, encoder_js_1.formatNumericField)(input.vatId, 9), // Field 1402: VAT ID (9)
|
|
127
|
+
(0, encoder_js_1.formatField)(input.accountKey, 15, 'left'), // Field 1403: Account key (15)
|
|
128
|
+
(0, encoder_js_1.formatField)(input.accountName, 50, 'left'), // Field 1404: Account name (50)
|
|
129
|
+
(0, encoder_js_1.formatField)(input.trialBalanceCode, 15, 'left'), // Field 1405: Trial balance code (15)
|
|
130
|
+
(0, encoder_js_1.formatField)(input.trialBalanceCodeDescription, 30, 'left'), // Field 1406: Trial balance code description (30)
|
|
131
|
+
(0, encoder_js_1.formatField)(input.customerSupplierAddressStreet, 50, 'left'), // Field 1407: Customer/Supplier address - street (50)
|
|
132
|
+
(0, encoder_js_1.formatField)(input.customerSupplierAddressHouseNumber, 10, 'left'), // Field 1408: Customer/Supplier address - house number (10)
|
|
133
|
+
(0, encoder_js_1.formatField)(input.customerSupplierAddressCity, 30, 'left'), // Field 1409: Customer/Supplier address - city (30)
|
|
134
|
+
(0, encoder_js_1.formatField)(input.customerSupplierAddressZip, 8, 'left'), // Field 1410: Customer/Supplier address - ZIP (8)
|
|
135
|
+
(0, encoder_js_1.formatField)(input.customerSupplierAddressCountry, 30, 'left'), // Field 1411: Customer/Supplier address - country (30)
|
|
136
|
+
(0, encoder_js_1.formatField)(input.countryCode, 2, 'left'), // Field 1412: Country code (2)
|
|
137
|
+
(0, encoder_js_1.formatField)(input.parentAccountKey, 15, 'left'), // Field 1413: Parent account key (15)
|
|
138
|
+
(0, encoder_js_1.formatField)(input.accountOpeningBalance, 15, 'right'), // Field 1414: Account opening balance (15) - right-aligned for amount
|
|
139
|
+
(0, encoder_js_1.formatField)(input.totalDebits, 15, 'right'), // Field 1415: Total debits (15) - right-aligned for amount
|
|
140
|
+
(0, encoder_js_1.formatField)(input.totalCredits, 15, 'right'), // Field 1416: Total credits (15) - right-aligned for amount
|
|
141
|
+
(0, encoder_js_1.formatNumericField)(input.accountingClassificationCode, 4), // Field 1417: Accounting classification code (4)
|
|
142
|
+
// Field 1418: Reserved field (0) - skipped as it has 0 length
|
|
143
|
+
(0, encoder_js_1.formatNumericField)(input.supplierCustomerTaxId, 9), // Field 1419: Supplier/Customer tax ID (9)
|
|
144
|
+
// Field 1420: Reserved field (0) - skipped as it has 0 length
|
|
145
|
+
(0, encoder_js_1.formatField)(input.branchId, 7, 'left'), // Field 1421: Branch ID (7)
|
|
146
|
+
(0, encoder_js_1.formatField)(input.openingBalanceForeignCurrency, 15, 'right'), // Field 1422: Opening balance in foreign currency (15) - right-aligned for amount
|
|
147
|
+
(0, encoder_js_1.formatField)(input.foreignCurrencyCode, 3, 'left'), // Field 1423: Foreign currency code (3)
|
|
148
|
+
(0, encoder_js_1.formatField)(input.reserved, 16, 'left'), // Field 1424: Reserved field (16)
|
|
149
|
+
];
|
|
150
|
+
return fields.join('') + index_js_1.CRLF;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Parses a fixed-width B110 record line back to object
|
|
154
|
+
* Expected line length: 376 characters (excluding CRLF)
|
|
155
|
+
*/
|
|
156
|
+
function parseB110(line) {
|
|
157
|
+
// Remove CRLF if present
|
|
158
|
+
const cleanLine = line.replace(/\r?\n$/, '');
|
|
159
|
+
if (cleanLine.length !== 376) {
|
|
160
|
+
throw new Error(`Invalid B110 record length: expected 376 characters, got ${cleanLine.length}`);
|
|
161
|
+
}
|
|
162
|
+
// Extract fields at their fixed positions
|
|
163
|
+
let pos = 0;
|
|
164
|
+
const code = cleanLine.slice(pos, pos + 4).trim();
|
|
165
|
+
pos += 4;
|
|
166
|
+
const recordNumber = cleanLine
|
|
167
|
+
.slice(pos, pos + 9)
|
|
168
|
+
.trim()
|
|
169
|
+
.replace(/^0+/, '') || '0';
|
|
170
|
+
pos += 9;
|
|
171
|
+
const vatId = cleanLine
|
|
172
|
+
.slice(pos, pos + 9)
|
|
173
|
+
.trim()
|
|
174
|
+
.replace(/^0+/, '') || '0';
|
|
175
|
+
pos += 9;
|
|
176
|
+
const accountKey = cleanLine.slice(pos, pos + 15).trim();
|
|
177
|
+
pos += 15;
|
|
178
|
+
const accountName = cleanLine.slice(pos, pos + 50).trim();
|
|
179
|
+
pos += 50;
|
|
180
|
+
const trialBalanceCode = cleanLine.slice(pos, pos + 15).trim();
|
|
181
|
+
pos += 15;
|
|
182
|
+
const trialBalanceCodeDescription = cleanLine.slice(pos, pos + 30).trim();
|
|
183
|
+
pos += 30;
|
|
184
|
+
const customerSupplierAddressStreet = cleanLine.slice(pos, pos + 50).trim();
|
|
185
|
+
pos += 50;
|
|
186
|
+
const customerSupplierAddressHouseNumber = cleanLine.slice(pos, pos + 10).trim();
|
|
187
|
+
pos += 10;
|
|
188
|
+
const customerSupplierAddressCity = cleanLine.slice(pos, pos + 30).trim();
|
|
189
|
+
pos += 30;
|
|
190
|
+
const customerSupplierAddressZip = cleanLine.slice(pos, pos + 8).trim();
|
|
191
|
+
pos += 8;
|
|
192
|
+
const customerSupplierAddressCountry = cleanLine.slice(pos, pos + 30).trim();
|
|
193
|
+
pos += 30;
|
|
194
|
+
const countryCode = cleanLine.slice(pos, pos + 2).trim();
|
|
195
|
+
pos += 2;
|
|
196
|
+
const parentAccountKey = cleanLine.slice(pos, pos + 15).trim();
|
|
197
|
+
pos += 15;
|
|
198
|
+
const accountOpeningBalance = cleanLine.slice(pos, pos + 15).trim();
|
|
199
|
+
pos += 15;
|
|
200
|
+
const totalDebits = cleanLine.slice(pos, pos + 15).trim();
|
|
201
|
+
pos += 15;
|
|
202
|
+
const totalCredits = cleanLine.slice(pos, pos + 15).trim();
|
|
203
|
+
pos += 15;
|
|
204
|
+
const accountingClassificationCode = cleanLine
|
|
205
|
+
.slice(pos, pos + 4)
|
|
206
|
+
.trim()
|
|
207
|
+
.replace(/^0+/, '') || '';
|
|
208
|
+
pos += 4;
|
|
209
|
+
// Field 1418: Reserved field (0) - skipped as it has 0 length
|
|
210
|
+
const supplierCustomerTaxId = cleanLine
|
|
211
|
+
.slice(pos, pos + 9)
|
|
212
|
+
.trim()
|
|
213
|
+
.replace(/^0+/, '') || '';
|
|
214
|
+
pos += 9;
|
|
215
|
+
// Field 1420: Reserved field (0) - skipped as it has 0 length
|
|
216
|
+
const branchId = cleanLine.slice(pos, pos + 7).trim();
|
|
217
|
+
pos += 7;
|
|
218
|
+
const openingBalanceForeignCurrency = cleanLine.slice(pos, pos + 15).trim();
|
|
219
|
+
pos += 15;
|
|
220
|
+
const foreignCurrencyCode = cleanLine.slice(pos, pos + 3).trim();
|
|
221
|
+
pos += 3;
|
|
222
|
+
const reserved = cleanLine.slice(pos, pos + 16).trim();
|
|
223
|
+
pos += 16;
|
|
224
|
+
// Validate the code field
|
|
225
|
+
if (code !== 'B110') {
|
|
226
|
+
throw new Error(`Invalid B110 record code: expected "B110", got "${code}"`);
|
|
227
|
+
}
|
|
228
|
+
const parsed = {
|
|
229
|
+
code,
|
|
230
|
+
recordNumber,
|
|
231
|
+
vatId,
|
|
232
|
+
accountKey,
|
|
233
|
+
accountName,
|
|
234
|
+
trialBalanceCode,
|
|
235
|
+
trialBalanceCodeDescription,
|
|
236
|
+
customerSupplierAddressStreet,
|
|
237
|
+
customerSupplierAddressHouseNumber,
|
|
238
|
+
customerSupplierAddressCity,
|
|
239
|
+
customerSupplierAddressZip,
|
|
240
|
+
customerSupplierAddressCountry,
|
|
241
|
+
countryCode,
|
|
242
|
+
parentAccountKey,
|
|
243
|
+
accountOpeningBalance,
|
|
244
|
+
totalDebits,
|
|
245
|
+
totalCredits,
|
|
246
|
+
accountingClassificationCode,
|
|
247
|
+
supplierCustomerTaxId,
|
|
248
|
+
branchId,
|
|
249
|
+
openingBalanceForeignCurrency,
|
|
250
|
+
foreignCurrencyCode,
|
|
251
|
+
reserved,
|
|
252
|
+
};
|
|
253
|
+
// Validate against schema
|
|
254
|
+
return exports.B110Schema.parse(parsed);
|
|
255
|
+
}
|