@fin.cx/einvoice 9.0.0 → 10.0.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 (126) hide show
  1. package/dist_ts/00_commitinfo_data.js +2 -2
  2. package/dist_ts/einvoice.d.ts +12 -0
  3. package/dist_ts/einvoice.js +45 -3
  4. package/dist_ts/formats/base/base.decoder.d.ts +27 -2
  5. package/dist_ts/formats/base/base.decoder.js +52 -27
  6. package/dist_ts/formats/cii/cii.decoder.d.ts +89 -6
  7. package/dist_ts/formats/cii/cii.decoder.js +125 -30
  8. package/dist_ts/formats/cii/cii.encoder.d.ts +71 -1
  9. package/dist_ts/formats/cii/cii.encoder.js +191 -12
  10. package/dist_ts/formats/cii/cii.types.d.ts +2 -5
  11. package/dist_ts/formats/cii/cii.types.js +7 -9
  12. package/dist_ts/formats/cii/cii.validator.d.ts +13 -6
  13. package/dist_ts/formats/cii/cii.validator.js +29 -30
  14. package/dist_ts/formats/cii/facturx/facturx.decoder.js +15 -3
  15. package/dist_ts/formats/cii/facturx/facturx.encoder.d.ts +0 -6
  16. package/dist_ts/formats/cii/facturx/facturx.encoder.js +11 -25
  17. package/dist_ts/formats/cii/facturx/facturx.types.d.ts +0 -5
  18. package/dist_ts/formats/cii/facturx/facturx.types.js +1 -8
  19. package/dist_ts/formats/cii/facturx/facturx.validator.d.ts +0 -5
  20. package/dist_ts/formats/cii/facturx/facturx.validator.js +5 -29
  21. package/dist_ts/formats/cii/zugferd/zugferd.decoder.js +15 -2
  22. package/dist_ts/formats/cii/zugferd/zugferd.encoder.d.ts +0 -7
  23. package/dist_ts/formats/cii/zugferd/zugferd.encoder.js +9 -67
  24. package/dist_ts/formats/cii/zugferd/zugferd.types.d.ts +0 -5
  25. package/dist_ts/formats/cii/zugferd/zugferd.types.js +1 -8
  26. package/dist_ts/formats/cii/zugferd/zugferd.v1.decoder.d.ts +26 -0
  27. package/dist_ts/formats/cii/zugferd/zugferd.v1.decoder.js +43 -1
  28. package/dist_ts/formats/cii/zugferd/zugferd.validator.js +6 -2
  29. package/dist_ts/formats/semantic/semantic.adapter.js +20 -18
  30. package/dist_ts/formats/ubl/en16931.ubl.validator.d.ts +0 -4
  31. package/dist_ts/formats/ubl/en16931.ubl.validator.js +5 -42
  32. package/dist_ts/formats/ubl/generic/ubl.encoder.js +18 -24
  33. package/dist_ts/formats/ubl/ubl.decoder.d.ts +4 -0
  34. package/dist_ts/formats/ubl/ubl.decoder.js +9 -1
  35. package/dist_ts/formats/ubl/ubl.encoder.js +9 -5
  36. package/dist_ts/formats/ubl/ubl.validator.d.ts +13 -0
  37. package/dist_ts/formats/ubl/ubl.validator.js +28 -1
  38. package/dist_ts/formats/ubl/xrechnung/xrechnung.decoder.js +10 -1
  39. package/dist_ts/formats/ubl/xrechnung/xrechnung.encoder.d.ts +0 -7
  40. package/dist_ts/formats/ubl/xrechnung/xrechnung.encoder.js +30 -45
  41. package/dist_ts/formats/ubl/xrechnung.validator.d.ts +5 -4
  42. package/dist_ts/formats/ubl/xrechnung.validator.js +71 -68
  43. package/dist_ts/formats/utils/date.value.d.ts +35 -0
  44. package/dist_ts/formats/utils/date.value.js +98 -1
  45. package/dist_ts/formats/utils/format.detector.js +16 -10
  46. package/dist_ts/formats/utils/party.contact.d.ts +16 -0
  47. package/dist_ts/formats/utils/party.contact.js +16 -0
  48. package/dist_ts/formats/utils/party.identifier.d.ts +28 -0
  49. package/dist_ts/formats/utils/party.identifier.js +49 -0
  50. package/dist_ts/formats/utils/peppol.profile.d.ts +10 -0
  51. package/dist_ts/formats/utils/peppol.profile.js +12 -0
  52. package/dist_ts/formats/utils/seller.identifier.d.ts +46 -0
  53. package/dist_ts/formats/utils/seller.identifier.js +78 -0
  54. package/dist_ts/formats/utils/stated.values.d.ts +80 -0
  55. package/dist_ts/formats/utils/stated.values.js +418 -0
  56. package/dist_ts/formats/utils/vat.category.d.ts +30 -2
  57. package/dist_ts/formats/utils/vat.category.js +36 -6
  58. package/dist_ts/formats/utils/vat.id.d.ts +18 -0
  59. package/dist_ts/formats/utils/vat.id.js +22 -0
  60. package/dist_ts/formats/validation/conformance.harness.js +6 -6
  61. package/dist_ts/formats/validation/en16931.business-rules.validator.js +4 -21
  62. package/dist_ts/formats/validation/facturx.validator.js +6 -6
  63. package/dist_ts/formats/validation/integrated.validator.js +4 -13
  64. package/dist_ts/formats/validation/peppol.validator.js +6 -13
  65. package/dist_ts/formats/validation/validation.types.d.ts +5 -0
  66. package/dist_ts/formats/validation/validation.types.js +6 -1
  67. package/dist_ts/formats/validation/vat-categories.validator.d.ts +21 -42
  68. package/dist_ts/formats/validation/vat-categories.validator.js +137 -431
  69. package/dist_ts/formats/validation/xrechnung.validator.d.ts +11 -58
  70. package/dist_ts/formats/validation/xrechnung.validator.js +58 -324
  71. package/dist_ts/index.d.ts +1 -0
  72. package/dist_ts/index.js +1 -1
  73. package/dist_ts/interfaces/en16931-metadata.d.ts +0 -4
  74. package/dist_ts/interfaces/stated.values.d.ts +93 -0
  75. package/dist_ts/interfaces/stated.values.js +2 -0
  76. package/package.json +4 -4
  77. package/readme.md +152 -7
  78. package/ts/00_commitinfo_data.ts +1 -1
  79. package/ts/einvoice.ts +52 -2
  80. package/ts/formats/base/base.decoder.ts +55 -45
  81. package/ts/formats/cii/cii.decoder.ts +159 -32
  82. package/ts/formats/cii/cii.encoder.ts +206 -14
  83. package/ts/formats/cii/cii.types.ts +7 -9
  84. package/ts/formats/cii/cii.validator.ts +30 -32
  85. package/ts/formats/cii/facturx/facturx.decoder.ts +16 -2
  86. package/ts/formats/cii/facturx/facturx.encoder.ts +13 -25
  87. package/ts/formats/cii/facturx/facturx.types.ts +0 -9
  88. package/ts/formats/cii/facturx/facturx.validator.ts +5 -43
  89. package/ts/formats/cii/zugferd/zugferd.decoder.ts +16 -1
  90. package/ts/formats/cii/zugferd/zugferd.encoder.ts +10 -72
  91. package/ts/formats/cii/zugferd/zugferd.types.ts +0 -9
  92. package/ts/formats/cii/zugferd/zugferd.v1.decoder.ts +56 -0
  93. package/ts/formats/cii/zugferd/zugferd.validator.ts +5 -1
  94. package/ts/formats/semantic/semantic.adapter.ts +19 -17
  95. package/ts/formats/ubl/en16931.ubl.validator.ts +5 -64
  96. package/ts/formats/ubl/generic/ubl.encoder.ts +19 -23
  97. package/ts/formats/ubl/ubl.decoder.ts +12 -0
  98. package/ts/formats/ubl/ubl.encoder.ts +8 -4
  99. package/ts/formats/ubl/ubl.validator.ts +29 -0
  100. package/ts/formats/ubl/xrechnung/xrechnung.decoder.ts +8 -0
  101. package/ts/formats/ubl/xrechnung/xrechnung.encoder.ts +33 -45
  102. package/ts/formats/ubl/xrechnung.validator.ts +75 -127
  103. package/ts/formats/utils/date.value.ts +106 -0
  104. package/ts/formats/utils/format.detector.ts +15 -9
  105. package/ts/formats/utils/party.contact.ts +30 -0
  106. package/ts/formats/utils/party.identifier.ts +61 -0
  107. package/ts/formats/utils/peppol.profile.ts +13 -0
  108. package/ts/formats/utils/seller.identifier.ts +102 -0
  109. package/ts/formats/utils/stated.values.ts +499 -0
  110. package/ts/formats/utils/vat.category.ts +47 -5
  111. package/ts/formats/utils/vat.id.ts +24 -0
  112. package/ts/formats/validation/conformance.harness.ts +5 -5
  113. package/ts/formats/validation/en16931.business-rules.validator.ts +3 -28
  114. package/ts/formats/validation/facturx.validator.ts +5 -5
  115. package/ts/formats/validation/integrated.validator.ts +3 -16
  116. package/ts/formats/validation/peppol.validator.ts +5 -16
  117. package/ts/formats/validation/validation.types.ts +7 -1
  118. package/ts/formats/validation/vat-categories.validator.ts +179 -761
  119. package/ts/formats/validation/xrechnung.validator.ts +61 -382
  120. package/ts/index.ts +9 -0
  121. package/ts/interfaces/en16931-metadata.ts +3 -7
  122. package/ts/interfaces/stated.values.ts +94 -0
  123. package/ts/readme.md +1 -1
  124. package/dist_ts/formats/utils/eu.memberstates.d.ts +0 -11
  125. package/dist_ts/formats/utils/eu.memberstates.js +0 -16
  126. package/ts/formats/utils/eu.memberstates.ts +0 -16
