@fin.cx/einvoice 5.0.3 → 5.1.3

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 (117) hide show
  1. package/dist_ts/00_commitinfo_data.js +1 -1
  2. package/dist_ts/einvoice.d.ts +4 -8
  3. package/dist_ts/einvoice.js +46 -7
  4. package/dist_ts/formats/converters/xml-to-einvoice.converter.d.ts +21 -0
  5. package/dist_ts/formats/converters/xml-to-einvoice.converter.js +127 -0
  6. package/dist_ts/formats/semantic/bt-bg.model.d.ts +445 -0
  7. package/dist_ts/formats/semantic/bt-bg.model.js +12 -0
  8. package/dist_ts/formats/semantic/semantic.adapter.d.ts +87 -0
  9. package/dist_ts/formats/semantic/semantic.adapter.js +538 -0
  10. package/dist_ts/formats/semantic/semantic.validator.d.ts +48 -0
  11. package/dist_ts/formats/semantic/semantic.validator.js +596 -0
  12. package/dist_ts/formats/utils/currency.calculator.decimal.d.ts +98 -0
  13. package/dist_ts/formats/utils/currency.calculator.decimal.js +212 -0
  14. package/dist_ts/formats/utils/currency.utils.d.ts +99 -0
  15. package/dist_ts/formats/utils/currency.utils.js +250 -0
  16. package/dist_ts/formats/utils/decimal.d.ts +151 -0
  17. package/dist_ts/formats/utils/decimal.js +435 -0
  18. package/dist_ts/formats/validation/codelist.validator.d.ts +49 -0
  19. package/dist_ts/formats/validation/codelist.validator.js +188 -0
  20. package/dist_ts/formats/validation/conformance.harness.d.ts +99 -0
  21. package/dist_ts/formats/validation/conformance.harness.js +471 -0
  22. package/dist_ts/formats/validation/en16931.business-rules.validator.d.ts +58 -0
  23. package/dist_ts/formats/validation/en16931.business-rules.validator.js +459 -0
  24. package/dist_ts/formats/validation/facturx.validator.d.ts +75 -0
  25. package/dist_ts/formats/validation/facturx.validator.js +522 -0
  26. package/dist_ts/formats/validation/integrated.validator.d.ts +82 -0
  27. package/dist_ts/formats/validation/integrated.validator.js +311 -0
  28. package/dist_ts/formats/validation/peppol.validator.d.ts +77 -0
  29. package/dist_ts/formats/validation/peppol.validator.js +529 -0
  30. package/dist_ts/formats/validation/schematron.downloader.d.ts +71 -0
  31. package/dist_ts/formats/validation/schematron.downloader.js +254 -0
  32. package/dist_ts/formats/validation/schematron.integration.d.ts +60 -0
  33. package/dist_ts/formats/validation/schematron.integration.js +230 -0
  34. package/dist_ts/formats/validation/schematron.validator.d.ts +79 -0
  35. package/dist_ts/formats/validation/schematron.validator.js +288 -0
  36. package/dist_ts/formats/validation/schematron.worker.d.ts +50 -0
  37. package/dist_ts/formats/validation/schematron.worker.js +185 -0
  38. package/dist_ts/formats/validation/validation.types.d.ts +163 -0
  39. package/dist_ts/formats/validation/validation.types.js +181 -0
  40. package/dist_ts/formats/validation/vat-categories.validator.d.ts +87 -0
  41. package/dist_ts/formats/validation/vat-categories.validator.js +497 -0
  42. package/dist_ts/formats/validation/xrechnung.validator.d.ts +92 -0
  43. package/dist_ts/formats/validation/xrechnung.validator.js +417 -0
  44. package/dist_ts/interfaces/common.d.ts +1 -0
  45. package/dist_ts/interfaces/en16931-metadata.d.ts +83 -0
  46. package/dist_ts/interfaces/en16931-metadata.js +6 -0
  47. package/dist_ts/plugins.d.ts +3 -1
  48. package/dist_ts/plugins.js +7 -2
  49. package/dist_ts_install/download-schematron.d.ts +6 -0
  50. package/dist_ts_install/download-schematron.js +62 -0
  51. package/dist_ts_install/download-test-samples.d.ts +19 -0
  52. package/dist_ts_install/download-test-samples.js +169 -0
  53. package/dist_ts_install/download-xrechnung-rules.d.ts +7 -0
  54. package/dist_ts_install/download-xrechnung-rules.js +146 -0
  55. package/dist_ts_install/index.d.ts +8 -0
  56. package/dist_ts_install/index.js +246 -0
  57. package/npmextra.json +1 -1
  58. package/package.json +12 -6
  59. package/readme.md +255 -810
  60. package/ts/00_commitinfo_data.ts +1 -1
  61. package/ts/einvoice.ts +63 -14
  62. package/ts/formats/converters/xml-to-einvoice.converter.ts +142 -0
  63. package/ts/formats/semantic/bt-bg.model.ts +524 -0
  64. package/ts/formats/semantic/semantic.adapter.ts +600 -0
  65. package/ts/formats/semantic/semantic.validator.ts +654 -0
  66. package/ts/formats/utils/currency.calculator.decimal.ts +323 -0
  67. package/ts/formats/utils/currency.utils.ts +299 -0
  68. package/ts/formats/utils/decimal.ts +509 -0
  69. package/ts/formats/validation/codelist.validator.ts +317 -0
  70. package/ts/formats/validation/conformance.harness.ts +591 -0
  71. package/ts/formats/validation/en16931.business-rules.validator.ts +694 -0
  72. package/ts/formats/validation/facturx.validator.ts +579 -0
  73. package/ts/formats/validation/integrated.validator.ts +405 -0
  74. package/ts/formats/validation/peppol.validator.ts +589 -0
  75. package/ts/formats/validation/schematron.downloader.ts +304 -0
  76. package/ts/formats/validation/schematron.integration.ts +285 -0
  77. package/ts/formats/validation/schematron.validator.ts +348 -0
  78. package/ts/formats/validation/schematron.worker.ts +221 -0
  79. package/ts/formats/validation/validation.types.ts +274 -0
  80. package/ts/formats/validation/vat-categories.validator.ts +845 -0
  81. package/ts/formats/validation/xrechnung.validator.ts +494 -0
  82. package/ts/interfaces/common.ts +1 -0
  83. package/ts/interfaces/en16931-metadata.ts +104 -0
  84. package/ts/plugins.ts +8 -0
  85. package/ts/tspublish.json +3 -0
  86. package/dist_ts/classes.decoder.d.ts +0 -40
  87. package/dist_ts/classes.decoder.js +0 -320
  88. package/dist_ts/classes.encoder.d.ts +0 -51
  89. package/dist_ts/classes.encoder.js +0 -293
  90. package/dist_ts/classes.xinvoice.d.ts +0 -136
  91. package/dist_ts/classes.xinvoice.js +0 -352
  92. package/dist_ts/formats/base.decoder.d.ts +0 -19
  93. package/dist_ts/formats/base.decoder.js +0 -130
  94. package/dist_ts/formats/base.validator.d.ts +0 -44
  95. package/dist_ts/formats/base.validator.js +0 -39
  96. package/dist_ts/formats/decoder.factory.d.ts +0 -15
  97. package/dist_ts/formats/decoder.factory.js +0 -46
  98. package/dist_ts/formats/factorx.decoder.d.ts +0 -18
  99. package/dist_ts/formats/factorx.decoder.js +0 -178
  100. package/dist_ts/formats/factorx.encoder.d.ts +0 -51
  101. package/dist_ts/formats/factorx.encoder.js +0 -293
  102. package/dist_ts/formats/facturx.decoder.d.ts +0 -18
  103. package/dist_ts/formats/facturx.decoder.js +0 -210
  104. package/dist_ts/formats/facturx.encoder.d.ts +0 -51
  105. package/dist_ts/formats/facturx.encoder.js +0 -293
  106. package/dist_ts/formats/facturx.validator.d.ts +0 -67
  107. package/dist_ts/formats/facturx.validator.js +0 -266
  108. package/dist_ts/formats/pdf/robust-pdf.extractor.d.ts +0 -40
  109. package/dist_ts/formats/pdf/robust-pdf.extractor.js +0 -324
  110. package/dist_ts/formats/ubl.validator.d.ts +0 -82
  111. package/dist_ts/formats/ubl.validator.js +0 -306
  112. package/dist_ts/formats/validator.factory.d.ts +0 -18
  113. package/dist_ts/formats/validator.factory.js +0 -78
  114. package/dist_ts/formats/xinvoice.decoder.d.ts +0 -28
  115. package/dist_ts/formats/xinvoice.decoder.js +0 -332
  116. package/dist_ts/formats/xinvoice.encoder.d.ts +0 -19
  117. package/dist_ts/formats/xinvoice.encoder.js +0 -282
