@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.
Files changed (269) hide show
  1. package/README.md +366 -13
  2. package/dist/README.md +476 -0
  3. package/dist/cjs/api/generate-report-legacy.js +6 -0
  4. package/dist/cjs/api/generate-report.js +328 -0
  5. package/dist/cjs/constants.js +11 -0
  6. package/dist/cjs/generator/format/encoder.js +86 -0
  7. package/dist/cjs/generator/records/a000-sum.js +66 -0
  8. package/dist/cjs/generator/records/a000.js +349 -0
  9. package/dist/cjs/generator/records/a100.js +107 -0
  10. package/dist/cjs/generator/records/b100.js +305 -0
  11. package/dist/cjs/generator/records/b110.js +255 -0
  12. package/dist/cjs/generator/records/c100.js +338 -0
  13. package/dist/cjs/generator/records/d110.js +272 -0
  14. package/dist/cjs/generator/records/d120.js +278 -0
  15. package/{cjs → dist/cjs}/generator/records/index.js +1 -0
  16. package/dist/cjs/generator/records/m100.js +177 -0
  17. package/dist/cjs/generator/records/z900.js +93 -0
  18. package/{cjs → dist/cjs}/index.js +3 -0
  19. package/dist/cjs/records/a100.js +78 -0
  20. package/dist/cjs/records/index.js +20 -0
  21. package/dist/cjs/records/z900.js +82 -0
  22. package/dist/cjs/types/enums.js +457 -0
  23. package/{cjs → dist/cjs}/types/index.js +6 -1
  24. package/dist/cjs/utils/file-helpers.js +198 -0
  25. package/dist/cjs/utils/index.js +8 -0
  26. package/dist/cjs/utils/key-generator.js +71 -0
  27. package/dist/esm/api/generate-report-legacy.js +2 -0
  28. package/dist/esm/api/generate-report.js +325 -0
  29. package/dist/esm/constants.js +8 -0
  30. package/dist/esm/generator/format/encoder.js +77 -0
  31. package/dist/esm/generator/records/a000-sum.js +61 -0
  32. package/dist/esm/generator/records/a000.js +344 -0
  33. package/dist/esm/generator/records/a100.js +102 -0
  34. package/dist/esm/generator/records/b100.js +300 -0
  35. package/dist/esm/generator/records/b110.js +250 -0
  36. package/dist/esm/generator/records/c100.js +333 -0
  37. package/dist/esm/generator/records/d110.js +267 -0
  38. package/dist/esm/generator/records/d120.js +273 -0
  39. package/{esm → dist/esm}/generator/records/index.js +1 -0
  40. package/dist/esm/generator/records/m100.js +172 -0
  41. package/dist/esm/generator/records/z900.js +88 -0
  42. package/{esm → dist/esm}/index.js +3 -0
  43. package/dist/esm/records/a100.js +73 -0
  44. package/dist/esm/records/index.js +11 -0
  45. package/dist/esm/records/z900.js +77 -0
  46. package/dist/esm/types/enums.js +454 -0
  47. package/{esm → dist/esm}/types/index.js +5 -1
  48. package/dist/esm/utils/file-helpers.js +188 -0
  49. package/dist/esm/utils/index.js +5 -0
  50. package/dist/esm/utils/key-generator.js +65 -0
  51. package/dist/package.json +54 -0
  52. package/dist/typings/api/generate-report-legacy.d.cts +1 -0
  53. package/dist/typings/api/generate-report-legacy.d.ts +1 -0
  54. package/dist/typings/constants.d.cts +8 -0
  55. package/dist/typings/constants.d.ts +8 -0
  56. package/dist/typings/generator/format/encoder.d.cts +57 -0
  57. package/dist/typings/generator/format/encoder.d.ts +57 -0
  58. package/dist/typings/generator/records/a000-sum.d.cts +40 -0
  59. package/dist/typings/generator/records/a000-sum.d.ts +40 -0
  60. package/dist/typings/generator/records/a000.d.cts +238 -0
  61. package/dist/typings/generator/records/a000.d.ts +238 -0
  62. package/dist/typings/generator/records/a100.d.cts +59 -0
  63. package/dist/typings/generator/records/a100.d.ts +59 -0
  64. package/dist/typings/generator/records/b100.d.cts +101 -0
  65. package/dist/typings/generator/records/b100.d.ts +101 -0
  66. package/dist/typings/generator/records/b110.d.cts +89 -0
  67. package/dist/typings/generator/records/b110.d.ts +89 -0
  68. package/dist/typings/generator/records/c100.d.cts +133 -0
  69. package/dist/typings/generator/records/c100.d.ts +133 -0
  70. package/dist/typings/generator/records/d110.d.cts +98 -0
  71. package/dist/typings/generator/records/d110.d.ts +98 -0
  72. package/dist/typings/generator/records/d120.d.cts +95 -0
  73. package/dist/typings/generator/records/d120.d.ts +95 -0
  74. package/{typings → dist/typings}/generator/records/index.d.cts +1 -0
  75. package/{typings → dist/typings}/generator/records/index.d.ts +1 -0
  76. package/dist/typings/generator/records/m100.d.cts +69 -0
  77. package/dist/typings/generator/records/m100.d.ts +69 -0
  78. package/dist/typings/generator/records/z900.d.cts +61 -0
  79. package/dist/typings/generator/records/z900.d.ts +61 -0
  80. package/{typings → dist/typings}/index.d.cts +3 -0
  81. package/{typings → dist/typings}/index.d.ts +3 -0
  82. package/dist/typings/records/a100.d.cts +35 -0
  83. package/dist/typings/records/a100.d.ts +35 -0
  84. package/dist/typings/records/index.d.cts +2 -0
  85. package/dist/typings/records/index.d.ts +2 -0
  86. package/dist/typings/records/z900.d.cts +38 -0
  87. package/dist/typings/records/z900.d.ts +38 -0
  88. package/dist/typings/types/enums.d.cts +162 -0
  89. package/dist/typings/types/enums.d.ts +162 -0
  90. package/{typings → dist/typings}/types/index.d.cts +17 -14
  91. package/{typings → dist/typings}/types/index.d.ts +17 -14
  92. package/dist/typings/utils/file-helpers.d.cts +131 -0
  93. package/dist/typings/utils/file-helpers.d.ts +131 -0
  94. package/dist/typings/utils/index.d.cts +5 -0
  95. package/dist/typings/utils/index.d.ts +5 -0
  96. package/dist/typings/utils/key-generator.d.cts +41 -0
  97. package/dist/typings/utils/key-generator.d.ts +41 -0
  98. package/documentation/IncomeTax_IncomeTaxSoftwareHousesInfo_horaot1.31_2_05.pdf +0 -0
  99. package/documentation/_4D6963726F736F667420576F7264202D20F8E5E0E9ED20F8E7E5F720F8E5E0E9ED20F9F7E5F32E646F63_.pdf +0 -0
  100. package/documentation/a000-sum.csv +3 -0
  101. package/documentation/a000.csv +37 -0
  102. package/documentation/a100.csv +7 -0
  103. package/documentation/b100.csv +29 -0
  104. package/documentation/b110.csv +26 -0
  105. package/documentation/c100.csv +37 -0
  106. package/documentation/d110.csv +27 -0
  107. package/documentation/d120.csv +26 -0
  108. package/documentation/m100.csv +17 -0
  109. package/documentation/z900.csv +8 -0
  110. package/package.json +50 -29
  111. package/prompt_plan.md +259 -0
  112. package/spec.md +206 -0
  113. package/src/api/generate-report.ts +366 -0
  114. package/src/api/parse-files.ts +33 -0
  115. package/src/constants.ts +9 -0
  116. package/src/format/index.ts +6 -0
  117. package/src/format/newline.ts +8 -0
  118. package/src/format/padding.ts +39 -0
  119. package/src/generator/format/decoder.ts +15 -0
  120. package/src/generator/format/encoder.ts +95 -0
  121. package/src/generator/format/index.ts +6 -0
  122. package/src/generator/index.ts +6 -0
  123. package/src/generator/records/a000-sum.ts +78 -0
  124. package/src/generator/records/a000.ts +373 -0
  125. package/src/generator/records/a100.ts +118 -0
  126. package/src/generator/records/b100.ts +317 -0
  127. package/src/generator/records/b110.ts +267 -0
  128. package/src/generator/records/c100.ts +347 -0
  129. package/src/generator/records/d110.ts +286 -0
  130. package/src/generator/records/d120.ts +293 -0
  131. package/src/generator/records/index.ts +14 -0
  132. package/src/generator/records/m100.ts +185 -0
  133. package/src/generator/records/z900.ts +104 -0
  134. package/src/index.ts +18 -0
  135. package/src/parser/data-parser.ts +14 -0
  136. package/src/parser/index.ts +6 -0
  137. package/src/parser/ini-parser.ts +14 -0
  138. package/src/types/enums.ts +531 -0
  139. package/src/types/index.ts +110 -0
  140. package/src/utils/file-helpers.ts +221 -0
  141. package/src/utils/index.ts +6 -0
  142. package/src/utils/key-generator.ts +75 -0
  143. package/src/validation/errors.ts +35 -0
  144. package/src/validation/index.ts +6 -0
  145. package/src/validation/validate-input.ts +67 -0
  146. package/tests/debug-output.test.ts +81 -0
  147. package/tests/format/crlf-join.test.ts +124 -0
  148. package/tests/format/encoder.test.ts +80 -0
  149. package/tests/format/newline.test.ts +19 -0
  150. package/tests/format/padding.test.ts +74 -0
  151. package/tests/index.test.ts +29 -0
  152. package/tests/ini-text.test.ts +122 -0
  153. package/tests/integration/comprehensive.integration.test.ts +350 -0
  154. package/tests/integration/roundtrip.integration.test.ts +377 -0
  155. package/tests/records/a000-sum.test.ts +278 -0
  156. package/tests/records/a000.test.ts +318 -0
  157. package/tests/records/a100.test.ts +239 -0
  158. package/tests/records/b100.test.ts +419 -0
  159. package/tests/records/b110.test.ts +445 -0
  160. package/tests/records/c100.test.ts +333 -0
  161. package/tests/records/d110.test.ts +93 -0
  162. package/tests/records/d120.test.ts +275 -0
  163. package/tests/records/m100.test.ts +437 -0
  164. package/tests/records/z900.test.ts +254 -0
  165. package/tests/types/enums.test.ts +290 -0
  166. package/tests/utils/file-helpers.test.ts +276 -0
  167. package/tests/utils/key-generator.test.ts +121 -0
  168. package/tests/validation/document-type-validation.test.ts +521 -0
  169. package/tests/validation/validate-input.test.ts +219 -0
  170. package/todo.md +203 -0
  171. package/tsconfig.json +10 -0
  172. package/vitest.config.ts +11 -0
  173. package/cjs/api/generate-report.js +0 -53
  174. package/cjs/generator/format/encoder.js +0 -46
  175. package/cjs/generator/records/a000.js +0 -8
  176. package/cjs/generator/records/a100.js +0 -8
  177. package/cjs/generator/records/b100.js +0 -8
  178. package/cjs/generator/records/b110.js +0 -8
  179. package/cjs/generator/records/c100.js +0 -8
  180. package/cjs/generator/records/d110.js +0 -8
  181. package/cjs/generator/records/d120.js +0 -8
  182. package/cjs/generator/records/m100.js +0 -8
  183. package/cjs/generator/records/z900.js +0 -8
  184. package/esm/api/generate-report.js +0 -50
  185. package/esm/generator/format/encoder.js +0 -42
  186. package/esm/generator/records/a000.js +0 -5
  187. package/esm/generator/records/a100.js +0 -5
  188. package/esm/generator/records/b100.js +0 -5
  189. package/esm/generator/records/b110.js +0 -5
  190. package/esm/generator/records/c100.js +0 -5
  191. package/esm/generator/records/d110.js +0 -5
  192. package/esm/generator/records/d120.js +0 -5
  193. package/esm/generator/records/m100.js +0 -5
  194. package/esm/generator/records/z900.js +0 -5
  195. package/typings/generator/format/encoder.d.cts +0 -33
  196. package/typings/generator/format/encoder.d.ts +0 -33
  197. package/typings/generator/records/a000.d.cts +0 -4
  198. package/typings/generator/records/a000.d.ts +0 -4
  199. package/typings/generator/records/a100.d.cts +0 -4
  200. package/typings/generator/records/a100.d.ts +0 -4
  201. package/typings/generator/records/b100.d.cts +0 -4
  202. package/typings/generator/records/b100.d.ts +0 -4
  203. package/typings/generator/records/b110.d.cts +0 -4
  204. package/typings/generator/records/b110.d.ts +0 -4
  205. package/typings/generator/records/c100.d.cts +0 -4
  206. package/typings/generator/records/c100.d.ts +0 -4
  207. package/typings/generator/records/d110.d.cts +0 -4
  208. package/typings/generator/records/d110.d.ts +0 -4
  209. package/typings/generator/records/d120.d.cts +0 -4
  210. package/typings/generator/records/d120.d.ts +0 -4
  211. package/typings/generator/records/m100.d.cts +0 -4
  212. package/typings/generator/records/m100.d.ts +0 -4
  213. package/typings/generator/records/z900.d.cts +0 -4
  214. package/typings/generator/records/z900.d.ts +0 -4
  215. /package/{cjs → dist/cjs}/api/parse-files.js +0 -0
  216. /package/{cjs → dist/cjs}/format/index.js +0 -0
  217. /package/{cjs → dist/cjs}/format/newline.js +0 -0
  218. /package/{cjs → dist/cjs}/format/padding.js +0 -0
  219. /package/{cjs → dist/cjs}/generator/format/decoder.js +0 -0
  220. /package/{cjs → dist/cjs}/generator/format/index.js +0 -0
  221. /package/{cjs → dist/cjs}/generator/index.js +0 -0
  222. /package/{cjs → dist/cjs}/package.json +0 -0
  223. /package/{cjs → dist/cjs}/parser/data-parser.js +0 -0
  224. /package/{cjs → dist/cjs}/parser/index.js +0 -0
  225. /package/{cjs → dist/cjs}/parser/ini-parser.js +0 -0
  226. /package/{cjs → dist/cjs}/validation/errors.js +0 -0
  227. /package/{cjs → dist/cjs}/validation/index.js +0 -0
  228. /package/{cjs → dist/cjs}/validation/validate-input.js +0 -0
  229. /package/{esm → dist/esm}/api/parse-files.js +0 -0
  230. /package/{esm → dist/esm}/format/index.js +0 -0
  231. /package/{esm → dist/esm}/format/newline.js +0 -0
  232. /package/{esm → dist/esm}/format/padding.js +0 -0
  233. /package/{esm → dist/esm}/generator/format/decoder.js +0 -0
  234. /package/{esm → dist/esm}/generator/format/index.js +0 -0
  235. /package/{esm → dist/esm}/generator/index.js +0 -0
  236. /package/{esm → dist/esm}/parser/data-parser.js +0 -0
  237. /package/{esm → dist/esm}/parser/index.js +0 -0
  238. /package/{esm → dist/esm}/parser/ini-parser.js +0 -0
  239. /package/{esm → dist/esm}/validation/errors.js +0 -0
  240. /package/{esm → dist/esm}/validation/index.js +0 -0
  241. /package/{esm → dist/esm}/validation/validate-input.js +0 -0
  242. /package/{typings → dist/typings}/api/generate-report.d.cts +0 -0
  243. /package/{typings → dist/typings}/api/generate-report.d.ts +0 -0
  244. /package/{typings → dist/typings}/api/parse-files.d.cts +0 -0
  245. /package/{typings → dist/typings}/api/parse-files.d.ts +0 -0
  246. /package/{typings → dist/typings}/format/index.d.cts +0 -0
  247. /package/{typings → dist/typings}/format/index.d.ts +0 -0
  248. /package/{typings → dist/typings}/format/newline.d.cts +0 -0
  249. /package/{typings → dist/typings}/format/newline.d.ts +0 -0
  250. /package/{typings → dist/typings}/format/padding.d.cts +0 -0
  251. /package/{typings → dist/typings}/format/padding.d.ts +0 -0
  252. /package/{typings → dist/typings}/generator/format/decoder.d.cts +0 -0
  253. /package/{typings → dist/typings}/generator/format/decoder.d.ts +0 -0
  254. /package/{typings → dist/typings}/generator/format/index.d.cts +0 -0
  255. /package/{typings → dist/typings}/generator/format/index.d.ts +0 -0
  256. /package/{typings → dist/typings}/generator/index.d.cts +0 -0
  257. /package/{typings → dist/typings}/generator/index.d.ts +0 -0
  258. /package/{typings → dist/typings}/parser/data-parser.d.cts +0 -0
  259. /package/{typings → dist/typings}/parser/data-parser.d.ts +0 -0
  260. /package/{typings → dist/typings}/parser/index.d.cts +0 -0
  261. /package/{typings → dist/typings}/parser/index.d.ts +0 -0
  262. /package/{typings → dist/typings}/parser/ini-parser.d.cts +0 -0
  263. /package/{typings → dist/typings}/parser/ini-parser.d.ts +0 -0
  264. /package/{typings → dist/typings}/validation/errors.d.cts +0 -0
  265. /package/{typings → dist/typings}/validation/errors.d.ts +0 -0
  266. /package/{typings → dist/typings}/validation/index.d.cts +0 -0
  267. /package/{typings → dist/typings}/validation/index.d.ts +0 -0
  268. /package/{typings → dist/typings}/validation/validate-input.d.cts +0 -0
  269. /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
+ }