@@ -247,34 +247,9 @@ export class EN16931BusinessRulesValidator {
247
247
  );
248
248
  }
249
249
 
250
- // BR-CO-16: Amount due for payment = Invoice total with VAT - Paid amount. The envelope's
251
- // paid amount (BT-113) is the one the encoders write; the amount due (BT-115) is compared when
252
- // a declared one is at hand (`metadata.amountDue`), since the envelope derives it otherwise
253
- const paidAmountValue = invoice.paidAmount ?? 0;
254
- const declaredDueValue = invoice.metadata?.amountDue;
255
- if (declaredDueValue !== undefined) {
256
- const paidAmount = useDecimal ? new Decimal(paidAmountValue) : paidAmountValue;
257
- const expectedDueAmount = useDecimal
258
- ? (expectedGrossTotal as Decimal).subtract(paidAmount)
259
- : (expectedGrossTotal as number) - (paidAmount as number);
260
- const declaredDueAmount = useDecimal ? new Decimal(declaredDueValue) : declaredDueValue;
261
-
262
- const isDueEqual = useDecimal
263
- ? this.decimalCalculator!.areEqual(expectedDueAmount, declaredDueAmount)
264
- : this.currencyCalculator
265
- ? this.currencyCalculator.areEqual(expectedDueAmount as number, declaredDueAmount as number)
266
- : Math.abs((expectedDueAmount as number) - (declaredDueAmount as number)) < 0.01;
267
-
268
- if (!isDueEqual) {
269
- this.addError(
270
- 'BR-CO-16',
271
- `Amount due (${useDecimal ? (declaredDueAmount as Decimal).toFixed(2) : (declaredDueAmount as number).toFixed(2)}) does not match calculation (${useDecimal ? (expectedDueAmount as Decimal).toFixed(2) : (expectedDueAmount as number).toFixed(2)})`,
272
- 'amountDue',
273
- useDecimal ? (declaredDueAmount as Decimal).toNumber() : declaredDueAmount as number,
274
- useDecimal ? (expectedDueAmount as Decimal).toNumber() : expectedDueAmount as number
275
- );
276
- }
277
- }
250
+ // BR-CO-16 (amount due for payment = invoice total with VAT - paid amount) is not checked
251
+ // here: the envelope has no amount due (BT-115); the encoders derive it from the gross total
252
+ // and the paid amount (BT-113), and the official rules check it on the written XML
278
253
  }
