@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.
- 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/npmextra.json +1 -1
- package/package.json +12 -6
- 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,596 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Semantic Model Validator
|
|
3
|
+
* Validates invoices against EN16931 Business Terms and Business Groups
|
|
4
|
+
*/
|
|
5
|
+
import { SemanticModelAdapter } from './semantic.adapter.js';
|
|
6
|
+
/**
|
|
7
|
+
* Semantic Model Validator
|
|
8
|
+
* Validates against all EN16931 Business Terms (BT) and Business Groups (BG)
|
|
9
|
+
*/
|
|
10
|
+
export class SemanticModelValidator {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.adapter = new SemanticModelAdapter();
|
|
13
|
+
this.btRules = this.initializeBusinessTermRules();
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Validate an invoice using the semantic model
|
|
17
|
+
*/
|
|
18
|
+
validate(invoice) {
|
|
19
|
+
const results = [];
|
|
20
|
+
// Convert to semantic model
|
|
21
|
+
const model = this.adapter.toSemanticModel(invoice);
|
|
22
|
+
// Validate all business terms
|
|
23
|
+
for (const rule of this.btRules) {
|
|
24
|
+
const result = rule.validate(model);
|
|
25
|
+
if (result) {
|
|
26
|
+
results.push(result);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
// Validate business groups
|
|
30
|
+
results.push(...this.validateBusinessGroups(model));
|
|
31
|
+
// Validate cardinality constraints
|
|
32
|
+
results.push(...this.validateCardinality(model));
|
|
33
|
+
// Validate conditional rules
|
|
34
|
+
results.push(...this.validateConditionalRules(model));
|
|
35
|
+
return results;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Initialize Business Term validation rules
|
|
39
|
+
*/
|
|
40
|
+
initializeBusinessTermRules() {
|
|
41
|
+
return [
|
|
42
|
+
// Document level mandatory fields
|
|
43
|
+
{
|
|
44
|
+
btId: 'BT-1',
|
|
45
|
+
description: 'Invoice number',
|
|
46
|
+
mandatory: true,
|
|
47
|
+
validate: (model) => {
|
|
48
|
+
if (!model.documentInformation.invoiceNumber) {
|
|
49
|
+
return {
|
|
50
|
+
ruleId: 'BT-1',
|
|
51
|
+
severity: 'error',
|
|
52
|
+
message: 'Invoice number is mandatory',
|
|
53
|
+
field: 'documentInformation.invoiceNumber',
|
|
54
|
+
btReference: 'BT-1',
|
|
55
|
+
source: 'SEMANTIC'
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
btId: 'BT-2',
|
|
63
|
+
description: 'Invoice issue date',
|
|
64
|
+
mandatory: true,
|
|
65
|
+
validate: (model) => {
|
|
66
|
+
if (!model.documentInformation.issueDate) {
|
|
67
|
+
return {
|
|
68
|
+
ruleId: 'BT-2',
|
|
69
|
+
severity: 'error',
|
|
70
|
+
message: 'Invoice issue date is mandatory',
|
|
71
|
+
field: 'documentInformation.issueDate',
|
|
72
|
+
btReference: 'BT-2',
|
|
73
|
+
source: 'SEMANTIC'
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
btId: 'BT-3',
|
|
81
|
+
description: 'Invoice type code',
|
|
82
|
+
mandatory: true,
|
|
83
|
+
validate: (model) => {
|
|
84
|
+
if (!model.documentInformation.typeCode) {
|
|
85
|
+
return {
|
|
86
|
+
ruleId: 'BT-3',
|
|
87
|
+
severity: 'error',
|
|
88
|
+
message: 'Invoice type code is mandatory',
|
|
89
|
+
field: 'documentInformation.typeCode',
|
|
90
|
+
btReference: 'BT-3',
|
|
91
|
+
source: 'SEMANTIC'
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
const validCodes = ['380', '381', '383', '384', '386', '389'];
|
|
95
|
+
if (!validCodes.includes(model.documentInformation.typeCode)) {
|
|
96
|
+
return {
|
|
97
|
+
ruleId: 'BT-3',
|
|
98
|
+
severity: 'error',
|
|
99
|
+
message: `Invalid invoice type code. Must be one of: ${validCodes.join(', ')}`,
|
|
100
|
+
field: 'documentInformation.typeCode',
|
|
101
|
+
value: model.documentInformation.typeCode,
|
|
102
|
+
btReference: 'BT-3',
|
|
103
|
+
source: 'SEMANTIC'
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
btId: 'BT-5',
|
|
111
|
+
description: 'Invoice currency code',
|
|
112
|
+
mandatory: true,
|
|
113
|
+
validate: (model) => {
|
|
114
|
+
if (!model.documentInformation.currencyCode) {
|
|
115
|
+
return {
|
|
116
|
+
ruleId: 'BT-5',
|
|
117
|
+
severity: 'error',
|
|
118
|
+
message: 'Invoice currency code is mandatory',
|
|
119
|
+
field: 'documentInformation.currencyCode',
|
|
120
|
+
btReference: 'BT-5',
|
|
121
|
+
source: 'SEMANTIC'
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
// Validate ISO 4217 currency code
|
|
125
|
+
if (!/^[A-Z]{3}$/.test(model.documentInformation.currencyCode)) {
|
|
126
|
+
return {
|
|
127
|
+
ruleId: 'BT-5',
|
|
128
|
+
severity: 'error',
|
|
129
|
+
message: 'Currency code must be a valid ISO 4217 code',
|
|
130
|
+
field: 'documentInformation.currencyCode',
|
|
131
|
+
value: model.documentInformation.currencyCode,
|
|
132
|
+
btReference: 'BT-5',
|
|
133
|
+
source: 'SEMANTIC'
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
// Seller mandatory fields
|
|
140
|
+
{
|
|
141
|
+
btId: 'BT-27',
|
|
142
|
+
description: 'Seller name',
|
|
143
|
+
mandatory: true,
|
|
144
|
+
validate: (model) => {
|
|
145
|
+
if (!model.seller?.name) {
|
|
146
|
+
return {
|
|
147
|
+
ruleId: 'BT-27',
|
|
148
|
+
severity: 'error',
|
|
149
|
+
message: 'Seller name is mandatory',
|
|
150
|
+
field: 'seller.name',
|
|
151
|
+
btReference: 'BT-27',
|
|
152
|
+
source: 'SEMANTIC'
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
btId: 'BT-40',
|
|
160
|
+
description: 'Seller country code',
|
|
161
|
+
mandatory: true,
|
|
162
|
+
validate: (model) => {
|
|
163
|
+
if (!model.seller?.postalAddress?.countryCode) {
|
|
164
|
+
return {
|
|
165
|
+
ruleId: 'BT-40',
|
|
166
|
+
severity: 'error',
|
|
167
|
+
message: 'Seller country code is mandatory',
|
|
168
|
+
field: 'seller.postalAddress.countryCode',
|
|
169
|
+
btReference: 'BT-40',
|
|
170
|
+
source: 'SEMANTIC'
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
// Validate ISO 3166-1 alpha-2 country code
|
|
174
|
+
if (!/^[A-Z]{2}$/.test(model.seller.postalAddress.countryCode)) {
|
|
175
|
+
return {
|
|
176
|
+
ruleId: 'BT-40',
|
|
177
|
+
severity: 'error',
|
|
178
|
+
message: 'Country code must be a valid ISO 3166-1 alpha-2 code',
|
|
179
|
+
field: 'seller.postalAddress.countryCode',
|
|
180
|
+
value: model.seller.postalAddress.countryCode,
|
|
181
|
+
btReference: 'BT-40',
|
|
182
|
+
source: 'SEMANTIC'
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
},
|
|
188
|
+
// Buyer mandatory fields
|
|
189
|
+
{
|
|
190
|
+
btId: 'BT-44',
|
|
191
|
+
description: 'Buyer name',
|
|
192
|
+
mandatory: true,
|
|
193
|
+
validate: (model) => {
|
|
194
|
+
if (!model.buyer?.name) {
|
|
195
|
+
return {
|
|
196
|
+
ruleId: 'BT-44',
|
|
197
|
+
severity: 'error',
|
|
198
|
+
message: 'Buyer name is mandatory',
|
|
199
|
+
field: 'buyer.name',
|
|
200
|
+
btReference: 'BT-44',
|
|
201
|
+
source: 'SEMANTIC'
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
return null;
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
btId: 'BT-55',
|
|
209
|
+
description: 'Buyer country code',
|
|
210
|
+
mandatory: true,
|
|
211
|
+
validate: (model) => {
|
|
212
|
+
if (!model.buyer?.postalAddress?.countryCode) {
|
|
213
|
+
return {
|
|
214
|
+
ruleId: 'BT-55',
|
|
215
|
+
severity: 'error',
|
|
216
|
+
message: 'Buyer country code is mandatory',
|
|
217
|
+
field: 'buyer.postalAddress.countryCode',
|
|
218
|
+
btReference: 'BT-55',
|
|
219
|
+
source: 'SEMANTIC'
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
// Validate ISO 3166-1 alpha-2 country code
|
|
223
|
+
if (!/^[A-Z]{2}$/.test(model.buyer.postalAddress.countryCode)) {
|
|
224
|
+
return {
|
|
225
|
+
ruleId: 'BT-55',
|
|
226
|
+
severity: 'error',
|
|
227
|
+
message: 'Country code must be a valid ISO 3166-1 alpha-2 code',
|
|
228
|
+
field: 'buyer.postalAddress.countryCode',
|
|
229
|
+
value: model.buyer.postalAddress.countryCode,
|
|
230
|
+
btReference: 'BT-55',
|
|
231
|
+
source: 'SEMANTIC'
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
return null;
|
|
235
|
+
}
|
|
236
|
+
},
|
|
237
|
+
// Payment means
|
|
238
|
+
{
|
|
239
|
+
btId: 'BT-81',
|
|
240
|
+
description: 'Payment means type code',
|
|
241
|
+
mandatory: true,
|
|
242
|
+
validate: (model) => {
|
|
243
|
+
if (!model.paymentInstructions?.paymentMeansTypeCode) {
|
|
244
|
+
return {
|
|
245
|
+
ruleId: 'BT-81',
|
|
246
|
+
severity: 'error',
|
|
247
|
+
message: 'Payment means type code is mandatory',
|
|
248
|
+
field: 'paymentInstructions.paymentMeansTypeCode',
|
|
249
|
+
btReference: 'BT-81',
|
|
250
|
+
source: 'SEMANTIC'
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
return null;
|
|
254
|
+
}
|
|
255
|
+
},
|
|
256
|
+
// Document totals
|
|
257
|
+
{
|
|
258
|
+
btId: 'BT-106',
|
|
259
|
+
description: 'Sum of invoice line net amount',
|
|
260
|
+
mandatory: true,
|
|
261
|
+
validate: (model) => {
|
|
262
|
+
if (model.documentTotals?.lineExtensionAmount === undefined) {
|
|
263
|
+
return {
|
|
264
|
+
ruleId: 'BT-106',
|
|
265
|
+
severity: 'error',
|
|
266
|
+
message: 'Sum of invoice line net amount is mandatory',
|
|
267
|
+
field: 'documentTotals.lineExtensionAmount',
|
|
268
|
+
btReference: 'BT-106',
|
|
269
|
+
source: 'SEMANTIC'
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
return null;
|
|
273
|
+
}
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
btId: 'BT-109',
|
|
277
|
+
description: 'Invoice total amount without VAT',
|
|
278
|
+
mandatory: true,
|
|
279
|
+
validate: (model) => {
|
|
280
|
+
if (model.documentTotals?.taxExclusiveAmount === undefined) {
|
|
281
|
+
return {
|
|
282
|
+
ruleId: 'BT-109',
|
|
283
|
+
severity: 'error',
|
|
284
|
+
message: 'Invoice total amount without VAT is mandatory',
|
|
285
|
+
field: 'documentTotals.taxExclusiveAmount',
|
|
286
|
+
btReference: 'BT-109',
|
|
287
|
+
source: 'SEMANTIC'
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
return null;
|
|
291
|
+
}
|
|
292
|
+
},
|
|
293
|
+
{
|
|
294
|
+
btId: 'BT-112',
|
|
295
|
+
description: 'Invoice total amount with VAT',
|
|
296
|
+
mandatory: true,
|
|
297
|
+
validate: (model) => {
|
|
298
|
+
if (model.documentTotals?.taxInclusiveAmount === undefined) {
|
|
299
|
+
return {
|
|
300
|
+
ruleId: 'BT-112',
|
|
301
|
+
severity: 'error',
|
|
302
|
+
message: 'Invoice total amount with VAT is mandatory',
|
|
303
|
+
field: 'documentTotals.taxInclusiveAmount',
|
|
304
|
+
btReference: 'BT-112',
|
|
305
|
+
source: 'SEMANTIC'
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
return null;
|
|
309
|
+
}
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
btId: 'BT-115',
|
|
313
|
+
description: 'Amount due for payment',
|
|
314
|
+
mandatory: true,
|
|
315
|
+
validate: (model) => {
|
|
316
|
+
if (model.documentTotals?.payableAmount === undefined) {
|
|
317
|
+
return {
|
|
318
|
+
ruleId: 'BT-115',
|
|
319
|
+
severity: 'error',
|
|
320
|
+
message: 'Amount due for payment is mandatory',
|
|
321
|
+
field: 'documentTotals.payableAmount',
|
|
322
|
+
btReference: 'BT-115',
|
|
323
|
+
source: 'SEMANTIC'
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
return null;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
];
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Validate Business Groups
|
|
333
|
+
*/
|
|
334
|
+
validateBusinessGroups(model) {
|
|
335
|
+
const results = [];
|
|
336
|
+
// BG-4: Seller
|
|
337
|
+
if (!model.seller) {
|
|
338
|
+
results.push({
|
|
339
|
+
ruleId: 'BG-4',
|
|
340
|
+
severity: 'error',
|
|
341
|
+
message: 'Seller information is mandatory',
|
|
342
|
+
field: 'seller',
|
|
343
|
+
bgReference: 'BG-4',
|
|
344
|
+
source: 'SEMANTIC'
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
// BG-5: Seller postal address
|
|
348
|
+
if (!model.seller?.postalAddress) {
|
|
349
|
+
results.push({
|
|
350
|
+
ruleId: 'BG-5',
|
|
351
|
+
severity: 'error',
|
|
352
|
+
message: 'Seller postal address is mandatory',
|
|
353
|
+
field: 'seller.postalAddress',
|
|
354
|
+
bgReference: 'BG-5',
|
|
355
|
+
source: 'SEMANTIC'
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
// BG-7: Buyer
|
|
359
|
+
if (!model.buyer) {
|
|
360
|
+
results.push({
|
|
361
|
+
ruleId: 'BG-7',
|
|
362
|
+
severity: 'error',
|
|
363
|
+
message: 'Buyer information is mandatory',
|
|
364
|
+
field: 'buyer',
|
|
365
|
+
bgReference: 'BG-7',
|
|
366
|
+
source: 'SEMANTIC'
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
// BG-8: Buyer postal address
|
|
370
|
+
if (!model.buyer?.postalAddress) {
|
|
371
|
+
results.push({
|
|
372
|
+
ruleId: 'BG-8',
|
|
373
|
+
severity: 'error',
|
|
374
|
+
message: 'Buyer postal address is mandatory',
|
|
375
|
+
field: 'buyer.postalAddress',
|
|
376
|
+
bgReference: 'BG-8',
|
|
377
|
+
source: 'SEMANTIC'
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
// BG-16: Payment instructions
|
|
381
|
+
if (!model.paymentInstructions) {
|
|
382
|
+
results.push({
|
|
383
|
+
ruleId: 'BG-16',
|
|
384
|
+
severity: 'error',
|
|
385
|
+
message: 'Payment instructions are mandatory',
|
|
386
|
+
field: 'paymentInstructions',
|
|
387
|
+
bgReference: 'BG-16',
|
|
388
|
+
source: 'SEMANTIC'
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
// BG-22: Document totals
|
|
392
|
+
if (!model.documentTotals) {
|
|
393
|
+
results.push({
|
|
394
|
+
ruleId: 'BG-22',
|
|
395
|
+
severity: 'error',
|
|
396
|
+
message: 'Document totals are mandatory',
|
|
397
|
+
field: 'documentTotals',
|
|
398
|
+
bgReference: 'BG-22',
|
|
399
|
+
source: 'SEMANTIC'
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
// BG-25: Invoice lines
|
|
403
|
+
if (!model.invoiceLines || model.invoiceLines.length === 0) {
|
|
404
|
+
results.push({
|
|
405
|
+
ruleId: 'BG-25',
|
|
406
|
+
severity: 'error',
|
|
407
|
+
message: 'At least one invoice line is mandatory',
|
|
408
|
+
field: 'invoiceLines',
|
|
409
|
+
bgReference: 'BG-25',
|
|
410
|
+
source: 'SEMANTIC'
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
// Validate each invoice line
|
|
414
|
+
model.invoiceLines?.forEach((line, index) => {
|
|
415
|
+
// BT-126: Line identifier
|
|
416
|
+
if (!line.identifier) {
|
|
417
|
+
results.push({
|
|
418
|
+
ruleId: 'BT-126',
|
|
419
|
+
severity: 'error',
|
|
420
|
+
message: `Invoice line ${index + 1}: Identifier is mandatory`,
|
|
421
|
+
field: `invoiceLines[${index}].identifier`,
|
|
422
|
+
btReference: 'BT-126',
|
|
423
|
+
source: 'SEMANTIC'
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
// BT-129: Invoiced quantity
|
|
427
|
+
if (line.invoicedQuantity === undefined) {
|
|
428
|
+
results.push({
|
|
429
|
+
ruleId: 'BT-129',
|
|
430
|
+
severity: 'error',
|
|
431
|
+
message: `Invoice line ${index + 1}: Invoiced quantity is mandatory`,
|
|
432
|
+
field: `invoiceLines[${index}].invoicedQuantity`,
|
|
433
|
+
btReference: 'BT-129',
|
|
434
|
+
source: 'SEMANTIC'
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
// BT-131: Line net amount
|
|
438
|
+
if (line.lineExtensionAmount === undefined) {
|
|
439
|
+
results.push({
|
|
440
|
+
ruleId: 'BT-131',
|
|
441
|
+
severity: 'error',
|
|
442
|
+
message: `Invoice line ${index + 1}: Line net amount is mandatory`,
|
|
443
|
+
field: `invoiceLines[${index}].lineExtensionAmount`,
|
|
444
|
+
btReference: 'BT-131',
|
|
445
|
+
source: 'SEMANTIC'
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
// BT-153: Item name
|
|
449
|
+
if (!line.itemInformation?.name) {
|
|
450
|
+
results.push({
|
|
451
|
+
ruleId: 'BT-153',
|
|
452
|
+
severity: 'error',
|
|
453
|
+
message: `Invoice line ${index + 1}: Item name is mandatory`,
|
|
454
|
+
field: `invoiceLines[${index}].itemInformation.name`,
|
|
455
|
+
btReference: 'BT-153',
|
|
456
|
+
source: 'SEMANTIC'
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
});
|
|
460
|
+
return results;
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* Validate cardinality constraints
|
|
464
|
+
*/
|
|
465
|
+
validateCardinality(model) {
|
|
466
|
+
const results = [];
|
|
467
|
+
// Check for duplicate invoice lines
|
|
468
|
+
const lineIds = model.invoiceLines?.map(l => l.identifier) || [];
|
|
469
|
+
const uniqueIds = new Set(lineIds);
|
|
470
|
+
if (lineIds.length !== uniqueIds.size) {
|
|
471
|
+
results.push({
|
|
472
|
+
ruleId: 'CARD-01',
|
|
473
|
+
severity: 'error',
|
|
474
|
+
message: 'Invoice line identifiers must be unique',
|
|
475
|
+
field: 'invoiceLines',
|
|
476
|
+
source: 'SEMANTIC'
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
// Check VAT breakdown cardinality
|
|
480
|
+
if (model.vatBreakdown) {
|
|
481
|
+
const vatCategories = model.vatBreakdown.map(v => v.vatCategoryCode);
|
|
482
|
+
const uniqueCategories = new Set(vatCategories);
|
|
483
|
+
if (vatCategories.length !== uniqueCategories.size) {
|
|
484
|
+
results.push({
|
|
485
|
+
ruleId: 'CARD-02',
|
|
486
|
+
severity: 'error',
|
|
487
|
+
message: 'Each VAT category code must appear only once in VAT breakdown',
|
|
488
|
+
field: 'vatBreakdown',
|
|
489
|
+
source: 'SEMANTIC'
|
|
490
|
+
});
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
return results;
|
|
494
|
+
}
|
|
495
|
+
/**
|
|
496
|
+
* Validate conditional rules
|
|
497
|
+
*/
|
|
498
|
+
validateConditionalRules(model) {
|
|
499
|
+
const results = [];
|
|
500
|
+
// If VAT accounting currency code is present, VAT amount in accounting currency must be present
|
|
501
|
+
if (model.documentInformation.currencyCode !== model.documentInformation.currencyCode) {
|
|
502
|
+
if (!model.documentTotals?.taxInclusiveAmount) {
|
|
503
|
+
results.push({
|
|
504
|
+
ruleId: 'COND-01',
|
|
505
|
+
severity: 'error',
|
|
506
|
+
message: 'When VAT accounting currency differs from invoice currency, VAT amount in accounting currency is mandatory',
|
|
507
|
+
field: 'documentTotals.taxInclusiveAmount',
|
|
508
|
+
source: 'SEMANTIC'
|
|
509
|
+
});
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
// If credit note, there should be a preceding invoice reference
|
|
513
|
+
if (model.documentInformation.typeCode === '381') {
|
|
514
|
+
if (!model.references?.precedingInvoices || model.references.precedingInvoices.length === 0) {
|
|
515
|
+
results.push({
|
|
516
|
+
ruleId: 'COND-02',
|
|
517
|
+
severity: 'warning',
|
|
518
|
+
message: 'Credit notes should reference the original invoice',
|
|
519
|
+
field: 'references.precedingInvoices',
|
|
520
|
+
source: 'SEMANTIC'
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
// If tax representative is present, certain fields are mandatory
|
|
525
|
+
if (model.taxRepresentative) {
|
|
526
|
+
if (!model.taxRepresentative.vatIdentifier) {
|
|
527
|
+
results.push({
|
|
528
|
+
ruleId: 'COND-03',
|
|
529
|
+
severity: 'error',
|
|
530
|
+
message: 'Tax representative VAT identifier is mandatory when tax representative is present',
|
|
531
|
+
field: 'taxRepresentative.vatIdentifier',
|
|
532
|
+
source: 'SEMANTIC'
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
// VAT exemption requires exemption reason
|
|
537
|
+
if (model.vatBreakdown) {
|
|
538
|
+
for (const vat of model.vatBreakdown) {
|
|
539
|
+
if (vat.vatCategoryCode === 'E' && !vat.vatExemptionReasonText && !vat.vatExemptionReasonCode) {
|
|
540
|
+
results.push({
|
|
541
|
+
ruleId: 'COND-04',
|
|
542
|
+
severity: 'error',
|
|
543
|
+
message: 'VAT exemption requires exemption reason text or code',
|
|
544
|
+
field: 'vatBreakdown.vatExemptionReasonText',
|
|
545
|
+
source: 'SEMANTIC'
|
|
546
|
+
});
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
return results;
|
|
551
|
+
}
|
|
552
|
+
/**
|
|
553
|
+
* Get semantic model from invoice
|
|
554
|
+
*/
|
|
555
|
+
getSemanticModel(invoice) {
|
|
556
|
+
return this.adapter.toSemanticModel(invoice);
|
|
557
|
+
}
|
|
558
|
+
/**
|
|
559
|
+
* Create invoice from semantic model
|
|
560
|
+
*/
|
|
561
|
+
createInvoice(model) {
|
|
562
|
+
return this.adapter.fromSemanticModel(model);
|
|
563
|
+
}
|
|
564
|
+
/**
|
|
565
|
+
* Get BT/BG mapping for an invoice
|
|
566
|
+
*/
|
|
567
|
+
getBusinessTermMapping(invoice) {
|
|
568
|
+
const model = this.adapter.toSemanticModel(invoice);
|
|
569
|
+
const mapping = new Map();
|
|
570
|
+
// Map all business terms
|
|
571
|
+
mapping.set('BT-1', model.documentInformation.invoiceNumber);
|
|
572
|
+
mapping.set('BT-2', model.documentInformation.issueDate);
|
|
573
|
+
mapping.set('BT-3', model.documentInformation.typeCode);
|
|
574
|
+
mapping.set('BT-5', model.documentInformation.currencyCode);
|
|
575
|
+
mapping.set('BT-10', model.references?.buyerReference);
|
|
576
|
+
mapping.set('BT-27', model.seller?.name);
|
|
577
|
+
mapping.set('BT-40', model.seller?.postalAddress?.countryCode);
|
|
578
|
+
mapping.set('BT-44', model.buyer?.name);
|
|
579
|
+
mapping.set('BT-55', model.buyer?.postalAddress?.countryCode);
|
|
580
|
+
mapping.set('BT-81', model.paymentInstructions?.paymentMeansTypeCode);
|
|
581
|
+
mapping.set('BT-106', model.documentTotals?.lineExtensionAmount);
|
|
582
|
+
mapping.set('BT-109', model.documentTotals?.taxExclusiveAmount);
|
|
583
|
+
mapping.set('BT-112', model.documentTotals?.taxInclusiveAmount);
|
|
584
|
+
mapping.set('BT-115', model.documentTotals?.payableAmount);
|
|
585
|
+
// Map business groups
|
|
586
|
+
mapping.set('BG-4', model.seller);
|
|
587
|
+
mapping.set('BG-5', model.seller?.postalAddress);
|
|
588
|
+
mapping.set('BG-7', model.buyer);
|
|
589
|
+
mapping.set('BG-8', model.buyer?.postalAddress);
|
|
590
|
+
mapping.set('BG-16', model.paymentInstructions);
|
|
591
|
+
mapping.set('BG-22', model.documentTotals);
|
|
592
|
+
mapping.set('BG-25', model.invoiceLines);
|
|
593
|
+
return mapping;
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VtYW50aWMudmFsaWRhdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdHMvZm9ybWF0cy9zZW1hbnRpYy9zZW1hbnRpYy52YWxpZGF0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7OztHQUdHO0FBS0gsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFZN0Q7OztHQUdHO0FBQ0gsTUFBTSxPQUFPLHNCQUFzQjtJQUlqQztRQUNFLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxvQkFBb0IsRUFBRSxDQUFDO1FBQzFDLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLDJCQUEyQixFQUFFLENBQUM7SUFDcEQsQ0FBQztJQUVEOztPQUVHO0lBQ0ksUUFBUSxDQUFDLE9BQWlCO1FBQy9CLE1BQU0sT0FBTyxHQUF1QixFQUFFLENBQUM7UUFFdkMsNEJBQTRCO1FBQzVCLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsZUFBZSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRXBELDhCQUE4QjtRQUM5QixLQUFLLE1BQU0sSUFBSSxJQUFJLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNoQyxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3BDLElBQUksTUFBTSxFQUFFLENBQUM7Z0JBQ1gsT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUN2QixDQUFDO1FBQ0gsQ0FBQztRQUVELDJCQUEyQjtRQUMzQixPQUFPLENBQUMsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLHNCQUFzQixDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7UUFFcEQsbUNBQW1DO1FBQ25DLE9BQU8sQ0FBQyxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUMsbUJBQW1CLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztRQUVqRCw2QkFBNkI7UUFDN0IsT0FB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
|