@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,328 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Main API for generating SHAAM uniform format reports
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.generateUniformFormatReport = generateUniformFormatReport;
|
|
7
|
+
const encoder_js_1 = require("../generator/format/encoder.js");
|
|
8
|
+
const index_js_1 = require("../generator/records/index.js");
|
|
9
|
+
const errors_js_1 = require("../validation/errors.js");
|
|
10
|
+
const validate_input_js_1 = require("../validation/validate-input.js");
|
|
11
|
+
/**
|
|
12
|
+
* Generates SHAAM uniform format report files (INI.TXT and BKMVDATA.TXT)
|
|
13
|
+
* from a high-level JSON input object.
|
|
14
|
+
*
|
|
15
|
+
* @param input - The report input data
|
|
16
|
+
* @param options - Generation options
|
|
17
|
+
* @returns Report output with generated file content
|
|
18
|
+
*/
|
|
19
|
+
function generateUniformFormatReport(input, options = {}) {
|
|
20
|
+
// Validate input data first
|
|
21
|
+
const validationMode = options.validationMode || 'fail-fast';
|
|
22
|
+
const validationErrors = (0, validate_input_js_1.validateInput)(input, validationMode);
|
|
23
|
+
if (validationErrors.length > 0) {
|
|
24
|
+
if (validationMode === 'fail-fast') {
|
|
25
|
+
// This should have already thrown, but just in case
|
|
26
|
+
throw new errors_js_1.ShaamFormatError('Validation failed', validationErrors);
|
|
27
|
+
}
|
|
28
|
+
// For collect-all mode, we still throw if there are errors
|
|
29
|
+
// The user can catch and inspect the errors if needed
|
|
30
|
+
throw new errors_js_1.ShaamFormatError('Input validation failed', validationErrors);
|
|
31
|
+
}
|
|
32
|
+
const records = [];
|
|
33
|
+
const iniRecords = [];
|
|
34
|
+
const recordCounts = {};
|
|
35
|
+
let recordNumber = 1;
|
|
36
|
+
// Helper function to count and add data record
|
|
37
|
+
const addRecord = (recordType, recordContent) => {
|
|
38
|
+
records.push(recordContent);
|
|
39
|
+
recordCounts[recordType] = (recordCounts[recordType] || 0) + 1;
|
|
40
|
+
recordNumber++;
|
|
41
|
+
};
|
|
42
|
+
// Helper function to add INI record
|
|
43
|
+
const addIniRecord = (recordType, recordContent) => {
|
|
44
|
+
iniRecords.push(recordContent);
|
|
45
|
+
recordCounts[recordType] = (recordCounts[recordType] || 0) + 1;
|
|
46
|
+
};
|
|
47
|
+
// Generate A000 record for INI.TXT
|
|
48
|
+
const fileHeaderRecord = {
|
|
49
|
+
reservedFuture: '',
|
|
50
|
+
totalRecords: '0', // Will be updated later with actual count
|
|
51
|
+
vatId: input.business.taxId,
|
|
52
|
+
softwareRegNumber: '12345678', // TODO: Use actual software registration number
|
|
53
|
+
softwareName: 'SHAAM Generator',
|
|
54
|
+
softwareVersion: '1.0.0',
|
|
55
|
+
vendorVatId: '123456789', // TODO: Use actual vendor VAT ID
|
|
56
|
+
vendorName: 'Accounter',
|
|
57
|
+
softwareType: '2', // Multi-year software
|
|
58
|
+
fileOutputPath: options.fileNameBase || 'report',
|
|
59
|
+
accountingType: '2', // Double-entry accounting
|
|
60
|
+
balanceRequired: '1',
|
|
61
|
+
companyRegId: '',
|
|
62
|
+
withholdingFileNum: '',
|
|
63
|
+
reserved1017: '',
|
|
64
|
+
businessName: input.business.name,
|
|
65
|
+
businessStreet: '',
|
|
66
|
+
businessHouseNum: '',
|
|
67
|
+
businessCity: '',
|
|
68
|
+
businessZip: '',
|
|
69
|
+
taxYear: '',
|
|
70
|
+
startDate: input.business.reportingPeriod.startDate.replace(/-/g, ''),
|
|
71
|
+
endDate: input.business.reportingPeriod.endDate.replace(/-/g, ''),
|
|
72
|
+
processStartDate: new Date().toISOString().slice(0, 10).replace(/-/g, ''),
|
|
73
|
+
processStartTime: new Date().toTimeString().slice(0, 5).replace(':', ''),
|
|
74
|
+
languageCode: '0', // Hebrew
|
|
75
|
+
characterEncoding: '1', // ISO-8859-8-i
|
|
76
|
+
compressionSoftware: '',
|
|
77
|
+
reserved1031: '',
|
|
78
|
+
baseCurrency: 'ILS',
|
|
79
|
+
reserved1033: '',
|
|
80
|
+
branchInfoFlag: '0', // No branches for now
|
|
81
|
+
reserved1035: '',
|
|
82
|
+
};
|
|
83
|
+
addIniRecord('A000', (0, index_js_1.encodeA000)(fileHeaderRecord));
|
|
84
|
+
// Add A000Sum records for each record type to INI.TXT
|
|
85
|
+
// Calculate expected counts based on input data
|
|
86
|
+
const expectedCounts = {
|
|
87
|
+
A100: 1,
|
|
88
|
+
C100: input.documents.length,
|
|
89
|
+
D110: input.documents.length,
|
|
90
|
+
D120: input.documents.length,
|
|
91
|
+
B100: input.journalEntries.length,
|
|
92
|
+
B110: input.accounts.length,
|
|
93
|
+
M100: input.inventory.length,
|
|
94
|
+
Z900: 1,
|
|
95
|
+
};
|
|
96
|
+
// Add summary records for each record type
|
|
97
|
+
for (const [recordType, count] of Object.entries(expectedCounts)) {
|
|
98
|
+
if (count > 0) {
|
|
99
|
+
const summaryRecord = {
|
|
100
|
+
code: recordType,
|
|
101
|
+
recordCount: count.toString(),
|
|
102
|
+
};
|
|
103
|
+
addIniRecord('A000Sum', (0, index_js_1.encodeA000Sum)(summaryRecord));
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// 1. Business metadata - A100 record
|
|
107
|
+
const businessMetadata = {
|
|
108
|
+
recordNumber: recordNumber.toString(),
|
|
109
|
+
vatId: input.business.taxId,
|
|
110
|
+
reserved: '',
|
|
111
|
+
};
|
|
112
|
+
addRecord('A100', (0, index_js_1.encodeA100)(businessMetadata));
|
|
113
|
+
// TODO: 2. Summaries... (not implemented yet)
|
|
114
|
+
// 3. For each document in input.documents
|
|
115
|
+
for (const document of input.documents) {
|
|
116
|
+
// Document header - C100 record
|
|
117
|
+
const documentRecord = {
|
|
118
|
+
code: 'C100',
|
|
119
|
+
recordNumber: recordNumber.toString(),
|
|
120
|
+
vatId: input.business.taxId,
|
|
121
|
+
documentType: document.type,
|
|
122
|
+
documentId: document.id,
|
|
123
|
+
documentIssueDate: document.date.replace(/-/g, ''), // Convert YYYY-MM-DD to YYYYMMDD
|
|
124
|
+
documentIssueTime: '',
|
|
125
|
+
customerName: '',
|
|
126
|
+
customerStreet: '',
|
|
127
|
+
customerHouseNumber: '',
|
|
128
|
+
customerCity: '',
|
|
129
|
+
customerPostCode: '',
|
|
130
|
+
customerCountry: '',
|
|
131
|
+
customerCountryCode: '',
|
|
132
|
+
customerPhone: '',
|
|
133
|
+
customerVatId: '',
|
|
134
|
+
documentValueDate: '',
|
|
135
|
+
foreignCurrencyAmount: '',
|
|
136
|
+
currencyCode: '',
|
|
137
|
+
amountBeforeDiscount: '',
|
|
138
|
+
documentDiscount: '',
|
|
139
|
+
amountAfterDiscountExcludingVat: '',
|
|
140
|
+
vatAmount: '',
|
|
141
|
+
amountIncludingVat: document.amount.toFixed(2), // Format as decimal with 2 places
|
|
142
|
+
withholdingTaxAmount: '',
|
|
143
|
+
customerKey: '',
|
|
144
|
+
matchingField: '',
|
|
145
|
+
cancelledAttribute1: '',
|
|
146
|
+
cancelledDocument: '',
|
|
147
|
+
cancelledAttribute2: '',
|
|
148
|
+
documentDate: '',
|
|
149
|
+
branchKey: '',
|
|
150
|
+
cancelledAttribute3: '',
|
|
151
|
+
actionExecutor: '',
|
|
152
|
+
lineConnectingField: '',
|
|
153
|
+
reserved: '',
|
|
154
|
+
};
|
|
155
|
+
addRecord('C100', (0, index_js_1.encodeC100)(documentRecord));
|
|
156
|
+
// Document line - D110 record
|
|
157
|
+
const documentLineRecord = {
|
|
158
|
+
code: 'D110',
|
|
159
|
+
recordNumber: recordNumber.toString(),
|
|
160
|
+
vatId: input.business.taxId,
|
|
161
|
+
documentType: document.type,
|
|
162
|
+
documentNumber: document.id,
|
|
163
|
+
lineNumber: '1',
|
|
164
|
+
baseDocumentType: '',
|
|
165
|
+
baseDocumentNumber: '',
|
|
166
|
+
transactionType: '',
|
|
167
|
+
internalCatalogCode: '',
|
|
168
|
+
goodsServiceDescription: document.description || 'Item',
|
|
169
|
+
manufacturerName: '',
|
|
170
|
+
serialNumber: '',
|
|
171
|
+
unitOfMeasureDescription: '',
|
|
172
|
+
quantity: '1',
|
|
173
|
+
unitPriceExcludingVat: '',
|
|
174
|
+
lineDiscount: '',
|
|
175
|
+
lineTotal: '',
|
|
176
|
+
vatRatePercent: '',
|
|
177
|
+
reserved1: '',
|
|
178
|
+
branchId: '1',
|
|
179
|
+
reserved2: '',
|
|
180
|
+
documentDate: document.date.replace(/-/g, ''),
|
|
181
|
+
headerLinkField: '',
|
|
182
|
+
baseDocumentBranchId: '',
|
|
183
|
+
reserved3: '',
|
|
184
|
+
};
|
|
185
|
+
addRecord('D110', (0, index_js_1.encodeD110)(documentLineRecord));
|
|
186
|
+
// Payment record - D120 record (if applicable)
|
|
187
|
+
const paymentRecord = {
|
|
188
|
+
code: 'D120',
|
|
189
|
+
recordNumber: recordNumber.toString(),
|
|
190
|
+
vatId: input.business.taxId,
|
|
191
|
+
documentType: document.type,
|
|
192
|
+
documentNumber: document.id,
|
|
193
|
+
lineNumber: '1',
|
|
194
|
+
paymentMethod: '1', // Default payment method
|
|
195
|
+
bankNumber: '',
|
|
196
|
+
branchNumber: '',
|
|
197
|
+
accountNumber: '',
|
|
198
|
+
checkNumber: '',
|
|
199
|
+
paymentDueDate: '',
|
|
200
|
+
lineAmount: document.amount.toFixed(2), // Format as decimal with 2 places
|
|
201
|
+
acquirerCode: '',
|
|
202
|
+
cardBrand: '',
|
|
203
|
+
creditTransactionType: '',
|
|
204
|
+
firstPaymentAmount: '',
|
|
205
|
+
installmentsCount: '',
|
|
206
|
+
additionalPaymentAmount: '',
|
|
207
|
+
reserved1: '',
|
|
208
|
+
branchId: '1',
|
|
209
|
+
reserved2: '',
|
|
210
|
+
documentDate: document.date.replace(/-/g, ''),
|
|
211
|
+
headerLinkField: '',
|
|
212
|
+
reserved: '',
|
|
213
|
+
};
|
|
214
|
+
addRecord('D120', (0, index_js_1.encodeD120)(paymentRecord));
|
|
215
|
+
}
|
|
216
|
+
// 4. Journal lines: for each entry and its lines
|
|
217
|
+
for (const entry of input.journalEntries) {
|
|
218
|
+
const journalRecord = {
|
|
219
|
+
code: 'B100',
|
|
220
|
+
recordNumber: recordNumber.toString(),
|
|
221
|
+
vatId: input.business.taxId,
|
|
222
|
+
transactionNumber: entry.id.replace(/\D/g, '') || '1', // Extract only digits, default to '1'
|
|
223
|
+
transactionLineNumber: '1',
|
|
224
|
+
batchNumber: '',
|
|
225
|
+
transactionType: '',
|
|
226
|
+
referenceDocument: '',
|
|
227
|
+
referenceDocumentType: '',
|
|
228
|
+
referenceDocument2: '',
|
|
229
|
+
referenceDocumentType2: '',
|
|
230
|
+
details: entry.description || '',
|
|
231
|
+
date: entry.date.replace(/-/g, ''),
|
|
232
|
+
valueDate: entry.date.replace(/-/g, ''), // Same as date for simplicity
|
|
233
|
+
accountKey: entry.accountId,
|
|
234
|
+
counterAccountKey: '',
|
|
235
|
+
debitCreditIndicator: (entry.amount >= 0 ? '1' : '2'),
|
|
236
|
+
currencyCode: '',
|
|
237
|
+
transactionAmount: Math.abs(entry.amount).toFixed(2), // Format as decimal with 2 places
|
|
238
|
+
foreignCurrencyAmount: '',
|
|
239
|
+
quantityField: '',
|
|
240
|
+
matchingField1: '',
|
|
241
|
+
matchingField2: '',
|
|
242
|
+
branchId: '',
|
|
243
|
+
entryDate: entry.date.replace(/-/g, ''),
|
|
244
|
+
operatorUsername: '',
|
|
245
|
+
reserved: '',
|
|
246
|
+
};
|
|
247
|
+
addRecord('B100', (0, index_js_1.encodeB100)(journalRecord));
|
|
248
|
+
}
|
|
249
|
+
// 5. Accounts: B110 records
|
|
250
|
+
for (const account of input.accounts) {
|
|
251
|
+
const accountRecord = {
|
|
252
|
+
code: 'B110',
|
|
253
|
+
recordNumber: recordNumber.toString(),
|
|
254
|
+
vatId: input.business.taxId,
|
|
255
|
+
accountKey: account.id,
|
|
256
|
+
accountName: account.name,
|
|
257
|
+
trialBalanceCode: account.type,
|
|
258
|
+
trialBalanceCodeDescription: account.type,
|
|
259
|
+
customerSupplierAddressStreet: '',
|
|
260
|
+
customerSupplierAddressHouseNumber: '',
|
|
261
|
+
customerSupplierAddressCity: '',
|
|
262
|
+
customerSupplierAddressZip: '',
|
|
263
|
+
customerSupplierAddressCountry: '',
|
|
264
|
+
countryCode: '',
|
|
265
|
+
parentAccountKey: '',
|
|
266
|
+
accountOpeningBalance: '0',
|
|
267
|
+
totalDebits: '0',
|
|
268
|
+
totalCredits: '0',
|
|
269
|
+
accountingClassificationCode: '',
|
|
270
|
+
supplierCustomerTaxId: '',
|
|
271
|
+
branchId: '',
|
|
272
|
+
openingBalanceForeignCurrency: '',
|
|
273
|
+
foreignCurrencyCode: '',
|
|
274
|
+
reserved: '',
|
|
275
|
+
};
|
|
276
|
+
addRecord('B110', (0, index_js_1.encodeB110)(accountRecord));
|
|
277
|
+
}
|
|
278
|
+
// 6. Inventory: M100 records
|
|
279
|
+
for (const item of input.inventory) {
|
|
280
|
+
const inventoryRecord = {
|
|
281
|
+
code: 'M100',
|
|
282
|
+
recordNumber: recordNumber.toString(),
|
|
283
|
+
vatId: input.business.taxId,
|
|
284
|
+
universalItemCode: '',
|
|
285
|
+
supplierItemCode: '',
|
|
286
|
+
internalItemCode: item.id,
|
|
287
|
+
itemName: item.name,
|
|
288
|
+
classificationCode: '',
|
|
289
|
+
classificationDescription: '',
|
|
290
|
+
unitOfMeasure: '',
|
|
291
|
+
openingStock: '0',
|
|
292
|
+
totalStockIn: '0',
|
|
293
|
+
totalStockOut: item.quantity.toString(),
|
|
294
|
+
endPeriodCostNonBonded: '',
|
|
295
|
+
endPeriodCostBonded: '',
|
|
296
|
+
reserved: '',
|
|
297
|
+
};
|
|
298
|
+
addRecord('M100', (0, index_js_1.encodeM100)(inventoryRecord));
|
|
299
|
+
}
|
|
300
|
+
// 7. Closing record: Z900
|
|
301
|
+
const closingRecord = {
|
|
302
|
+
recordNumber: recordNumber.toString(),
|
|
303
|
+
vatId: input.business.taxId,
|
|
304
|
+
totalRecords: records.length.toString(), // Count of records before Z900 is added
|
|
305
|
+
reserved: '',
|
|
306
|
+
};
|
|
307
|
+
addRecord('Z900', (0, index_js_1.encodeZ900)(closingRecord));
|
|
308
|
+
// Build iniText and dataText using the assembler
|
|
309
|
+
const iniText = (0, encoder_js_1.assembleFile)(iniRecords);
|
|
310
|
+
const dataText = (0, encoder_js_1.assembleFile)(records);
|
|
311
|
+
// Create virtual File objects
|
|
312
|
+
const iniFile = new File([iniText], `${options.fileNameBase || 'report'}.INI.TXT`, {
|
|
313
|
+
type: 'text/plain',
|
|
314
|
+
});
|
|
315
|
+
const dataFile = new File([dataText], `${options.fileNameBase || 'report'}.BKMVDATA.TXT`, {
|
|
316
|
+
type: 'text/plain',
|
|
317
|
+
});
|
|
318
|
+
return {
|
|
319
|
+
iniText,
|
|
320
|
+
dataText,
|
|
321
|
+
iniFile,
|
|
322
|
+
dataFile,
|
|
323
|
+
summary: {
|
|
324
|
+
totalRecords: records.length + iniRecords.length,
|
|
325
|
+
perType: recordCounts,
|
|
326
|
+
},
|
|
327
|
+
};
|
|
328
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* SHAAM format constants
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.SHAAM_VERSION = void 0;
|
|
7
|
+
/**
|
|
8
|
+
* SHAAM specification version identifier
|
|
9
|
+
* Used in fields 1104 (A100) and 1154 (Z900)
|
|
10
|
+
*/
|
|
11
|
+
exports.SHAAM_VERSION = '&OF1.31&';
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Fixed-width formatting utilities
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.formatField = formatField;
|
|
7
|
+
exports.encodeFixedWidth = encodeFixedWidth;
|
|
8
|
+
exports.formatNumericField = formatNumericField;
|
|
9
|
+
exports.joinFields = joinFields;
|
|
10
|
+
exports.joinRecords = joinRecords;
|
|
11
|
+
exports.joinLinesWithCRLF = joinLinesWithCRLF;
|
|
12
|
+
exports.assembleFile = assembleFile;
|
|
13
|
+
const newline_js_1 = require("../../format/newline.js");
|
|
14
|
+
const padding_js_1 = require("../../format/padding.js");
|
|
15
|
+
/**
|
|
16
|
+
* Formats a field value with specified width and alignment
|
|
17
|
+
*
|
|
18
|
+
* @param value - The value to format
|
|
19
|
+
* @param width - Target field width
|
|
20
|
+
* @param align - Alignment ('left' or 'right')
|
|
21
|
+
* @param padChar - Character to use for padding (default: space)
|
|
22
|
+
* @returns Formatted fixed-width string
|
|
23
|
+
*/
|
|
24
|
+
function formatField(value, width, align, padChar = ' ') {
|
|
25
|
+
if (align === 'left') {
|
|
26
|
+
return (0, padding_js_1.padRight)(value, width, padChar);
|
|
27
|
+
}
|
|
28
|
+
return (0, padding_js_1.padLeft)(value, width, padChar);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Encodes a value to fixed-width format with padding
|
|
32
|
+
*
|
|
33
|
+
* @param value - The value to encode
|
|
34
|
+
* @param width - Target width
|
|
35
|
+
* @param padChar - Padding character (default: space)
|
|
36
|
+
* @param align - Alignment ('left' or 'right')
|
|
37
|
+
* @returns Fixed-width encoded string
|
|
38
|
+
*/
|
|
39
|
+
function encodeFixedWidth(value, width, padChar = ' ', align = 'left') {
|
|
40
|
+
const str = String(value);
|
|
41
|
+
return formatField(str, width, align, padChar);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Helper function to format numeric fields with zero padding
|
|
45
|
+
*/
|
|
46
|
+
function formatNumericField(value, width) {
|
|
47
|
+
return (0, padding_js_1.padLeft)(value, width, '0');
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Joins an array of field values into a single record line with CRLF ending
|
|
51
|
+
* This is used by individual record encoders to create their output
|
|
52
|
+
*
|
|
53
|
+
* @param fields - Array of formatted field values
|
|
54
|
+
* @returns Single record line ending with CRLF
|
|
55
|
+
*/
|
|
56
|
+
function joinFields(fields) {
|
|
57
|
+
return fields.join('') + newline_js_1.CRLF;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Joins an array of record lines that already have CRLF endings
|
|
61
|
+
*
|
|
62
|
+
* @param lines - Array of record lines to join (each line should already end with CRLF)
|
|
63
|
+
* @returns Joined string
|
|
64
|
+
*/
|
|
65
|
+
function joinRecords(lines) {
|
|
66
|
+
return lines.join('');
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Joins an array of record lines and adds CRLF to each line
|
|
70
|
+
*
|
|
71
|
+
* @param lines - Array of record lines to join (without CRLF endings)
|
|
72
|
+
* @returns Joined string with CRLF line endings
|
|
73
|
+
*/
|
|
74
|
+
function joinLinesWithCRLF(lines) {
|
|
75
|
+
return lines.map(line => line + newline_js_1.CRLF).join('');
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Creates a complete SHAAM format file by joining records
|
|
79
|
+
* This is the main function for assembling final file content
|
|
80
|
+
*
|
|
81
|
+
* @param records - Array of encoded record strings (each already ending with CRLF)
|
|
82
|
+
* @returns Complete file content ready for output
|
|
83
|
+
*/
|
|
84
|
+
function assembleFile(records) {
|
|
85
|
+
return joinRecords(records);
|
|
86
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.A000SumInputSchema = exports.A000SumSchema = void 0;
|
|
4
|
+
exports.encodeA000Sum = encodeA000Sum;
|
|
5
|
+
exports.parseA000Sum = parseA000Sum;
|
|
6
|
+
const zod_1 = require("zod");
|
|
7
|
+
const encoder_js_1 = require("../format/encoder.js");
|
|
8
|
+
/**
|
|
9
|
+
* A000Sum Record Schema - Record count summary for INI.TXT
|
|
10
|
+
* Fields 1050-1051 based on SHAAM uniform format specification
|
|
11
|
+
*/
|
|
12
|
+
exports.A000SumSchema = zod_1.z.object({
|
|
13
|
+
// Field 1050: Record Code (4) - Required - Alphanumeric
|
|
14
|
+
code: zod_1.z.string().min(1).max(4).describe('Record type code being summarized'),
|
|
15
|
+
// Field 1051: Record Count (15) - Required - Numeric
|
|
16
|
+
recordCount: zod_1.z
|
|
17
|
+
.string()
|
|
18
|
+
.min(1)
|
|
19
|
+
.max(15)
|
|
20
|
+
.regex(/^\d+$/)
|
|
21
|
+
.describe('Total number of records of this type'),
|
|
22
|
+
});
|
|
23
|
+
/**
|
|
24
|
+
* A000Sum Input Schema - for user input (no auto-generated fields)
|
|
25
|
+
*/
|
|
26
|
+
exports.A000SumInputSchema = exports.A000SumSchema;
|
|
27
|
+
/**
|
|
28
|
+
* Encodes an A000Sum record to fixed-width string format
|
|
29
|
+
* Total line width: 19 characters + CRLF
|
|
30
|
+
*/
|
|
31
|
+
function encodeA000Sum(input) {
|
|
32
|
+
const fullRecord = {
|
|
33
|
+
...input,
|
|
34
|
+
};
|
|
35
|
+
const fields = [
|
|
36
|
+
(0, encoder_js_1.formatField)(fullRecord.code, 4, 'left'), // Field 1050: Record code (4)
|
|
37
|
+
(0, encoder_js_1.formatNumericField)(fullRecord.recordCount, 15), // Field 1051: Record count (15)
|
|
38
|
+
];
|
|
39
|
+
return (0, encoder_js_1.joinFields)(fields);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Parses a fixed-width A000Sum record line back to object
|
|
43
|
+
* Expected line length: 19 characters (excluding CRLF)
|
|
44
|
+
*/
|
|
45
|
+
function parseA000Sum(line) {
|
|
46
|
+
// Remove CRLF if present
|
|
47
|
+
const cleanLine = line.replace(/\r?\n$/, '');
|
|
48
|
+
if (cleanLine.length !== 19) {
|
|
49
|
+
throw new Error(`Invalid A000Sum record length: expected 19 characters, got ${cleanLine.length}`);
|
|
50
|
+
}
|
|
51
|
+
let offset = 0;
|
|
52
|
+
// Extract fields at their fixed positions
|
|
53
|
+
const code = cleanLine.slice(offset, offset + 4).trim();
|
|
54
|
+
offset += 4; // Field 1050 (4)
|
|
55
|
+
const recordCount = cleanLine
|
|
56
|
+
.slice(offset, offset + 15)
|
|
57
|
+
.trim()
|
|
58
|
+
.replace(/^0+/, '') || '0';
|
|
59
|
+
offset += 15; // Field 1051 (15)
|
|
60
|
+
const parsed = {
|
|
61
|
+
code,
|
|
62
|
+
recordCount,
|
|
63
|
+
};
|
|
64
|
+
// Validate against schema
|
|
65
|
+
return exports.A000SumSchema.parse(parsed);
|
|
66
|
+
}
|