279
254
 
280
255
  /**
@@ -79,7 +79,7 @@ export class FacturXValidator {
79
79
  'dueDate', // BT-9: Payment due date
80
80
  ],
81
81
  optional: [
82
- 'metadata.buyerReference', // BT-10: Buyer reference
82
+ 'buyerReference', // BT-10: Buyer reference
83
83
  'metadata.purchaseOrderReference', // BT-13: Purchase order reference
84
84
  'metadata.salesOrderReference', // BT-14: Sales order reference
85
85
  'metadata.contractReference', // BT-12: Contract reference
@@ -108,7 +108,7 @@ export class FacturXValidator {
108
108
  // No items required
109
109
  ],
110
110
  optional: [
111
- 'metadata.buyerReference',
111
+ 'buyerReference',
112
112
  'metadata.purchaseOrderReference',
113
113
  'metadata.contractReference',
114
114
  ]
@@ -122,7 +122,7 @@ export class FacturXValidator {
122
122
  'issueDate',
123
123
  'accountingDocType',
124
124
  'currency',
125
- 'metadata.buyerReference',
125
+ 'buyerReference',
126
126
 
127
127
  // Seller information
128
128
  'from.name',
@@ -411,12 +411,12 @@ export class FacturXValidator {
411
411
 
412
412
  case FacturXProfile.EN16931:
413
413
  // EN16931 requires full compliance - additional checks handled by EN16931 validator
414
- if (!invoice.metadata?.buyerReference && !invoice.metadata?.extensions?.purchaseOrderReference) {
414
+ if (!invoice.buyerReference && !invoice.metadata?.extensions?.purchaseOrderReference) {
415
415
  results.push({
416
416
  ruleId: 'FX-EN-01',
417
417
  severity: 'error',
418
418
  message: 'EN16931 profile requires either buyer reference or purchase order reference',
419
- field: 'metadata.buyerReference',
419
+ field: 'buyerReference',
420
420
  source: 'FACTURX'
421
421
  });
422
422
  }
@@ -12,6 +12,7 @@ import { CodeListValidator } from './codelist.validator.js';
12
12
  import type { ValidationResult, ValidationOptions, ValidationReport } from './validation.types.js';
13
13
  import type { EInvoice } from '../../einvoice.js';
14
14
  import { UBL_CUSTOMIZATION_IDS } from '../ubl/ubl.types.js';
15
+ import { isPeppolBisBilling3 } from '../utils/peppol.profile.js';
15
16
 
16
17
  /**
17
18
  * Main validator that combines all validation capabilities
@@ -172,8 +173,7 @@ export class MainValidator {
172
173
  return 'XRECHNUNG_3.0';
173
174
  }
174
175
 
175
- if (profileId.includes('peppol') || customizationId.includes('peppol') ||
176
- profileId.includes('urn:fdc:peppol.eu')) {
176
+ if (isPeppolBisBilling3(customizationId)) {
177
177
  return 'PEPPOL_BIS_3.0';
178
178
  }
179
179
 
@@ -215,20 +215,7 @@ export class MainValidator {
215
215
  * Check if invoice is PEPPOL
216
216
  */