@@ -0,0 +1,471 @@
1
+ /**
2
+ * Conformance Test Harness for EN16931 Validation
3
+ * Tests validators against official samples and generates coverage reports
4
+ */
5
+ import * as plugins from '../../plugins.js';
6
+ import * as fs from 'fs';
7
+ import * as path from 'path';
8
+ import { IntegratedValidator } from './schematron.integration.js';
9
+ import { EN16931BusinessRulesValidator } from './en16931.business-rules.validator.js';
10
+ import { CodeListValidator } from './codelist.validator.js';
11
+ import { VATCategoriesValidator } from './vat-categories.validator.js';
12
+ import { XMLToEInvoiceConverter } from '../converters/xml-to-einvoice.converter.js';
13
+ /**
14
+ * Conformance Test Harness
15
+ */
16
+ export class ConformanceTestHarness {
17
+ constructor() {
18
+ this.testSamples = [];
19
+ this.results = [];
20
+ this.integratedValidator = new IntegratedValidator();
21
+ this.businessRulesValidator = new EN16931BusinessRulesValidator();
22
+ this.codeListValidator = new CodeListValidator();
23
+ this.vatCategoriesValidator = new VATCategoriesValidator();
24
+ this.xmlConverter = new XMLToEInvoiceConverter();
25
+ }
26
+ /**
27
+ * Load test samples from directory
28
+ */
29
+ async loadTestSamples(baseDir = 'test-samples') {
30
+ this.testSamples = [];
31
+ // Load PEPPOL BIS 3.0 samples
32
+ const peppolDir = path.join(baseDir, 'peppol-bis3');
33
+ if (fs.existsSync(peppolDir)) {
34
+ const peppolFiles = fs.readdirSync(peppolDir);
35
+ for (const file of peppolFiles) {
36
+ if (file.endsWith('.xml')) {
37
+ this.testSamples.push({
38
+ id: `peppol-${path.basename(file, '.xml')}`,
39
+ name: file,
40
+ path: path.join(peppolDir, file),
41
+ format: 'UBL',
42
+ standard: 'PEPPOL-BIS-3.0',
43
+ expectedValid: true,
44
+ description: this.getDescriptionFromFilename(file),
45
+ focusRules: this.getFocusRulesFromFilename(file)
46
+ });
47
+ }
48
+ }
49
+ }
50
+ // Load CEN TC434 samples
51
+ const cenDir = path.join(baseDir, 'cen-tc434');
52
+ if (fs.existsSync(cenDir)) {
53
+ const cenFiles = fs.readdirSync(cenDir);
54
+ for (const file of cenFiles) {
55
+ if (file.endsWith('.xml')) {
56
+ const format = file.includes('ubl') ? 'UBL' : 'CII';
57
+ this.testSamples.push({
58
+ id: `cen-${path.basename(file, '.xml')}`,
59
+ name: file,
60
+ path: path.join(cenDir, file),
61
+ format,
62
+ standard: 'EN16931',
63
+ expectedValid: true,
64
+ description: `CEN TC434 ${format} example`
65
+ });
66
+ }
67
+ }
68
+ }
69
+ console.log(`Loaded ${this.testSamples.length} test samples`);
70
+ }
71
+ /**
72
+ * Run all validators against a single test sample
73
+ */
74
+ async runTestSample(sample) {
75
+ const startTime = Date.now();
76
+ const result = {
77
+ sampleId: sample.id,
78
+ sampleName: sample.name,
79
+ passed: false,
80
+ errors: [],
81
+ warnings: [],
82
+ rulesTriggered: [],
83
+ executionTime: 0,
84
+ validatorResults: {
85
+ typescript: [],
86
+ schematron: [],
87
+ vatCategories: [],
88
+ codeLists: []
89
+ }
90
+ };
91
+ try {
92
+ // Read XML content
93
+ const xmlContent = fs.readFileSync(sample.path, 'utf-8');
94
+ // Convert XML to EInvoice
95
+ const invoice = await this.xmlConverter.convert(xmlContent, sample.format);
96
+ // Run TypeScript validators
97
+ const businessRules = this.businessRulesValidator.validate(invoice);
98
+ result.validatorResults.typescript = businessRules;
99
+ const codeLists = this.codeListValidator.validate(invoice);
100
+ result.validatorResults.codeLists = codeLists;
101
+ const vatCategories = this.vatCategoriesValidator.validate(invoice);
102
+ result.validatorResults.vatCategories = vatCategories;
103
+ // Try to run Schematron if available
104
+ try {
105
+ await this.integratedValidator.loadSchematron('EN16931', sample.format);
106
+ const report = await this.integratedValidator.validate(invoice, xmlContent);
107
+ result.validatorResults.schematron = report.results.filter(r => r.source === 'Schematron');
108
+ }
109
+ catch (error) {
110
+ console.warn(`Schematron not available for ${sample.format}: ${error.message}`);
111
+ }
112
+ // Aggregate results
113
+ const allResults = [
114
+ ...businessRules,
115
+ ...codeLists,
116
+ ...vatCategories,
117
+ ...result.validatorResults.schematron
118
+ ];
119
+ result.errors = allResults.filter(r => r.severity === 'error');
120
+ result.warnings = allResults.filter(r => r.severity === 'warning');
121
+ result.rulesTriggered = [...new Set(allResults.map(r => r.ruleId))];
122
+ result.passed = result.errors.length === 0 === sample.expectedValid;
123
+ }
124
+ catch (error) {
125
+ console.error(`Error testing ${sample.name}: ${error.message}`);
126
+ result.errors.push({
127
+ ruleId: 'TEST-ERROR',
128
+ source: 'TestHarness',
129
+ severity: 'error',
130
+ message: `Test execution failed: ${error.message}`
131
+ });
132
+ }
133
+ result.executionTime = Date.now() - startTime;
134
+ return result;
135
+ }
136
+ /**
137
+ * Run conformance tests on all samples
138
+ */
139
+ async runConformanceTests() {
140
+ console.log('\nšŸ”¬ Running conformance tests...\n');
141
+ this.results = [];
142
+ for (const sample of this.testSamples) {
143
+ process.stdout.write(`Testing ${sample.name}... `);
144
+ const result = await this.runTestSample(sample);
145
+ this.results.push(result);
146
+ if (result.passed) {
147
+ console.log('āœ… PASSED');
148
+ }
149
+ else {
150
+ console.log(`āŒ FAILED (${result.errors.length} errors)`);
151
+ }
152
+ }
153
+ console.log('\n' + '='.repeat(60));
154
+ this.printSummary();
155
+ }
156
+ /**
157
+ * Generate BR coverage matrix
158
+ */
159
+ generateCoverageMatrix() {
160
+ // Define all EN16931 business rules
161
+ const allRules = this.getAllEN16931Rules();
162
+ const ruleDetails = new Map();
163
+ // Initialize rule details
164
+ for (const rule of allRules) {
165
+ ruleDetails.set(rule, {
166
+ covered: false,
167
+ samplesCovering: [],
168
+ errorCount: 0,
169
+ warningCount: 0
170
+ });
171
+ }
172
+ // Process test results
173
+ for (const result of this.results) {
174
+ for (const ruleId of result.rulesTriggered) {
175
+ if (ruleDetails.has(ruleId)) {
176
+ const detail = ruleDetails.get(ruleId);
177
+ detail.covered = true;
178
+ detail.samplesCovering.push(result.sampleId);
179
+ detail.errorCount += result.errors.filter(e => e.ruleId === ruleId).length;
180
+ detail.warningCount += result.warnings.filter(w => w.ruleId === ruleId).length;
181
+ }
182
+ }
183
+ }
184
+ // Calculate coverage by category
185
+ const categories = {
186
+ document: { total: 0, covered: 0 },
187
+ calculation: { total: 0, covered: 0 },
188
+ vat: { total: 0, covered: 0 },
189
+ lineLevel: { total: 0, covered: 0 },
190
+ codeLists: { total: 0, covered: 0 }
191
+ };
192
+ for (const [rule, detail] of ruleDetails) {
193
+ const category = this.getRuleCategory(rule);
194
+ if (category && categories[category]) {
195
+ categories[category].total++;
196
+ if (detail.covered) {
197
+ categories[category].covered++;
198
+ }
199
+ }
200
+ }
201
+ // Find uncovered rules
202
+ const uncoveredRules = Array.from(ruleDetails.entries())
203
+ .filter(([_, detail]) => !detail.covered)
204
+ .map(([rule, _]) => rule);
205
+ const coveredCount = Array.from(ruleDetails.values())
206
+ .filter(d => d.covered).length;
207
+ return {
208
+ totalRules: allRules.length,
209
+ coveredRules: coveredCount,
210
+ coveragePercentage: (coveredCount / allRules.length) * 100,
211
+ ruleDetails,
212
+ uncoveredRules,
213
+ byCategory: categories
214
+ };
215
+ }
216
+ /**
217
+ * Print test summary
218
+ */
219
+ printSummary() {
220
+ const passed = this.results.filter(r => r.passed).length;
221
+ const failed = this.results.filter(r => !r.passed).length;
222
+ const totalErrors = this.results.reduce((sum, r) => sum + r.errors.length, 0);
223
+ const totalWarnings = this.results.reduce((sum, r) => sum + r.warnings.length, 0);
224
+ console.log('\nšŸ“Š Test Summary:');
225
+ console.log(` Total samples: ${this.testSamples.length}`);
226
+ console.log(` āœ… Passed: ${passed}`);
227
+ console.log(` āŒ Failed: ${failed}`);
228
+ console.log(` šŸ”“ Total errors: ${totalErrors}`);
229
+ console.log(` 🟔 Total warnings: ${totalWarnings}`);
230
+ // Show failed samples
231
+ if (failed > 0) {
232
+ console.log('\nāŒ Failed samples:');
233
+ for (const result of this.results.filter(r => !r.passed)) {
234
+ console.log(` - ${result.sampleName} (${result.errors.length} errors)`);
235
+ for (const error of result.errors.slice(0, 3)) {
236
+ console.log(` • ${error.ruleId}: ${error.message}`);
237
+ }
238
+ if (result.errors.length > 3) {
239
+ console.log(` ... and ${result.errors.length - 3} more errors`);
240
+ }
241
+ }
242
+ }
243
+ }
244
+ /**
245
+ * Generate HTML coverage report
246
+ */
247
+ async generateHTMLReport(outputPath = 'coverage-report.html') {
248
+ const coverage = this.generateCoverageMatrix();
249
+ const html = `
250
+ <!DOCTYPE html>
251
+ <html>
252
+ <head>
253
+ <title>EN16931 Conformance Test Report</title>
254
+ <style>
255
+ body { font-family: Arial, sans-serif; margin: 20px; }
256
+ h1 { color: #333; }
257
+ .summary { background: #f0f0f0; padding: 15px; border-radius: 5px; margin: 20px 0; }
258
+ .metric { display: inline-block; margin: 10px 20px 10px 0; }
259
+ .metric-value { font-size: 24px; font-weight: bold; color: #007bff; }
260
+ .coverage-bar { width: 100%; height: 30px; background: #e0e0e0; border-radius: 5px; overflow: hidden; }
261
+ .coverage-fill { height: 100%; background: linear-gradient(90deg, #28a745, #ffc107); }
262
+ table { width: 100%; border-collapse: collapse; margin: 20px 0; }
263
+ th, td { padding: 10px; text-align: left; border: 1px solid #ddd; }
264
+ th { background: #f8f9fa; font-weight: bold; }
265
+ .covered { background: #d4edda; }
266
+ .uncovered { background: #f8d7da; }
267
+ .category-section { margin: 30px 0; }
268
+ .rule-tag { display: inline-block; padding: 2px 8px; margin: 2px; background: #007bff; color: white; border-radius: 3px; font-size: 12px; }
269
+ </style>
270
+ </head>
271
+ <body>
272
+ <h1>EN16931 Conformance Test Report</h1>
273
+ <div class="summary">
274
+ <h2>Overall Coverage</h2>
275
+ <div class="metric">
276
+ <div class="metric-value">${coverage.coveragePercentage.toFixed(1)}%</div>
277
+ <div>Total Coverage</div>
278
+ </div>
279
+ <div class="metric">
280
+ <div class="metric-value">${coverage.coveredRules}</div>
281
+ <div>Rules Covered</div>
282
+ </div>
283
+ <div class="metric">
284
+ <div class="metric-value">${coverage.totalRules}</div>
285
+ <div>Total Rules</div>
286
+ </div>
287
+ <div class="coverage-bar">
288
+ <div class="coverage-fill" style="width: ${coverage.coveragePercentage}%"></div>
289
+ </div>
290
+ </div>
291
+
292
+ <div class="category-section">
293
+ <h2>Coverage by Category</h2>
294
+ <table>
295
+ <tr>
296
+ <th>Category</th>
297
+ <th>Covered</th>
298
+ <th>Total</th>
299
+ <th>Percentage</th>
300
+ </tr>
301
+ ${Object.entries(coverage.byCategory).map(([cat, data]) => `
302
+ <tr>
303
+ <td>${cat.charAt(0).toUpperCase() + cat.slice(1)}</td>
304
+ <td>${data.covered}</td>
305
+ <td>${data.total}</td>
306
+ <td>${data.total > 0 ? ((data.covered / data.total) * 100).toFixed(1) : 0}%</td>
307
+ </tr>
308
+ `).join('')}
309
+ </table>
310
+ </div>
311
+
312
+ <div class="category-section">
313
+ <h2>Test Samples</h2>
314
+ <table>
315
+ <tr>
316
+ <th>Sample</th>
317
+ <th>Status</th>
318
+ <th>Errors</th>
319
+ <th>Warnings</th>
320
+ <th>Rules Triggered</th>
321
+ </tr>
322
+ ${this.results.map(r => `
323
+ <tr class="${r.passed ? 'covered' : 'uncovered'}">
324
+ <td>${r.sampleName}</td>
325
+ <td>${r.passed ? 'āœ… PASSED' : 'āŒ FAILED'}</td>
326
+ <td>${r.errors.length}</td>
327
+ <td>${r.warnings.length}</td>
328
+ <td>${r.rulesTriggered.length}</td>
329
+ </tr>
330
+ `).join('')}
331
+ </table>
332
+ </div>
333
+
334
+ <div class="category-section">
335
+ <h2>Uncovered Rules</h2>
336
+ ${coverage.uncoveredRules.length === 0 ? '<p>All rules covered! šŸŽ‰</p>' : `
337
+ <p>The following ${coverage.uncoveredRules.length} rules need test coverage:</p>
338
+ <div>
339
+ ${coverage.uncoveredRules.map(rule => `<span class="rule-tag">${rule}</span>`).join('')}
340
+ </div>
341
+ `}
342
+ </div>
343
+
344
+ <div class="category-section">
345
+ <p>Generated: ${new Date().toISOString()}</p>
346
+ </div>
347
+ </body>
348
+ </html>
349
+ `;
350
+ fs.writeFileSync(outputPath, html);
351
+ console.log(`\nšŸ“„ HTML report generated: ${outputPath}`);
352
+ }
353
+ /**
354
+ * Get all EN16931 business rules
355
+ */
356
+ getAllEN16931Rules() {
357
+ return [
358
+ // Document level rules
359
+ 'BR-01', 'BR-02', 'BR-03', 'BR-04', 'BR-05', 'BR-06', 'BR-07', 'BR-08', 'BR-09', 'BR-10',
360
+ 'BR-11', 'BR-12', 'BR-13', 'BR-14', 'BR-15', 'BR-16', 'BR-17', 'BR-18', 'BR-19', 'BR-20',
361
+ // Line level rules
362
+ 'BR-21', 'BR-22', 'BR-23', 'BR-24', 'BR-25', 'BR-26', 'BR-27', 'BR-28', 'BR-29', 'BR-30',
363
+ // Allowances and charges
364
+ 'BR-31', 'BR-32', 'BR-33', 'BR-34', 'BR-35', 'BR-36', 'BR-37', 'BR-38', 'BR-39', 'BR-40',
365
+ 'BR-41', 'BR-42', 'BR-43', 'BR-44', 'BR-45', 'BR-46', 'BR-47', 'BR-48', 'BR-49', 'BR-50',
366
+ 'BR-51', 'BR-52', 'BR-53', 'BR-54', 'BR-55', 'BR-56', 'BR-57', 'BR-58', 'BR-59', 'BR-60',
367
+ 'BR-61', 'BR-62', 'BR-63', 'BR-64', 'BR-65',
368
+ // Calculation rules
369
+ 'BR-CO-01', 'BR-CO-02', 'BR-CO-03', 'BR-CO-04', 'BR-CO-05', 'BR-CO-06', 'BR-CO-07', 'BR-CO-08',
370
+ 'BR-CO-09', 'BR-CO-10', 'BR-CO-11', 'BR-CO-12', 'BR-CO-13', 'BR-CO-14', 'BR-CO-15', 'BR-CO-16',
371
+ 'BR-CO-17', 'BR-CO-18', 'BR-CO-19', 'BR-CO-20',
372
+ // VAT rules - Standard rate
373
+ 'BR-S-01', 'BR-S-02', 'BR-S-03', 'BR-S-04', 'BR-S-05', 'BR-S-06', 'BR-S-07', 'BR-S-08',
374
+ // VAT rules - Zero rated
375
+ 'BR-Z-01', 'BR-Z-02', 'BR-Z-03', 'BR-Z-04', 'BR-Z-05', 'BR-Z-06', 'BR-Z-07', 'BR-Z-08',
376
+ // VAT rules - Exempt
377
+ 'BR-E-01', 'BR-E-02', 'BR-E-03', 'BR-E-04', 'BR-E-05', 'BR-E-06', 'BR-E-07', 'BR-E-08',
378
+ // VAT rules - Reverse charge
379
+ 'BR-AE-01', 'BR-AE-02', 'BR-AE-03', 'BR-AE-04', 'BR-AE-05', 'BR-AE-06', 'BR-AE-07', 'BR-AE-08',
380
+ // VAT rules - Intra-community
381
+ 'BR-K-01', 'BR-K-02', 'BR-K-03', 'BR-K-04', 'BR-K-05', 'BR-K-06', 'BR-K-07', 'BR-K-08',
382
+ 'BR-K-09', 'BR-K-10',
383
+ // VAT rules - Export
384
+ 'BR-G-01', 'BR-G-02', 'BR-G-03', 'BR-G-04', 'BR-G-05', 'BR-G-06', 'BR-G-07', 'BR-G-08',
385
+ // VAT rules - Out of scope
386
+ 'BR-O-01', 'BR-O-02', 'BR-O-03', 'BR-O-04', 'BR-O-05', 'BR-O-06', 'BR-O-07', 'BR-O-08',
387
+ // Code list rules
388
+ 'BR-CL-01', 'BR-CL-02', 'BR-CL-03', 'BR-CL-04', 'BR-CL-05', 'BR-CL-06', 'BR-CL-07', 'BR-CL-08',
389
+ 'BR-CL-09', 'BR-CL-10', 'BR-CL-11', 'BR-CL-12', 'BR-CL-13', 'BR-CL-14', 'BR-CL-15', 'BR-CL-16',
390
+ 'BR-CL-17', 'BR-CL-18', 'BR-CL-19', 'BR-CL-20', 'BR-CL-21', 'BR-CL-22', 'BR-CL-23', 'BR-CL-24',
391
+ 'BR-CL-25', 'BR-CL-26'
392
+ ];
393
+ }
394
+ /**
395
+ * Get category for a rule
396
+ */
397
+ getRuleCategory(ruleId) {
398
+ if (ruleId.startsWith('BR-CO-'))
399
+ return 'calculation';
400
+ if (ruleId.match(/^BR-[SZAEKG0]-/))
401
+ return 'vat';
402
+ if (ruleId.startsWith('BR-CL-'))
403
+ return 'codeLists';
404
+ if (ruleId.match(/^BR-2[0-9]/) || ruleId.match(/^BR-3[0-9]/))
405
+ return 'lineLevel';
406
+ if (ruleId.match(/^BR-[0-9]/) || ruleId.match(/^BR-1[0-9]/))
407
+ return 'document';
408
+ return null;
409
+ }
410
+ /**
411
+ * Get description from filename
412
+ */
413
+ getDescriptionFromFilename(filename) {
414
+ const descriptions = {
415
+ 'Allowance-example': 'Invoice with document level allowances',
416
+ 'base-example': 'Basic EN16931 compliant invoice',
417
+ 'base-negative-inv-correction': 'Negative invoice correction',
418
+ 'vat-category-E': 'VAT Exempt invoice',
419
+ 'vat-category-O': 'Out of scope services',
420
+ 'vat-category-S': 'Standard rated VAT',
421
+ 'vat-category-Z': 'Zero rated VAT',
422
+ 'vat-category-AE': 'Reverse charge VAT',
423
+ 'vat-category-K': 'Intra-community supply',
424
+ 'vat-category-G': 'Export outside EU'
425
+ };
426
+ const key = filename.replace('.xml', '');
427
+ return descriptions[key] || filename;
428
+ }
429
+ /**
430
+ * Get focus rules from filename
431
+ */
432
+ getFocusRulesFromFilename(filename) {
433
+ const focusMap = {
434
+ 'vat-category-E': ['BR-E-01', 'BR-E-02', 'BR-E-03', 'BR-E-04', 'BR-E-05', 'BR-E-06'],
435
+ 'vat-category-S': ['BR-S-01', 'BR-S-02', 'BR-S-03', 'BR-S-04', 'BR-S-05'],
436
+ 'vat-category-Z': ['BR-Z-01', 'BR-Z-02', 'BR-Z-03', 'BR-Z-04', 'BR-Z-05'],
437
+ 'vat-category-AE': ['BR-AE-01', 'BR-AE-02', 'BR-AE-03', 'BR-AE-04', 'BR-AE-05', 'BR-AE-06'],
438
+ 'vat-category-K': ['BR-K-01', 'BR-K-02', 'BR-K-03', 'BR-K-04', 'BR-K-05', 'BR-K-06'],
439
+ 'vat-category-G': ['BR-G-01', 'BR-G-02', 'BR-G-03', 'BR-G-04', 'BR-G-05', 'BR-G-06'],
440
+ 'vat-category-O': ['BR-O-01', 'BR-O-02', 'BR-O-03', 'BR-O-04', 'BR-O-05', 'BR-O-06']
441
+ };
442
+ const key = filename.replace('.xml', '');
443
+ return focusMap[key] || [];
444
+ }
445
+ }
446
+ /**
447
+ * Export convenience function to run conformance tests
448
+ */
449
+ export async function runConformanceTests(samplesDir = 'test-samples', generateReport = true) {
450
+ const harness = new ConformanceTestHarness();
451
+ // Load samples
452
+ await harness.loadTestSamples(samplesDir);
453
+ // Run tests
454
+ await harness.runConformanceTests();
455
+ // Generate reports
456
+ if (generateReport) {
457
+ const coverage = harness.generateCoverageMatrix();
458
+ console.log('\nšŸ“Š Coverage Report:');
459
+ console.log(` Overall: ${coverage.coveragePercentage.toFixed(1)}%`);
460
+ console.log(` Rules covered: ${coverage.coveredRules}/${coverage.totalRules}`);
461
+ // Show category breakdown
462
+ console.log('\n By Category:');
463
+ for (const [category, data] of Object.entries(coverage.byCategory)) {
464
+ const pct = data.total > 0 ? ((data.covered / data.total) * 100).toFixed(1) : '0';
465
+ console.log(` - ${category}: ${data.covered}/${data.total} (${pct}%)`);
466
+ }
467
+ // Generate HTML report
468
+ await harness.generateHTMLReport();
469
+ }
470
+ }
471
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZm9ybWFuY2UuaGFybmVzcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3RzL2Zvcm1hdHMvdmFsaWRhdGlvbi9jb25mb3JtYW5jZS5oYXJuZXNzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7R0FHRztBQUVILE9BQU8sS0FBSyxPQUFPLE1BQU0sa0JBQWtCLENBQUM7QUFDNUMsT0FBTyxLQUFLLEVBQUUsTUFBTSxJQUFJLENBQUM7QUFDekIsT0FBTyxLQUFLLElBQUksTUFBTSxNQUFNLENBQUM7QUFDN0IsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDbEUsT0FBTyxFQUFFLDZCQUE2QixFQUFFLE1BQU0sdUNBQXVDLENBQUM7QUFDdEYsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDNUQsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFHdkUsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sNENBQTRDLENBQUM7QUEwRHBGOztHQUVHO0FBQ0gsTUFBTSxPQUFPLHNCQUFzQjtJQVNqQztRQUhRLGdCQUFXLEdBQWlCLEVBQUUsQ0FBQztRQUMvQixZQUFPLEdBQWlCLEVBQUUsQ0FBQztRQUdqQyxJQUFJLENBQUMsbUJBQW1CLEdBQUcsSUFBSSxtQkFBbUIsRUFBRSxDQUFDO1FBQ3JELElBQUksQ0FBQyxzQkFBc0IsR0FBRyxJQUFJLDZCQUE2QixFQUFFLENBQUM7UUFDbEUsSUFBSSxDQUFDLGlCQUFpQixHQUFHLElBQUksaUJBQWlCLEVBQUUsQ0FBQztRQUNqRCxJQUFJLENBQUMsc0JBQXNCLEdBQUcsSUFBSSxzQkFBc0IsRUFBRSxDQUFDO1FBQzNELElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxzQkFBc0IsRUFBRSxDQUFDO0lBQ25ELENBQUM7SUFFRDs7T0FFRztJQUNJLEtBQUssQ0FBQyxlQUFlLENBQUMsVUFBa0IsY0FBYztR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
@@ -0,0 +1,58 @@
1
+ import type { EInvoice } from '../../einvoice.js';
2
+ import type { ValidationResult, ValidationOptions } from './validation.types.js';
3
+ /**
4
+ * EN16931 Business Rules Validator
5
+ * Implements the full set of EN16931 business rules for invoice validation
6
+ */
7
+ export declare class EN16931BusinessRulesValidator {
8
+ private results;
9
+ private currencyCalculator?;
10
+ private decimalCalculator?;
11
+ /**
12
+ * Validate an invoice against EN16931 business rules
13
+ */
14
+ validate(invoice: EInvoice, options?: ValidationOptions): ValidationResult[];
15
+ /**
16
+ * Validate document level rules (BR-01 to BR-65)
17
+ */
18
+ private validateDocumentRules;
19
+ /**
20
+ * Validate calculation rules (BR-CO-*)
21
+ */
22
+ private validateCalculationRules;
23
+ /**
24
+ * Validate VAT rules
25
+ */
26
+ private validateVATRules;
27
+ /**
28
+ * Validate line level rules (BR-21 to BR-30)
29
+ */
30
+ private validateLineRules;
31
+ /**
32
+ * Validate allowances and charges
33
+ */
34
+ private validateAllowancesCharges;
35
+ private calculateLineTotal;
36
+ /**
37
+ * Calculate line total using decimal arithmetic for precision
38
+ */
39
+ private calculateLineTotalDecimal;
40
+ /**
41
+ * Calculate document allowances using decimal arithmetic
42
+ */
43
+ private calculateDocumentAllowancesDecimal;
44
+ /**
45
+ * Calculate document charges using decimal arithmetic
46
+ */
47
+ private calculateDocumentChargesDecimal;
48
+ /**
49
+ * Calculate total VAT using decimal arithmetic
50
+ */
51
+ private calculateTotalVATDecimal;
52
+ private calculateDocumentAllowances;
53
+ private calculateDocumentCharges;
54
+ private calculateTotalVAT;
55
+ private groupItemsByVAT;
56
+ private addError;
57
+ private addWarning;
58
+ }