@fin.cx/einvoice 5.0.2 → 5.1.2
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/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/einvoice.d.ts +4 -8
- package/dist_ts/einvoice.js +46 -7
- package/dist_ts/formats/converters/xml-to-einvoice.converter.d.ts +21 -0
- package/dist_ts/formats/converters/xml-to-einvoice.converter.js +127 -0
- package/dist_ts/formats/semantic/bt-bg.model.d.ts +445 -0
- package/dist_ts/formats/semantic/bt-bg.model.js +12 -0
- package/dist_ts/formats/semantic/semantic.adapter.d.ts +87 -0
- package/dist_ts/formats/semantic/semantic.adapter.js +538 -0
- package/dist_ts/formats/semantic/semantic.validator.d.ts +48 -0
- package/dist_ts/formats/semantic/semantic.validator.js +596 -0
- package/dist_ts/formats/utils/currency.calculator.decimal.d.ts +98 -0
- package/dist_ts/formats/utils/currency.calculator.decimal.js +212 -0
- package/dist_ts/formats/utils/currency.utils.d.ts +99 -0
- package/dist_ts/formats/utils/currency.utils.js +250 -0
- package/dist_ts/formats/utils/decimal.d.ts +151 -0
- package/dist_ts/formats/utils/decimal.js +435 -0
- package/dist_ts/formats/validation/codelist.validator.d.ts +49 -0
- package/dist_ts/formats/validation/codelist.validator.js +188 -0
- package/dist_ts/formats/validation/conformance.harness.d.ts +99 -0
- package/dist_ts/formats/validation/conformance.harness.js +471 -0
- package/dist_ts/formats/validation/en16931.business-rules.validator.d.ts +58 -0
- package/dist_ts/formats/validation/en16931.business-rules.validator.js +459 -0
- package/dist_ts/formats/validation/facturx.validator.d.ts +75 -0
- package/dist_ts/formats/validation/facturx.validator.js +522 -0
- package/dist_ts/formats/validation/integrated.validator.d.ts +82 -0
- package/dist_ts/formats/validation/integrated.validator.js +311 -0
- package/dist_ts/formats/validation/peppol.validator.d.ts +77 -0
- package/dist_ts/formats/validation/peppol.validator.js +529 -0
- package/dist_ts/formats/validation/schematron.downloader.d.ts +71 -0
- package/dist_ts/formats/validation/schematron.downloader.js +254 -0
- package/dist_ts/formats/validation/schematron.integration.d.ts +60 -0
- package/dist_ts/formats/validation/schematron.integration.js +230 -0
- package/dist_ts/formats/validation/schematron.validator.d.ts +79 -0
- package/dist_ts/formats/validation/schematron.validator.js +288 -0
- package/dist_ts/formats/validation/schematron.worker.d.ts +50 -0
- package/dist_ts/formats/validation/schematron.worker.js +185 -0
- package/dist_ts/formats/validation/validation.types.d.ts +163 -0
- package/dist_ts/formats/validation/validation.types.js +181 -0
- package/dist_ts/formats/validation/vat-categories.validator.d.ts +87 -0
- package/dist_ts/formats/validation/vat-categories.validator.js +497 -0
- package/dist_ts/formats/validation/xrechnung.validator.d.ts +92 -0
- package/dist_ts/formats/validation/xrechnung.validator.js +417 -0
- package/dist_ts/interfaces/common.d.ts +1 -0
- package/dist_ts/interfaces/en16931-metadata.d.ts +83 -0
- package/dist_ts/interfaces/en16931-metadata.js +6 -0
- package/dist_ts/plugins.d.ts +3 -1
- package/dist_ts/plugins.js +7 -2
- package/dist_ts_install/download-schematron.d.ts +6 -0
- package/dist_ts_install/download-schematron.js +62 -0
- package/dist_ts_install/download-test-samples.d.ts +19 -0
- package/dist_ts_install/download-test-samples.js +169 -0
- package/dist_ts_install/download-xrechnung-rules.d.ts +7 -0
- package/dist_ts_install/download-xrechnung-rules.js +146 -0
- package/dist_ts_install/index.d.ts +8 -0
- package/dist_ts_install/index.js +246 -0
- package/package.json +13 -8
- package/readme.md +255 -810
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/einvoice.ts +63 -14
- package/ts/formats/converters/xml-to-einvoice.converter.ts +142 -0
- package/ts/formats/semantic/bt-bg.model.ts +524 -0
- package/ts/formats/semantic/semantic.adapter.ts +600 -0
- package/ts/formats/semantic/semantic.validator.ts +654 -0
- package/ts/formats/utils/currency.calculator.decimal.ts +323 -0
- package/ts/formats/utils/currency.utils.ts +299 -0
- package/ts/formats/utils/decimal.ts +509 -0
- package/ts/formats/validation/codelist.validator.ts +317 -0
- package/ts/formats/validation/conformance.harness.ts +591 -0
- package/ts/formats/validation/en16931.business-rules.validator.ts +694 -0
- package/ts/formats/validation/facturx.validator.ts +579 -0
- package/ts/formats/validation/integrated.validator.ts +405 -0
- package/ts/formats/validation/peppol.validator.ts +589 -0
- package/ts/formats/validation/schematron.downloader.ts +304 -0
- package/ts/formats/validation/schematron.integration.ts +285 -0
- package/ts/formats/validation/schematron.validator.ts +348 -0
- package/ts/formats/validation/schematron.worker.ts +221 -0
- package/ts/formats/validation/validation.types.ts +274 -0
- package/ts/formats/validation/vat-categories.validator.ts +845 -0
- package/ts/formats/validation/xrechnung.validator.ts +494 -0
- package/ts/interfaces/common.ts +1 -0
- package/ts/interfaces/en16931-metadata.ts +104 -0
- package/ts/plugins.ts +8 -0
- package/ts/tspublish.json +3 -0
- package/dist_ts/classes.decoder.d.ts +0 -40
- package/dist_ts/classes.decoder.js +0 -320
- package/dist_ts/classes.encoder.d.ts +0 -51
- package/dist_ts/classes.encoder.js +0 -293
- package/dist_ts/classes.xinvoice.d.ts +0 -136
- package/dist_ts/classes.xinvoice.js +0 -352
- package/dist_ts/formats/base.decoder.d.ts +0 -19
- package/dist_ts/formats/base.decoder.js +0 -130
- package/dist_ts/formats/base.validator.d.ts +0 -44
- package/dist_ts/formats/base.validator.js +0 -39
- package/dist_ts/formats/decoder.factory.d.ts +0 -15
- package/dist_ts/formats/decoder.factory.js +0 -46
- package/dist_ts/formats/factorx.decoder.d.ts +0 -18
- package/dist_ts/formats/factorx.decoder.js +0 -178
- package/dist_ts/formats/factorx.encoder.d.ts +0 -51
- package/dist_ts/formats/factorx.encoder.js +0 -293
- package/dist_ts/formats/facturx.decoder.d.ts +0 -18
- package/dist_ts/formats/facturx.decoder.js +0 -210
- package/dist_ts/formats/facturx.encoder.d.ts +0 -51
- package/dist_ts/formats/facturx.encoder.js +0 -293
- package/dist_ts/formats/facturx.validator.d.ts +0 -67
- package/dist_ts/formats/facturx.validator.js +0 -266
- package/dist_ts/formats/pdf/robust-pdf.extractor.d.ts +0 -40
- package/dist_ts/formats/pdf/robust-pdf.extractor.js +0 -324
- package/dist_ts/formats/ubl.validator.d.ts +0 -82
- package/dist_ts/formats/ubl.validator.js +0 -306
- package/dist_ts/formats/validator.factory.d.ts +0 -18
- package/dist_ts/formats/validator.factory.js +0 -78
- package/dist_ts/formats/xinvoice.decoder.d.ts +0 -28
- package/dist_ts/formats/xinvoice.decoder.js +0 -332
- package/dist_ts/formats/xinvoice.encoder.d.ts +0 -19
- package/dist_ts/formats/xinvoice.encoder.js +0 -282
|
@@ -0,0 +1,522 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Factur-X validator for profile-specific compliance
|
|
3
|
+
* Implements validation for MINIMUM, BASIC, EN16931, and EXTENDED profiles
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Factur-X Profile definitions
|
|
7
|
+
*/
|
|
8
|
+
export var FacturXProfile;
|
|
9
|
+
(function (FacturXProfile) {
|
|
10
|
+
FacturXProfile["MINIMUM"] = "MINIMUM";
|
|
11
|
+
FacturXProfile["BASIC"] = "BASIC";
|
|
12
|
+
FacturXProfile["BASIC_WL"] = "BASIC_WL";
|
|
13
|
+
FacturXProfile["EN16931"] = "EN16931";
|
|
14
|
+
FacturXProfile["EXTENDED"] = "EXTENDED";
|
|
15
|
+
})(FacturXProfile || (FacturXProfile = {}));
|
|
16
|
+
/**
|
|
17
|
+
* Factur-X Validator
|
|
18
|
+
* Validates invoices according to Factur-X profile specifications
|
|
19
|
+
*/
|
|
20
|
+
export class FacturXValidator {
|
|
21
|
+
constructor() {
|
|
22
|
+
/**
|
|
23
|
+
* Profile requirements mapping
|
|
24
|
+
*/
|
|
25
|
+
this.profileRequirements = {
|
|
26
|
+
[FacturXProfile.MINIMUM]: {
|
|
27
|
+
mandatory: [
|
|
28
|
+
'accountingDocId', // BT-1: Invoice number
|
|
29
|
+
'issueDate', // BT-2: Invoice issue date
|
|
30
|
+
'accountingDocType', // BT-3: Invoice type code
|
|
31
|
+
'currency', // BT-5: Invoice currency code
|
|
32
|
+
'from.name', // BT-27: Seller name
|
|
33
|
+
'from.vatNumber', // BT-31: Seller VAT identifier
|
|
34
|
+
'to.name', // BT-44: Buyer name
|
|
35
|
+
'totalInvoiceAmount', // BT-112: Invoice total amount with VAT
|
|
36
|
+
'totalNetAmount', // BT-109: Invoice total amount without VAT
|
|
37
|
+
'totalVatAmount', // BT-110: Invoice total VAT amount
|
|
38
|
+
],
|
|
39
|
+
optional: []
|
|
40
|
+
},
|
|
41
|
+
[FacturXProfile.BASIC]: {
|
|
42
|
+
mandatory: [
|
|
43
|
+
// All MINIMUM fields plus:
|
|
44
|
+
'accountingDocId',
|
|
45
|
+
'issueDate',
|
|
46
|
+
'accountingDocType',
|
|
47
|
+
'currency',
|
|
48
|
+
'from.name',
|
|
49
|
+
'from.vatNumber',
|
|
50
|
+
'from.address', // BT-35: Seller postal address
|
|
51
|
+
'from.country', // BT-40: Seller country code
|
|
52
|
+
'to.name',
|
|
53
|
+
'to.address', // BT-50: Buyer postal address
|
|
54
|
+
'to.country', // BT-55: Buyer country code
|
|
55
|
+
'items', // BG-25: Invoice line items
|
|
56
|
+
'items[].name', // BT-153: Item name
|
|
57
|
+
'items[].unitQuantity', // BT-129: Invoiced quantity
|
|
58
|
+
'items[].unitNetPrice', // BT-146: Item net price
|
|
59
|
+
'items[].vatPercentage', // BT-152: Invoiced item VAT rate
|
|
60
|
+
'totalInvoiceAmount',
|
|
61
|
+
'totalNetAmount',
|
|
62
|
+
'totalVatAmount',
|
|
63
|
+
'dueDate', // BT-9: Payment due date
|
|
64
|
+
],
|
|
65
|
+
optional: [
|
|
66
|
+
'metadata.buyerReference', // BT-10: Buyer reference
|
|
67
|
+
'metadata.purchaseOrderReference', // BT-13: Purchase order reference
|
|
68
|
+
'metadata.salesOrderReference', // BT-14: Sales order reference
|
|
69
|
+
'metadata.contractReference', // BT-12: Contract reference
|
|
70
|
+
'projectReference', // BT-11: Project reference
|
|
71
|
+
]
|
|
72
|
+
},
|
|
73
|
+
[FacturXProfile.BASIC_WL]: {
|
|
74
|
+
// Basic without lines - for summary invoices
|
|
75
|
+
mandatory: [
|
|
76
|
+
'accountingDocId',
|
|
77
|
+
'issueDate',
|
|
78
|
+
'accountingDocType',
|
|
79
|
+
'currency',
|
|
80
|
+
'from.name',
|
|
81
|
+
'from.vatNumber',
|
|
82
|
+
'from.address',
|
|
83
|
+
'from.country',
|
|
84
|
+
'to.name',
|
|
85
|
+
'to.address',
|
|
86
|
+
'to.country',
|
|
87
|
+
'totalInvoiceAmount',
|
|
88
|
+
'totalNetAmount',
|
|
89
|
+
'totalVatAmount',
|
|
90
|
+
'dueDate',
|
|
91
|
+
// No items required
|
|
92
|
+
],
|
|
93
|
+
optional: [
|
|
94
|
+
'metadata.buyerReference',
|
|
95
|
+
'metadata.purchaseOrderReference',
|
|
96
|
+
'metadata.contractReference',
|
|
97
|
+
]
|
|
98
|
+
},
|
|
99
|
+
[FacturXProfile.EN16931]: {
|
|
100
|
+
// Full EN16931 compliance - all mandatory fields from the standard
|
|
101
|
+
mandatory: [
|
|
102
|
+
// Document level
|
|
103
|
+
'accountingDocId',
|
|
104
|
+
'issueDate',
|
|
105
|
+
'accountingDocType',
|
|
106
|
+
'currency',
|
|
107
|
+
'metadata.buyerReference',
|
|
108
|
+
// Seller information
|
|
109
|
+
'from.name',
|
|
110
|
+
'from.address',
|
|
111
|
+
'from.city',
|
|
112
|
+
'from.postalCode',
|
|
113
|
+
'from.country',
|
|
114
|
+
'from.vatNumber',
|
|
115
|
+
// Buyer information
|
|
116
|
+
'to.name',
|
|
117
|
+
'to.address',
|
|
118
|
+
'to.city',
|
|
119
|
+
'to.postalCode',
|
|
120
|
+
'to.country',
|
|
121
|
+
// Line items
|
|
122
|
+
'items',
|
|
123
|
+
'items[].name',
|
|
124
|
+
'items[].unitQuantity',
|
|
125
|
+
'items[].unitType',
|
|
126
|
+
'items[].unitNetPrice',
|
|
127
|
+
'items[].vatPercentage',
|
|
128
|
+
// Totals
|
|
129
|
+
'totalInvoiceAmount',
|
|
130
|
+
'totalNetAmount',
|
|
131
|
+
'totalVatAmount',
|
|
132
|
+
'dueDate',
|
|
133
|
+
],
|
|
134
|
+
optional: [
|
|
135
|
+
// All other EN16931 fields
|
|
136
|
+
'metadata.purchaseOrderReference',
|
|
137
|
+
'metadata.salesOrderReference',
|
|
138
|
+
'metadata.contractReference',
|
|
139
|
+
'metadata.deliveryDate',
|
|
140
|
+
'metadata.paymentTerms',
|
|
141
|
+
'metadata.paymentMeans',
|
|
142
|
+
'to.vatNumber',
|
|
143
|
+
'to.legalRegistration',
|
|
144
|
+
'items[].articleNumber',
|
|
145
|
+
'items[].description',
|
|
146
|
+
'paymentAccount',
|
|
147
|
+
]
|
|
148
|
+
},
|
|
149
|
+
[FacturXProfile.EXTENDED]: {
|
|
150
|
+
// Extended profile allows all fields
|
|
151
|
+
mandatory: [
|
|
152
|
+
// Same as EN16931 core
|
|
153
|
+
'accountingDocId',
|
|
154
|
+
'issueDate',
|
|
155
|
+
'accountingDocType',
|
|
156
|
+
'currency',
|
|
157
|
+
'from.name',
|
|
158
|
+
'from.vatNumber',
|
|
159
|
+
'to.name',
|
|
160
|
+
'totalInvoiceAmount',
|
|
161
|
+
],
|
|
162
|
+
optional: [
|
|
163
|
+
// All fields are allowed in EXTENDED profile
|
|
164
|
+
]
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Singleton pattern for validator instance
|
|
170
|
+
*/
|
|
171
|
+
static create() {
|
|
172
|
+
if (!FacturXValidator.instance) {
|
|
173
|
+
FacturXValidator.instance = new FacturXValidator();
|
|
174
|
+
}
|
|
175
|
+
return FacturXValidator.instance;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Main validation entry point for Factur-X
|
|
179
|
+
*/
|
|
180
|
+
validateFacturX(invoice, profile) {
|
|
181
|
+
const results = [];
|
|
182
|
+
// Detect profile if not provided
|
|
183
|
+
const detectedProfile = profile || this.detectProfile(invoice);
|
|
184
|
+
// Skip if not a Factur-X invoice
|
|
185
|
+
if (!detectedProfile) {
|
|
186
|
+
return results;
|
|
187
|
+
}
|
|
188
|
+
// Validate according to profile
|
|
189
|
+
results.push(...this.validateProfileRequirements(invoice, detectedProfile));
|
|
190
|
+
results.push(...this.validateProfileSpecificRules(invoice, detectedProfile));
|
|
191
|
+
// Add profile-specific business rules
|
|
192
|
+
if (detectedProfile === FacturXProfile.MINIMUM) {
|
|
193
|
+
results.push(...this.validateMinimumProfile(invoice));
|
|
194
|
+
}
|
|
195
|
+
else if (detectedProfile === FacturXProfile.BASIC || detectedProfile === FacturXProfile.BASIC_WL) {
|
|
196
|
+
results.push(...this.validateBasicProfile(invoice, detectedProfile));
|
|
197
|
+
}
|
|
198
|
+
else if (detectedProfile === FacturXProfile.EN16931) {
|
|
199
|
+
results.push(...this.validateEN16931Profile(invoice));
|
|
200
|
+
}
|
|
201
|
+
else if (detectedProfile === FacturXProfile.EXTENDED) {
|
|
202
|
+
results.push(...this.validateExtendedProfile(invoice));
|
|
203
|
+
}
|
|
204
|
+
return results;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Detect Factur-X profile from invoice metadata
|
|
208
|
+
*/
|
|
209
|
+
detectProfile(invoice) {
|
|
210
|
+
const profileId = invoice.metadata?.profileId || '';
|
|
211
|
+
const customizationId = invoice.metadata?.customizationId || '';
|
|
212
|
+
const format = invoice.metadata?.format;
|
|
213
|
+
// Check if it's a Factur-X invoice
|
|
214
|
+
if (!format?.includes('facturx') && !profileId.includes('facturx') &&
|
|
215
|
+
!customizationId.includes('facturx') && !profileId.includes('zugferd')) {
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
218
|
+
// Detect specific profile
|
|
219
|
+
const profileLower = profileId.toLowerCase();
|
|
220
|
+
const customLower = customizationId.toLowerCase();
|
|
221
|
+
if (profileLower.includes('minimum') || customLower.includes('minimum')) {
|
|
222
|
+
return FacturXProfile.MINIMUM;
|
|
223
|
+
}
|
|
224
|
+
else if (profileLower.includes('basic_wl') || customLower.includes('basicwl')) {
|
|
225
|
+
return FacturXProfile.BASIC_WL;
|
|
226
|
+
}
|
|
227
|
+
else if (profileLower.includes('basic') || customLower.includes('basic')) {
|
|
228
|
+
return FacturXProfile.BASIC;
|
|
229
|
+
}
|
|
230
|
+
else if (profileLower.includes('en16931') || customLower.includes('en16931') ||
|
|
231
|
+
profileLower.includes('comfort') || customLower.includes('comfort')) {
|
|
232
|
+
return FacturXProfile.EN16931;
|
|
233
|
+
}
|
|
234
|
+
else if (profileLower.includes('extended') || customLower.includes('extended')) {
|
|
235
|
+
return FacturXProfile.EXTENDED;
|
|
236
|
+
}
|
|
237
|
+
// Default to BASIC if format is Factur-X but profile unclear
|
|
238
|
+
return FacturXProfile.BASIC;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Validate field requirements for a specific profile
|
|
242
|
+
*/
|
|
243
|
+
validateProfileRequirements(invoice, profile) {
|
|
244
|
+
const results = [];
|
|
245
|
+
const requirements = this.profileRequirements[profile];
|
|
246
|
+
// Check mandatory fields
|
|
247
|
+
for (const field of requirements.mandatory) {
|
|
248
|
+
const value = this.getFieldValue(invoice, field);
|
|
249
|
+
if (value === undefined || value === null || value === '') {
|
|
250
|
+
results.push({
|
|
251
|
+
ruleId: `FX-${profile}-M01`,
|
|
252
|
+
severity: 'error',
|
|
253
|
+
message: `Field '${field}' is mandatory for Factur-X ${profile} profile`,
|
|
254
|
+
field: field,
|
|
255
|
+
source: 'FACTURX'
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
// Check forbidden fields (if any)
|
|
260
|
+
if (requirements.forbidden) {
|
|
261
|
+
for (const field of requirements.forbidden) {
|
|
262
|
+
const value = this.getFieldValue(invoice, field);
|
|
263
|
+
if (value !== undefined && value !== null) {
|
|
264
|
+
results.push({
|
|
265
|
+
ruleId: `FX-${profile}-F01`,
|
|
266
|
+
severity: 'error',
|
|
267
|
+
message: `Field '${field}' is not allowed in Factur-X ${profile} profile`,
|
|
268
|
+
field: field,
|
|
269
|
+
value: value,
|
|
270
|
+
source: 'FACTURX'
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
return results;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Get field value from invoice using dot notation
|
|
279
|
+
*/
|
|
280
|
+
getFieldValue(invoice, fieldPath) {
|
|
281
|
+
// Handle special calculated fields
|
|
282
|
+
if (fieldPath === 'totalInvoiceAmount') {
|
|
283
|
+
return invoice.totalGross || invoice.totalInvoiceAmount;
|
|
284
|
+
}
|
|
285
|
+
if (fieldPath === 'totalNetAmount') {
|
|
286
|
+
return invoice.totalNet || invoice.totalNetAmount;
|
|
287
|
+
}
|
|
288
|
+
if (fieldPath === 'totalVatAmount') {
|
|
289
|
+
return invoice.totalVat || invoice.totalVatAmount;
|
|
290
|
+
}
|
|
291
|
+
if (fieldPath === 'dueDate') {
|
|
292
|
+
// Check for dueInDays which is used in EInvoice
|
|
293
|
+
if (invoice.dueInDays !== undefined && invoice.dueInDays !== null) {
|
|
294
|
+
return true; // Has payment terms
|
|
295
|
+
}
|
|
296
|
+
return invoice.dueDate;
|
|
297
|
+
}
|
|
298
|
+
const parts = fieldPath.split('.');
|
|
299
|
+
let value = invoice;
|
|
300
|
+
for (const part of parts) {
|
|
301
|
+
if (part.includes('[')) {
|
|
302
|
+
// Array field like items[]
|
|
303
|
+
const fieldName = part.substring(0, part.indexOf('['));
|
|
304
|
+
const arrayField = part.substring(part.indexOf('[') + 1, part.indexOf(']'));
|
|
305
|
+
if (!value[fieldName] || !Array.isArray(value[fieldName])) {
|
|
306
|
+
return undefined;
|
|
307
|
+
}
|
|
308
|
+
if (arrayField === '') {
|
|
309
|
+
// Check if array exists and has items
|
|
310
|
+
return value[fieldName].length > 0 ? value[fieldName] : undefined;
|
|
311
|
+
}
|
|
312
|
+
else {
|
|
313
|
+
// Check specific field in array items
|
|
314
|
+
return value[fieldName].every((item) => item[arrayField] !== undefined);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
else {
|
|
318
|
+
value = value?.[part];
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
return value;
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Profile-specific validation rules
|
|
325
|
+
*/
|
|
326
|
+
validateProfileSpecificRules(invoice, profile) {
|
|
327
|
+
const results = [];
|
|
328
|
+
// Validate according to profile level
|
|
329
|
+
switch (profile) {
|
|
330
|
+
case FacturXProfile.MINIMUM:
|
|
331
|
+
// MINIMUM requires at least gross amounts
|
|
332
|
+
// Check both calculated totals and direct properties (for test compatibility)
|
|
333
|
+
const totalGross = invoice.totalGross || invoice.totalInvoiceAmount;
|
|
334
|
+
if (!totalGross || totalGross <= 0) {
|
|
335
|
+
results.push({
|
|
336
|
+
ruleId: 'FX-MIN-01',
|
|
337
|
+
severity: 'error',
|
|
338
|
+
message: 'MINIMUM profile requires positive total invoice amount',
|
|
339
|
+
field: 'totalInvoiceAmount',
|
|
340
|
+
value: totalGross,
|
|
341
|
+
source: 'FACTURX'
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
break;
|
|
345
|
+
case FacturXProfile.BASIC:
|
|
346
|
+
case FacturXProfile.BASIC_WL:
|
|
347
|
+
// BASIC requires VAT breakdown
|
|
348
|
+
const totalVat = invoice.totalVat;
|
|
349
|
+
if (!invoice.metadata?.extensions?.taxDetails && totalVat > 0) {
|
|
350
|
+
results.push({
|
|
351
|
+
ruleId: 'FX-BAS-01',
|
|
352
|
+
severity: 'warning',
|
|
353
|
+
message: 'BASIC profile should include VAT breakdown when VAT is present',
|
|
354
|
+
field: 'metadata.extensions.taxDetails',
|
|
355
|
+
source: 'FACTURX'
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
break;
|
|
359
|
+
case FacturXProfile.EN16931:
|
|
360
|
+
// EN16931 requires full compliance - additional checks handled by EN16931 validator
|
|
361
|
+
if (!invoice.metadata?.buyerReference && !invoice.metadata?.extensions?.purchaseOrderReference) {
|
|
362
|
+
results.push({
|
|
363
|
+
ruleId: 'FX-EN-01',
|
|
364
|
+
severity: 'error',
|
|
365
|
+
message: 'EN16931 profile requires either buyer reference or purchase order reference',
|
|
366
|
+
field: 'metadata.buyerReference',
|
|
367
|
+
source: 'FACTURX'
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
break;
|
|
371
|
+
}
|
|
372
|
+
return results;
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Validate MINIMUM profile specific rules
|
|
376
|
+
*/
|
|
377
|
+
validateMinimumProfile(invoice) {
|
|
378
|
+
const results = [];
|
|
379
|
+
// MINIMUM profile allows only essential fields
|
|
380
|
+
// Check that complex structures are not present
|
|
381
|
+
if (invoice.items && invoice.items.length > 0) {
|
|
382
|
+
// Lines are optional but if present must be minimal
|
|
383
|
+
invoice.items.forEach((item, index) => {
|
|
384
|
+
if (item.allowances || item.charges) {
|
|
385
|
+
results.push({
|
|
386
|
+
ruleId: 'FX-MIN-02',
|
|
387
|
+
severity: 'warning',
|
|
388
|
+
message: `Line ${index + 1}: MINIMUM profile should not include line allowances/charges`,
|
|
389
|
+
field: `items[${index}]`,
|
|
390
|
+
source: 'FACTURX'
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
return results;
|
|
396
|
+
}
|
|
397
|
+
/**
|
|
398
|
+
* Validate BASIC profile specific rules
|
|
399
|
+
*/
|
|
400
|
+
validateBasicProfile(invoice, profile) {
|
|
401
|
+
const results = [];
|
|
402
|
+
// BASIC requires line items (except BASIC_WL)
|
|
403
|
+
// Only check for line items in BASIC profile, not BASIC_WL
|
|
404
|
+
if (profile === FacturXProfile.BASIC) {
|
|
405
|
+
if (!invoice.items || invoice.items.length === 0) {
|
|
406
|
+
results.push({
|
|
407
|
+
ruleId: 'FX-BAS-02',
|
|
408
|
+
severity: 'error',
|
|
409
|
+
message: 'BASIC profile requires at least one invoice line item',
|
|
410
|
+
field: 'items',
|
|
411
|
+
source: 'FACTURX'
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
// Payment information should be present
|
|
416
|
+
if (!invoice.dueInDays && invoice.dueInDays !== 0) {
|
|
417
|
+
results.push({
|
|
418
|
+
ruleId: 'FX-BAS-03',
|
|
419
|
+
severity: 'warning',
|
|
420
|
+
message: 'BASIC profile should include payment terms (due in days)',
|
|
421
|
+
field: 'dueInDays',
|
|
422
|
+
source: 'FACTURX'
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
return results;
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* Validate EN16931 profile specific rules
|
|
429
|
+
*/
|
|
430
|
+
validateEN16931Profile(invoice) {
|
|
431
|
+
const results = [];
|
|
432
|
+
// EN16931 requires complete address information
|
|
433
|
+
const fromAny = invoice.from;
|
|
434
|
+
const toAny = invoice.to;
|
|
435
|
+
if (!fromAny?.city || !fromAny?.postalCode) {
|
|
436
|
+
results.push({
|
|
437
|
+
ruleId: 'FX-EN-02',
|
|
438
|
+
severity: 'error',
|
|
439
|
+
message: 'EN16931 profile requires complete seller address including city and postal code',
|
|
440
|
+
field: 'from.address',
|
|
441
|
+
source: 'FACTURX'
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
if (!toAny?.city || !toAny?.postalCode) {
|
|
445
|
+
results.push({
|
|
446
|
+
ruleId: 'FX-EN-03',
|
|
447
|
+
severity: 'error',
|
|
448
|
+
message: 'EN16931 profile requires complete buyer address including city and postal code',
|
|
449
|
+
field: 'to.address',
|
|
450
|
+
source: 'FACTURX'
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
// Line items must have unit type
|
|
454
|
+
if (invoice.items) {
|
|
455
|
+
invoice.items.forEach((item, index) => {
|
|
456
|
+
if (!item.unitType) {
|
|
457
|
+
results.push({
|
|
458
|
+
ruleId: 'FX-EN-04',
|
|
459
|
+
severity: 'error',
|
|
460
|
+
message: `Line ${index + 1}: EN16931 profile requires unit of measure`,
|
|
461
|
+
field: `items[${index}].unitType`,
|
|
462
|
+
source: 'FACTURX'
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
return results;
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* Validate EXTENDED profile specific rules
|
|
471
|
+
*/
|
|
472
|
+
validateExtendedProfile(invoice) {
|
|
473
|
+
const results = [];
|
|
474
|
+
// EXTENDED profile is most permissive - mainly check for data consistency
|
|
475
|
+
if (invoice.metadata?.extensions) {
|
|
476
|
+
// Extended profile can include additional structured data
|
|
477
|
+
// Validate that extended data is well-formed
|
|
478
|
+
const extensions = invoice.metadata.extensions;
|
|
479
|
+
if (extensions.attachments && Array.isArray(extensions.attachments)) {
|
|
480
|
+
extensions.attachments.forEach((attachment, index) => {
|
|
481
|
+
if (!attachment.filename || !attachment.mimeType) {
|
|
482
|
+
results.push({
|
|
483
|
+
ruleId: 'FX-EXT-01',
|
|
484
|
+
severity: 'warning',
|
|
485
|
+
message: `Attachment ${index + 1}: Should include filename and MIME type`,
|
|
486
|
+
field: `metadata.extensions.attachments[${index}]`,
|
|
487
|
+
source: 'FACTURX'
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
});
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
return results;
|
|
494
|
+
}
|
|
495
|
+
/**
|
|
496
|
+
* Get profile display name
|
|
497
|
+
*/
|
|
498
|
+
getProfileDisplayName(profile) {
|
|
499
|
+
const names = {
|
|
500
|
+
[FacturXProfile.MINIMUM]: 'Factur-X MINIMUM',
|
|
501
|
+
[FacturXProfile.BASIC]: 'Factur-X BASIC',
|
|
502
|
+
[FacturXProfile.BASIC_WL]: 'Factur-X BASIC WL',
|
|
503
|
+
[FacturXProfile.EN16931]: 'Factur-X EN16931',
|
|
504
|
+
[FacturXProfile.EXTENDED]: 'Factur-X EXTENDED'
|
|
505
|
+
};
|
|
506
|
+
return names[profile];
|
|
507
|
+
}
|
|
508
|
+
/**
|
|
509
|
+
* Get profile compliance level (for reporting)
|
|
510
|
+
*/
|
|
511
|
+
getProfileComplianceLevel(profile) {
|
|
512
|
+
const levels = {
|
|
513
|
+
[FacturXProfile.MINIMUM]: 1,
|
|
514
|
+
[FacturXProfile.BASIC_WL]: 2,
|
|
515
|
+
[FacturXProfile.BASIC]: 3,
|
|
516
|
+
[FacturXProfile.EN16931]: 4,
|
|
517
|
+
[FacturXProfile.EXTENDED]: 5
|
|
518
|
+
};
|
|
519
|
+
return levels[profile];
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFjdHVyeC52YWxpZGF0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9mb3JtYXRzL3ZhbGlkYXRpb24vZmFjdHVyeC52YWxpZGF0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7OztHQUdHO0FBS0g7O0dBRUc7QUFDSCxNQUFNLENBQU4sSUFBWSxjQU1YO0FBTkQsV0FBWSxjQUFjO0lBQ3hCLHFDQUFtQixDQUFBO0lBQ25CLGlDQUFlLENBQUE7SUFDZix1Q0FBcUIsQ0FBQTtJQUNyQixxQ0FBbUIsQ0FBQTtJQUNuQix1Q0FBcUIsQ0FBQTtBQUN2QixDQUFDLEVBTlcsY0FBYyxLQUFkLGNBQWMsUUFNekI7QUFXRDs7O0dBR0c7QUFDSCxNQUFNLE9BQU8sZ0JBQWdCO0lBQTdCO1FBR0U7O1dBRUc7UUFDSyx3QkFBbUIsR0FBZ0Q7WUFDekUsQ0FBQyxjQUFjLENBQUMsT0FBTyxDQUFDLEVBQUU7Z0JBQ3hCLFNBQVMsRUFBRTtvQkFDVCxpQkFBaUIsRUFBTyx1QkFBdUI7b0JBQy9DLFdBQVcsRUFBWSwyQkFBMkI7b0JBQ2xELG1CQUFtQixFQUFJLDBCQUEwQjtvQkFDakQsVUFBVSxFQUFhLDhCQUE4QjtvQkFDckQsV0FBVyxFQUFZLHFCQUFxQjtvQkFDNUMsZ0JBQWdCLEVBQU8sK0JBQStCO29CQUN0RCxTQUFTLEVBQWMsb0JBQW9CO29CQUMzQyxvQkFBb0IsRUFBRyx3Q0FBd0M7b0JBQy9ELGdCQUFnQixFQUFPLDJDQUEyQztvQkFDbEUsZ0JBQWdCLEVBQU8sbUNBQW1DO2lCQUMzRDtnQkFDRCxRQUFRLEVBQUUsRUFBRTthQUNiO1lBRUQsQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLEVBQUU7Z0JBQ3RCLFNBQVMsRUFBRTtvQkFDVCwyQkFBMkI7b0JBQzNCLGlCQUFpQjtvQkFDakIsV0FBVztvQkFDWCxtQkFBbUI7b0JBQ25CLFVBQVU7b0JBQ1YsV0FBVztvQkFDWCxnQkFBZ0I7b0JBQ2hCLGNBQWMsRUFBUywr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
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Main integrated validator combining all validation capabilities
|
|
3
|
+
* Orchestrates TypeScript validators, Schematron, and profile-specific rules
|
|
4
|
+
*/
|
|
5
|
+
import type { ValidationOptions, ValidationReport } from './validation.types.js';
|
|
6
|
+
import type { EInvoice } from '../../einvoice.js';
|
|
7
|
+
/**
|
|
8
|
+
* Main validator that combines all validation capabilities
|
|
9
|
+
*/
|
|
10
|
+
export declare class MainValidator {
|
|
11
|
+
private integratedValidator;
|
|
12
|
+
private xrechnungValidator;
|
|
13
|
+
private peppolValidator;
|
|
14
|
+
private facturxValidator;
|
|
15
|
+
private businessRulesValidator;
|
|
16
|
+
private codeListValidator;
|
|
17
|
+
private schematronEnabled;
|
|
18
|
+
constructor();
|
|
19
|
+
/**
|
|
20
|
+
* Initialize Schematron validation for better coverage
|
|
21
|
+
*/
|
|
22
|
+
initializeSchematron(profile?: 'EN16931' | 'PEPPOL' | 'XRECHNUNG'): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Validate an invoice with all available validators
|
|
25
|
+
*/
|
|
26
|
+
validate(invoice: EInvoice, xmlContent?: string, options?: ValidationOptions): Promise<ValidationReport>;
|
|
27
|
+
/**
|
|
28
|
+
* Detect profile from invoice metadata
|
|
29
|
+
*/
|
|
30
|
+
private detectProfile;
|
|
31
|
+
/**
|
|
32
|
+
* Check if invoice is XRechnung
|
|
33
|
+
*/
|
|
34
|
+
private isXRechnungInvoice;
|
|
35
|
+
/**
|
|
36
|
+
* Check if invoice is PEPPOL
|
|
37
|
+
*/
|
|
38
|
+
private isPeppolInvoice;
|
|
39
|
+
/**
|
|
40
|
+
* Check if invoice is Factur-X
|
|
41
|
+
*/
|
|
42
|
+
private isFacturXInvoice;
|
|
43
|
+
/**
|
|
44
|
+
* Detect format from XML content
|
|
45
|
+
*/
|
|
46
|
+
private detectFormat;
|
|
47
|
+
/**
|
|
48
|
+
* Remove duplicate validation results
|
|
49
|
+
*/
|
|
50
|
+
private deduplicateResults;
|
|
51
|
+
/**
|
|
52
|
+
* Estimate total rules for coverage calculation
|
|
53
|
+
*/
|
|
54
|
+
private estimateTotalRules;
|
|
55
|
+
/**
|
|
56
|
+
* Validate with automatic format and profile detection
|
|
57
|
+
*/
|
|
58
|
+
validateAuto(invoice: EInvoice, xmlContent?: string): Promise<ValidationReport>;
|
|
59
|
+
/**
|
|
60
|
+
* Get validation capabilities
|
|
61
|
+
*/
|
|
62
|
+
getCapabilities(): {
|
|
63
|
+
schematron: boolean;
|
|
64
|
+
xrechnung: boolean;
|
|
65
|
+
peppol: boolean;
|
|
66
|
+
facturx: boolean;
|
|
67
|
+
calculations: boolean;
|
|
68
|
+
codeLists: boolean;
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* Format validation report as text
|
|
72
|
+
*/
|
|
73
|
+
formatReport(report: ValidationReport): string;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Create a pre-configured validator instance
|
|
77
|
+
*/
|
|
78
|
+
export declare function createValidator(options?: {
|
|
79
|
+
profile?: 'EN16931' | 'PEPPOL' | 'XRECHNUNG';
|
|
80
|
+
enableSchematron?: boolean;
|
|
81
|
+
}): Promise<MainValidator>;
|
|
82
|
+
export type { ValidationReport, ValidationResult, ValidationOptions } from './validation.types.js';
|