217
217
  private isPeppolInvoice(invoice: EInvoice): boolean {
218
- const profileId = invoice.metadata?.profileId || '';
219
- const customizationId = invoice.metadata?.customizationId || '';
220
-
221
- const peppolProfiles = [
222
- 'urn:fdc:peppol.eu:2017:poacc:billing:3.0',
223
- 'urn:fdc:peppol.eu:2017:poacc:billing:01:1.0',
224
- 'peppol-bis-3',
225
- 'peppol'
226
- ];
227
-
228
- return peppolProfiles.some(profile =>
229
- profileId.toLowerCase().includes(profile.toLowerCase()) ||
230
- customizationId.toLowerCase().includes(profile.toLowerCase())
231
- );
218
+ return isPeppolBisBilling3(invoice.metadata?.customizationId);
232
219
  }
233
220
 
234
221
  /**
@@ -5,6 +5,7 @@
5
5
 
6
6
  import type { ValidationResult } from './validation.types.js';
7
7
  import type { EInvoice } from '../../einvoice.js';
8
+ import { isPeppolBisBilling3 } from '../utils/peppol.profile.js';
8
9
 
9
10
  /**
10
11
  * PEPPOL BIS 3.0 Validator
@@ -50,20 +51,8 @@ export class PeppolValidator {
50
51
  * Check if invoice is PEPPOL
51
52
  */
52
53
  private isPeppolInvoice(invoice: EInvoice): boolean {
53
- const profileId = invoice.metadata?.profileId || '';
54
- const customizationId = invoice.metadata?.customizationId || '';
55
-
56
- const peppolProfiles = [
57
- 'urn:fdc:peppol.eu:2017:poacc:billing:3.0',
58
- 'urn:fdc:peppol.eu:2017:poacc:billing:01:1.0',
59
- 'peppol-bis-3',
60
- 'peppol'
61
- ];
62
-
63
- return peppolProfiles.some(profile =>
64
- profileId.toLowerCase().includes(profile.toLowerCase()) ||
65
- customizationId.toLowerCase().includes(profile.toLowerCase())
66
- );
54
+ // the PEPPOL BIS Billing 3.0 specification identifier (BT-24), not a derivative that names PEPPOL
55
+ return isPeppolBisBilling3(invoice.metadata?.customizationId);
67
56
  }
68
57
 
69
58
  /**
@@ -393,12 +382,12 @@ export class PeppolValidator {
393
382
 
394
383
  // PEPPOL-B-01: Invoice must have a buyer reference or purchase order reference
395
384
  const purchaseOrderRef = invoice.metadata?.extensions?.purchaseOrderReference;
396
- if (!invoice.metadata?.buyerReference && !purchaseOrderRef) {
385
+ if (!invoice.buyerReference && !purchaseOrderRef) {
397
386
  results.push({
398
387
  ruleId: 'PEPPOL-B-01',
399
388
  severity: 'error',
400
389
  message: 'Invoice must have either a buyer reference (BT-10) or purchase order reference (BT-13)',
401
- field: 'metadata.buyerReference',
390
+ field: 'buyerReference',
402
391
  source: 'PEPPOL'
403
392
  });
404
393
  }
@@ -2,10 +2,16 @@
2
2
  * Enhanced validation types for EN16931 compliance
3
3
  */
4
4
 
5
+ /**
6
+ * The source of a check of the package's own, one no official rule set states
7
+ * (such as `EINVOICE-DE-VATID-FORMAT`), so it is not attributed to a standard
8
+ */
9
+ export const EINVOICE_RULE_SOURCE = 'EINVOICE';
10
+
5
11
  export interface ValidationResult {
6
12
  // Core identification
7
13
  ruleId: string; // e.g., "BR-CO-14"
8
- source: string; // e.g., "EN16931", "PEPPOL", "XRECHNUNG"
14
+ source: string; // e.g., "EN16931", "PEPPOL", "XRECHNUNG"; EINVOICE_RULE_SOURCE for a check of the package's own
9
15
  severity: 'error' | 'warning' | 'info';
10
16
  message: string;
11
17