@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
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import { BaseValidator } from './base.validator.js';
|
|
2
|
-
import { ValidationLevel } from '../interfaces.js';
|
|
3
|
-
import type { ValidationResult } from '../interfaces.js';
|
|
4
|
-
/**
|
|
5
|
-
* Validator for UBL (Universal Business Language) invoice format
|
|
6
|
-
* Implements validation rules according to EN16931 and UBL 2.1 specification
|
|
7
|
-
*/
|
|
8
|
-
export declare class UBLValidator extends BaseValidator {
|
|
9
|
-
private static NS_INVOICE;
|
|
10
|
-
private static NS_CAC;
|
|
11
|
-
private static NS_CBC;
|
|
12
|
-
private xmlDoc;
|
|
13
|
-
private customizationId;
|
|
14
|
-
constructor(xml: string);
|
|
15
|
-
/**
|
|
16
|
-
* Validates the UBL invoice against the specified level
|
|
17
|
-
* @param level Validation level
|
|
18
|
-
* @returns Validation result
|
|
19
|
-
*/
|
|
20
|
-
validate(level?: ValidationLevel): ValidationResult;
|
|
21
|
-
/**
|
|
22
|
-
* Validates XML against schema
|
|
23
|
-
* @returns True if schema validation passed
|
|
24
|
-
*/
|
|
25
|
-
protected validateSchema(): boolean;
|
|
26
|
-
/**
|
|
27
|
-
* Validates structure of the XML document
|
|
28
|
-
* @returns True if structure validation passed
|
|
29
|
-
*/
|
|
30
|
-
private validateStructure;
|
|
31
|
-
/**
|
|
32
|
-
* Validates business rules
|
|
33
|
-
* @returns True if business rule validation passed
|
|
34
|
-
*/
|
|
35
|
-
protected validateBusinessRules(): boolean;
|
|
36
|
-
/**
|
|
37
|
-
* Gets the root node name (Invoice or CreditNote)
|
|
38
|
-
* @returns Root node name
|
|
39
|
-
*/
|
|
40
|
-
private getRootNodeName;
|
|
41
|
-
/**
|
|
42
|
-
* Detects UBL customization ID from the XML
|
|
43
|
-
*/
|
|
44
|
-
private detectCustomizationId;
|
|
45
|
-
/**
|
|
46
|
-
* Checks if invoice is an XRechnung
|
|
47
|
-
* @returns True if XRechnung customization ID is present
|
|
48
|
-
*/
|
|
49
|
-
private isXRechnung;
|
|
50
|
-
/**
|
|
51
|
-
* Validates amount calculations in the invoice
|
|
52
|
-
* @returns True if amount validation passed
|
|
53
|
-
*/
|
|
54
|
-
private validateAmounts;
|
|
55
|
-
/**
|
|
56
|
-
* Validates mutually exclusive fields
|
|
57
|
-
* @returns True if validation passed
|
|
58
|
-
*/
|
|
59
|
-
private validateMutuallyExclusiveFields;
|
|
60
|
-
/**
|
|
61
|
-
* Validates seller VAT identifier requirements
|
|
62
|
-
* @returns True if validation passed
|
|
63
|
-
*/
|
|
64
|
-
private validateSellerVatIdentifier;
|
|
65
|
-
/**
|
|
66
|
-
* Validates XRechnung specific rules
|
|
67
|
-
* @returns True if validation passed
|
|
68
|
-
*/
|
|
69
|
-
private validateXRechnungRules;
|
|
70
|
-
/**
|
|
71
|
-
* Helper method to check if a node exists
|
|
72
|
-
* @param xpathExpression XPath to check
|
|
73
|
-
* @returns True if node exists
|
|
74
|
-
*/
|
|
75
|
-
private exists;
|
|
76
|
-
/**
|
|
77
|
-
* Helper method to get a number value from XPath
|
|
78
|
-
* @param xpathExpression XPath to get number from
|
|
79
|
-
* @returns Number value or NaN if not found
|
|
80
|
-
*/
|
|
81
|
-
private getNumberValue;
|
|
82
|
-
}
|
|
@@ -1,306 +0,0 @@
|
|
|
1
|
-
import { BaseValidator } from './base.validator.js';
|
|
2
|
-
import { ValidationLevel } from '../interfaces.js';
|
|
3
|
-
import * as xpath from 'xpath';
|
|
4
|
-
import { DOMParser } from 'xmldom';
|
|
5
|
-
/**
|
|
6
|
-
* Validator for UBL (Universal Business Language) invoice format
|
|
7
|
-
* Implements validation rules according to EN16931 and UBL 2.1 specification
|
|
8
|
-
*/
|
|
9
|
-
export class UBLValidator extends BaseValidator {
|
|
10
|
-
// XML namespaces for UBL
|
|
11
|
-
static { this.NS_INVOICE = 'urn:oasis:names:specification:ubl:schema:xsd:Invoice-2'; }
|
|
12
|
-
static { this.NS_CAC = 'urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2'; }
|
|
13
|
-
static { this.NS_CBC = 'urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2'; }
|
|
14
|
-
constructor(xml) {
|
|
15
|
-
super(xml);
|
|
16
|
-
// XML document for processing
|
|
17
|
-
this.xmlDoc = null;
|
|
18
|
-
// UBL profile or customization ID
|
|
19
|
-
this.customizationId = '';
|
|
20
|
-
try {
|
|
21
|
-
// Parse XML document
|
|
22
|
-
this.xmlDoc = new DOMParser().parseFromString(xml, 'application/xml');
|
|
23
|
-
// Determine UBL customization ID (e.g. EN16931, XRechnung)
|
|
24
|
-
this.detectCustomizationId();
|
|
25
|
-
}
|
|
26
|
-
catch (error) {
|
|
27
|
-
this.addError('UBL-PARSE', `Failed to parse XML: ${error}`, '/');
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Validates the UBL invoice against the specified level
|
|
32
|
-
* @param level Validation level
|
|
33
|
-
* @returns Validation result
|
|
34
|
-
*/
|
|
35
|
-
validate(level = ValidationLevel.SYNTAX) {
|
|
36
|
-
// Reset errors
|
|
37
|
-
this.errors = [];
|
|
38
|
-
// Check if document was parsed successfully
|
|
39
|
-
if (!this.xmlDoc) {
|
|
40
|
-
return {
|
|
41
|
-
valid: false,
|
|
42
|
-
errors: this.errors,
|
|
43
|
-
level: level
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
// Perform validation based on level
|
|
47
|
-
let valid = true;
|
|
48
|
-
if (level === ValidationLevel.SYNTAX) {
|
|
49
|
-
valid = this.validateSchema();
|
|
50
|
-
}
|
|
51
|
-
else if (level === ValidationLevel.SEMANTIC) {
|
|
52
|
-
valid = this.validateSchema() && this.validateStructure();
|
|
53
|
-
}
|
|
54
|
-
else if (level === ValidationLevel.BUSINESS) {
|
|
55
|
-
valid = this.validateSchema() &&
|
|
56
|
-
this.validateStructure() &&
|
|
57
|
-
this.validateBusinessRules();
|
|
58
|
-
}
|
|
59
|
-
return {
|
|
60
|
-
valid,
|
|
61
|
-
errors: this.errors,
|
|
62
|
-
level
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Validates XML against schema
|
|
67
|
-
* @returns True if schema validation passed
|
|
68
|
-
*/
|
|
69
|
-
validateSchema() {
|
|
70
|
-
// Basic schema validation (simplified for now)
|
|
71
|
-
if (!this.xmlDoc)
|
|
72
|
-
return false;
|
|
73
|
-
// Check for root element
|
|
74
|
-
const root = this.xmlDoc.documentElement;
|
|
75
|
-
if (!root || (root.nodeName !== 'Invoice' && root.nodeName !== 'CreditNote')) {
|
|
76
|
-
this.addError('UBL-SCHEMA-1', 'Root element must be Invoice or CreditNote', '/');
|
|
77
|
-
return false;
|
|
78
|
-
}
|
|
79
|
-
// Check for required namespaces
|
|
80
|
-
if (!root.lookupNamespaceURI('cac') || !root.lookupNamespaceURI('cbc')) {
|
|
81
|
-
this.addError('UBL-SCHEMA-2', 'Required namespaces cac and cbc must be declared', '/');
|
|
82
|
-
return false;
|
|
83
|
-
}
|
|
84
|
-
return true;
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* Validates structure of the XML document
|
|
88
|
-
* @returns True if structure validation passed
|
|
89
|
-
*/
|
|
90
|
-
validateStructure() {
|
|
91
|
-
if (!this.xmlDoc)
|
|
92
|
-
return false;
|
|
93
|
-
let valid = true;
|
|
94
|
-
// Check for required main sections
|
|
95
|
-
const sections = [
|
|
96
|
-
'cbc:ID',
|
|
97
|
-
'cbc:IssueDate',
|
|
98
|
-
'cac:AccountingSupplierParty',
|
|
99
|
-
'cac:AccountingCustomerParty',
|
|
100
|
-
'cac:LegalMonetaryTotal'
|
|
101
|
-
];
|
|
102
|
-
for (const section of sections) {
|
|
103
|
-
if (!this.exists(`/${this.getRootNodeName()}/${section}`)) {
|
|
104
|
-
this.addError('UBL-STRUCT-1', `Required section ${section} is missing`, `/${this.getRootNodeName()}`);
|
|
105
|
-
valid = false;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
// Check for TaxTotal section
|
|
109
|
-
if (this.exists(`/${this.getRootNodeName()}/cac:TaxTotal`)) {
|
|
110
|
-
const taxSubsections = [
|
|
111
|
-
'cbc:TaxAmount',
|
|
112
|
-
'cac:TaxSubtotal'
|
|
113
|
-
];
|
|
114
|
-
for (const subsection of taxSubsections) {
|
|
115
|
-
if (!this.exists(`/${this.getRootNodeName()}/cac:TaxTotal/${subsection}`)) {
|
|
116
|
-
this.addError('UBL-STRUCT-2', `Required subsection ${subsection} is missing`, `/${this.getRootNodeName()}/cac:TaxTotal`);
|
|
117
|
-
valid = false;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
return valid;
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* Validates business rules
|
|
125
|
-
* @returns True if business rule validation passed
|
|
126
|
-
*/
|
|
127
|
-
validateBusinessRules() {
|
|
128
|
-
if (!this.xmlDoc)
|
|
129
|
-
return false;
|
|
130
|
-
let valid = true;
|
|
131
|
-
// BR-16: Amount due for payment (BT-115) = Invoice total amount with VAT (BT-112) - Paid amount (BT-113)
|
|
132
|
-
valid = this.validateAmounts() && valid;
|
|
133
|
-
// BR-CO-3: Value added tax point date (BT-7) and Value added tax point date code (BT-8) are mutually exclusive
|
|
134
|
-
valid = this.validateMutuallyExclusiveFields() && valid;
|
|
135
|
-
// BR-S-1: An Invoice that contains a line where the VAT category code is "Standard rated"
|
|
136
|
-
// shall contain the Seller VAT Identifier or the Seller tax representative VAT identifier
|
|
137
|
-
valid = this.validateSellerVatIdentifier() && valid;
|
|
138
|
-
// XRechnung specific rules when customization ID matches
|
|
139
|
-
if (this.isXRechnung()) {
|
|
140
|
-
valid = this.validateXRechnungRules() && valid;
|
|
141
|
-
}
|
|
142
|
-
return valid;
|
|
143
|
-
}
|
|
144
|
-
/**
|
|
145
|
-
* Gets the root node name (Invoice or CreditNote)
|
|
146
|
-
* @returns Root node name
|
|
147
|
-
*/
|
|
148
|
-
getRootNodeName() {
|
|
149
|
-
if (!this.xmlDoc || !this.xmlDoc.documentElement)
|
|
150
|
-
return 'Invoice';
|
|
151
|
-
return this.xmlDoc.documentElement.nodeName;
|
|
152
|
-
}
|
|
153
|
-
/**
|
|
154
|
-
* Detects UBL customization ID from the XML
|
|
155
|
-
*/
|
|
156
|
-
detectCustomizationId() {
|
|
157
|
-
if (!this.xmlDoc)
|
|
158
|
-
return;
|
|
159
|
-
// Look for customization ID
|
|
160
|
-
const customizationNode = xpath.select1(`string(/${this.getRootNodeName()}/cbc:CustomizationID)`, this.xmlDoc);
|
|
161
|
-
if (customizationNode) {
|
|
162
|
-
this.customizationId = customizationNode.toString();
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
/**
|
|
166
|
-
* Checks if invoice is an XRechnung
|
|
167
|
-
* @returns True if XRechnung customization ID is present
|
|
168
|
-
*/
|
|
169
|
-
isXRechnung() {
|
|
170
|
-
return this.customizationId.includes('xrechnung') ||
|
|
171
|
-
this.customizationId.includes('XRechnung');
|
|
172
|
-
}
|
|
173
|
-
/**
|
|
174
|
-
* Validates amount calculations in the invoice
|
|
175
|
-
* @returns True if amount validation passed
|
|
176
|
-
*/
|
|
177
|
-
validateAmounts() {
|
|
178
|
-
if (!this.xmlDoc)
|
|
179
|
-
return false;
|
|
180
|
-
try {
|
|
181
|
-
// Extract amounts
|
|
182
|
-
const totalAmount = this.getNumberValue(`/${this.getRootNodeName()}/cac:LegalMonetaryTotal/cbc:TaxInclusiveAmount`);
|
|
183
|
-
const paidAmount = this.getNumberValue(`/${this.getRootNodeName()}/cac:LegalMonetaryTotal/cbc:PrepaidAmount`) || 0;
|
|
184
|
-
const dueAmount = this.getNumberValue(`/${this.getRootNodeName()}/cac:LegalMonetaryTotal/cbc:PayableAmount`);
|
|
185
|
-
// Calculate expected due amount
|
|
186
|
-
const expectedDueAmount = totalAmount - paidAmount;
|
|
187
|
-
// Compare with a small tolerance for rounding errors
|
|
188
|
-
if (Math.abs(dueAmount - expectedDueAmount) > 0.01) {
|
|
189
|
-
this.addError('BR-16', `Amount due for payment (${dueAmount}) must equal Invoice total amount with VAT (${totalAmount}) - Paid amount (${paidAmount})`, `/${this.getRootNodeName()}/cac:LegalMonetaryTotal`);
|
|
190
|
-
return false;
|
|
191
|
-
}
|
|
192
|
-
return true;
|
|
193
|
-
}
|
|
194
|
-
catch (error) {
|
|
195
|
-
this.addError('UBL-AMOUNT', `Error validating amounts: ${error}`, '/');
|
|
196
|
-
return false;
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
/**
|
|
200
|
-
* Validates mutually exclusive fields
|
|
201
|
-
* @returns True if validation passed
|
|
202
|
-
*/
|
|
203
|
-
validateMutuallyExclusiveFields() {
|
|
204
|
-
if (!this.xmlDoc)
|
|
205
|
-
return false;
|
|
206
|
-
try {
|
|
207
|
-
// Check for VAT point date and code (BR-CO-3)
|
|
208
|
-
const vatPointDate = this.exists(`/${this.getRootNodeName()}/cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cbc:TaxPointDate`);
|
|
209
|
-
const vatPointDateCode = this.exists(`/${this.getRootNodeName()}/cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cbc:TaxExemptionReasonCode`);
|
|
210
|
-
if (vatPointDate && vatPointDateCode) {
|
|
211
|
-
this.addError('BR-CO-3', 'Value added tax point date and Value added tax point date code are mutually exclusive', `/${this.getRootNodeName()}/cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory`);
|
|
212
|
-
return false;
|
|
213
|
-
}
|
|
214
|
-
return true;
|
|
215
|
-
}
|
|
216
|
-
catch (error) {
|
|
217
|
-
this.addError('UBL-MUTUAL', `Error validating mutually exclusive fields: ${error}`, '/');
|
|
218
|
-
return false;
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
/**
|
|
222
|
-
* Validates seller VAT identifier requirements
|
|
223
|
-
* @returns True if validation passed
|
|
224
|
-
*/
|
|
225
|
-
validateSellerVatIdentifier() {
|
|
226
|
-
if (!this.xmlDoc)
|
|
227
|
-
return false;
|
|
228
|
-
try {
|
|
229
|
-
// Check if there are any standard rated line items
|
|
230
|
-
const standardRatedItems = this.exists(`/${this.getRootNodeName()}/cac:InvoiceLine/cac:Item/cac:ClassifiedTaxCategory/cbc:ID[text()="S"]`);
|
|
231
|
-
if (standardRatedItems) {
|
|
232
|
-
// Check for seller VAT identifier
|
|
233
|
-
const sellerVatId = this.exists(`/${this.getRootNodeName()}/cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID`);
|
|
234
|
-
const sellerTaxRepId = this.exists(`/${this.getRootNodeName()}/cac:TaxRepresentativeParty/cac:PartyTaxScheme/cbc:CompanyID`);
|
|
235
|
-
if (!sellerVatId && !sellerTaxRepId) {
|
|
236
|
-
this.addError('BR-S-1', 'An Invoice with standard rated items must contain the Seller VAT Identifier or Tax representative VAT identifier', `/${this.getRootNodeName()}/cac:AccountingSupplierParty/cac:Party`);
|
|
237
|
-
return false;
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
return true;
|
|
241
|
-
}
|
|
242
|
-
catch (error) {
|
|
243
|
-
this.addError('UBL-VAT', `Error validating seller VAT identifier: ${error}`, '/');
|
|
244
|
-
return false;
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
/**
|
|
248
|
-
* Validates XRechnung specific rules
|
|
249
|
-
* @returns True if validation passed
|
|
250
|
-
*/
|
|
251
|
-
validateXRechnungRules() {
|
|
252
|
-
if (!this.xmlDoc)
|
|
253
|
-
return false;
|
|
254
|
-
let valid = true;
|
|
255
|
-
try {
|
|
256
|
-
// BR-DE-1: Buyer reference must be present for German VAT compliance
|
|
257
|
-
if (!this.exists(`/${this.getRootNodeName()}/cbc:BuyerReference`)) {
|
|
258
|
-
this.addError('BR-DE-1', 'BuyerReference is mandatory for XRechnung', `/${this.getRootNodeName()}`);
|
|
259
|
-
valid = false;
|
|
260
|
-
}
|
|
261
|
-
// BR-DE-15: Contact information must be present
|
|
262
|
-
if (!this.exists(`/${this.getRootNodeName()}/cac:AccountingSupplierParty/cac:Party/cac:Contact`)) {
|
|
263
|
-
this.addError('BR-DE-15', 'Supplier contact information is mandatory for XRechnung', `/${this.getRootNodeName()}/cac:AccountingSupplierParty/cac:Party`);
|
|
264
|
-
valid = false;
|
|
265
|
-
}
|
|
266
|
-
// BR-DE-16: Electronic address identifier scheme (e.g. PEPPOL) must be present
|
|
267
|
-
if (!this.exists(`/${this.getRootNodeName()}/cac:AccountingSupplierParty/cac:Party/cbc:EndpointID`) ||
|
|
268
|
-
!this.exists(`/${this.getRootNodeName()}/cac:AccountingSupplierParty/cac:Party/cbc:EndpointID/@schemeID`)) {
|
|
269
|
-
this.addError('BR-DE-16', 'Supplier electronic address with scheme identifier is mandatory for XRechnung', `/${this.getRootNodeName()}/cac:AccountingSupplierParty/cac:Party`);
|
|
270
|
-
valid = false;
|
|
271
|
-
}
|
|
272
|
-
return valid;
|
|
273
|
-
}
|
|
274
|
-
catch (error) {
|
|
275
|
-
this.addError('UBL-XRECHNUNG', `Error validating XRechnung rules: ${error}`, '/');
|
|
276
|
-
return false;
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
/**
|
|
280
|
-
* Helper method to check if a node exists
|
|
281
|
-
* @param xpathExpression XPath to check
|
|
282
|
-
* @returns True if node exists
|
|
283
|
-
*/
|
|
284
|
-
exists(xpathExpression) {
|
|
285
|
-
if (!this.xmlDoc)
|
|
286
|
-
return false;
|
|
287
|
-
const nodes = xpath.select(xpathExpression, this.xmlDoc);
|
|
288
|
-
// Handle different return types from xpath.select()
|
|
289
|
-
if (Array.isArray(nodes)) {
|
|
290
|
-
return nodes.length > 0;
|
|
291
|
-
}
|
|
292
|
-
return nodes ? true : false;
|
|
293
|
-
}
|
|
294
|
-
/**
|
|
295
|
-
* Helper method to get a number value from XPath
|
|
296
|
-
* @param xpathExpression XPath to get number from
|
|
297
|
-
* @returns Number value or NaN if not found
|
|
298
|
-
*/
|
|
299
|
-
getNumberValue(xpathExpression) {
|
|
300
|
-
if (!this.xmlDoc)
|
|
301
|
-
return NaN;
|
|
302
|
-
const node = xpath.select1(`string(${xpathExpression})`, this.xmlDoc);
|
|
303
|
-
return node ? parseFloat(node.toString()) : NaN;
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidWJsLnZhbGlkYXRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL2Zvcm1hdHMvdWJsLnZhbGlkYXRvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDcEQsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBRW5ELE9BQU8sS0FBSyxLQUFLLE1BQU0sT0FBTyxDQUFDO0FBQy9CLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxRQUFRLENBQUM7QUFFbkM7OztHQUdHO0FBQ0gsTUFBTSxPQUFPLFlBQWEsU0FBUSxhQUFhO0lBQzdDLHlCQUF5QjthQUNWLGVBQVUsR0FBRyx3REFBd0QsQUFBM0QsQ0FBNEQ7YUFDdEUsV0FBTSxHQUFHLDBFQUEwRSxBQUE3RSxDQUE4RTthQUNwRixXQUFNLEdBQUcsc0VBQXNFLEFBQXpFLENBQTBFO0lBUS9GLFlBQVksR0FBVztRQUNyQixLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7UUFQYiw4QkFBOEI7UUFDdEIsV0FBTSxHQUFvQixJQUFJLENBQUM7UUFFdkMsa0NBQWtDO1FBQzFCLG9CQUFlLEdBQVcsRUFBRSxDQUFDO1FBS25DLElBQUksQ0FBQztZQUNILHFCQUFxQjtZQUNyQixJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksU0FBUyxFQUFFLENBQUMsZUFBZSxDQUFDLEdBQUcsRUFBRSxpQkFBaUIsQ0FBQyxDQUFDO1lBRXRFLDJEQUEyRDtZQUMzRCxJQUFJLENBQUMscUJBQXFCLEVBQUUsQ0FBQztRQUMvQixDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxFQUFFLHdCQUF3QixLQUFLLEVBQUUsRUFBRSxHQUFHLENBQUMsQ0FBQztRQUNuRSxDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7O09BSUc7SUFDSSxRQUFRLENBQUMsUUFBeUIsZUFBZSxD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
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { BaseValidator } from './base.validator.js';
|
|
2
|
-
/**
|
|
3
|
-
* Factory to create the appropriate validator based on the XML format
|
|
4
|
-
*/
|
|
5
|
-
export declare class ValidatorFactory {
|
|
6
|
-
/**
|
|
7
|
-
* Creates a validator for the specified XML content
|
|
8
|
-
* @param xml XML content to validate
|
|
9
|
-
* @returns Appropriate validator instance
|
|
10
|
-
*/
|
|
11
|
-
static createValidator(xml: string): BaseValidator;
|
|
12
|
-
/**
|
|
13
|
-
* Detects the invoice format from XML content
|
|
14
|
-
* @param xml XML content to analyze
|
|
15
|
-
* @returns Detected invoice format
|
|
16
|
-
*/
|
|
17
|
-
private static detectFormat;
|
|
18
|
-
}
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { InvoiceFormat } from '../interfaces.js';
|
|
2
|
-
import { BaseValidator } from './base.validator.js';
|
|
3
|
-
import { FacturXValidator } from './facturx.validator.js';
|
|
4
|
-
import { UBLValidator } from './ubl.validator.js';
|
|
5
|
-
import { DOMParser } from 'xmldom';
|
|
6
|
-
/**
|
|
7
|
-
* Factory to create the appropriate validator based on the XML format
|
|
8
|
-
*/
|
|
9
|
-
export class ValidatorFactory {
|
|
10
|
-
/**
|
|
11
|
-
* Creates a validator for the specified XML content
|
|
12
|
-
* @param xml XML content to validate
|
|
13
|
-
* @returns Appropriate validator instance
|
|
14
|
-
*/
|
|
15
|
-
static createValidator(xml) {
|
|
16
|
-
const format = ValidatorFactory.detectFormat(xml);
|
|
17
|
-
switch (format) {
|
|
18
|
-
case InvoiceFormat.UBL:
|
|
19
|
-
case InvoiceFormat.XRECHNUNG:
|
|
20
|
-
return new UBLValidator(xml);
|
|
21
|
-
case InvoiceFormat.CII:
|
|
22
|
-
case InvoiceFormat.ZUGFERD:
|
|
23
|
-
case InvoiceFormat.FACTURX:
|
|
24
|
-
return new FacturXValidator(xml);
|
|
25
|
-
// FatturaPA and other formats would be implemented here
|
|
26
|
-
default:
|
|
27
|
-
throw new Error(`Unsupported invoice format: ${format}`);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Detects the invoice format from XML content
|
|
32
|
-
* @param xml XML content to analyze
|
|
33
|
-
* @returns Detected invoice format
|
|
34
|
-
*/
|
|
35
|
-
static detectFormat(xml) {
|
|
36
|
-
try {
|
|
37
|
-
const doc = new DOMParser().parseFromString(xml, 'application/xml');
|
|
38
|
-
const root = doc.documentElement;
|
|
39
|
-
if (!root) {
|
|
40
|
-
return InvoiceFormat.UNKNOWN;
|
|
41
|
-
}
|
|
42
|
-
// UBL detection (Invoice or CreditNote root element)
|
|
43
|
-
if (root.nodeName === 'Invoice' || root.nodeName === 'CreditNote') {
|
|
44
|
-
// Check if it's XRechnung by looking at CustomizationID
|
|
45
|
-
const customizationNodes = root.getElementsByTagName('cbc:CustomizationID');
|
|
46
|
-
if (customizationNodes.length > 0) {
|
|
47
|
-
const customizationId = customizationNodes[0].textContent || '';
|
|
48
|
-
if (customizationId.includes('xrechnung') || customizationId.includes('XRechnung')) {
|
|
49
|
-
return InvoiceFormat.XRECHNUNG;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
return InvoiceFormat.UBL;
|
|
53
|
-
}
|
|
54
|
-
// Factur-X/ZUGFeRD detection (CrossIndustryInvoice root element)
|
|
55
|
-
if (root.nodeName === 'rsm:CrossIndustryInvoice' || root.nodeName === 'CrossIndustryInvoice') {
|
|
56
|
-
// Check for profile to determine if it's Factur-X or ZUGFeRD
|
|
57
|
-
const profileNodes = root.getElementsByTagName('ram:ID');
|
|
58
|
-
for (let i = 0; i < profileNodes.length; i++) {
|
|
59
|
-
const profileText = profileNodes[i].textContent || '';
|
|
60
|
-
if (profileText.includes('factur-x') || profileText.includes('Factur-X')) {
|
|
61
|
-
return InvoiceFormat.FACTURX;
|
|
62
|
-
}
|
|
63
|
-
if (profileText.includes('zugferd') || profileText.includes('ZUGFeRD')) {
|
|
64
|
-
return InvoiceFormat.ZUGFERD;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
// If no specific profile found, default to CII
|
|
68
|
-
return InvoiceFormat.CII;
|
|
69
|
-
}
|
|
70
|
-
// FatturaPA detection would be implemented here
|
|
71
|
-
return InvoiceFormat.UNKNOWN;
|
|
72
|
-
}
|
|
73
|
-
catch (error) {
|
|
74
|
-
return InvoiceFormat.UNKNOWN;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsaWRhdG9yLmZhY3RvcnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9mb3JtYXRzL3ZhbGlkYXRvci5mYWN0b3J5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUVqRCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDcEQsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDMUQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ2xELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxRQUFRLENBQUM7QUFFbkM7O0dBRUc7QUFDSCxNQUFNLE9BQU8sZ0JBQWdCO0lBQzNCOzs7O09BSUc7SUFDSSxNQUFNLENBQUMsZUFBZSxDQUFDLEdBQVc7UUFDdkMsTUFBTSxNQUFNLEdBQUcsZ0JBQWdCLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBRWxELFFBQVEsTUFBTSxFQUFFLENBQUM7WUFDZixLQUFLLGFBQWEsQ0FBQyxHQUFHLENBQUM7WUFDdkIsS0FBSyxhQUFhLENBQUMsU0FBUztnQkFDMUIsT0FBTyxJQUFJLFlBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUUvQixLQUFLLGFBQWEsQ0FBQyxHQUFHLENBQUM7WUFDdkIsS0FBSyxhQUFhLENBQUMsT0FBTyxDQUFDO1lBQzNCLEtBQUssYUFBYSxDQUFDLE9BQU87Z0JBQ3hCLE9BQU8sSUFBSSxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUVuQyx3REFBd0Q7WUFFeEQ7Z0JBQ0UsTUFBTSxJQUFJLEtBQUssQ0FBQywrQkFBK0IsTUFBTSxFQUFFLENBQUMsQ0FBQztRQUM3RCxDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7O09BSUc7SUFDSyxNQUFNLENBQUMsWUFBWSxDQUFDLEdBQVc7UUFDckMsSUFBSSxDQUFDO1lBQ0gsTUFBTSxHQUFHLEdBQUcsSUFBSSxTQUFTLEVBQUUsQ0FBQyxlQUFlLENBQUMsR0FBRyxFQUFFLGlCQUFpQixDQUFDLENBQUM7WUFDcEUsTUFBTSxJQUFJLEdBQUcsR0FBRyxDQUFDLGVBQWUsQ0FBQztZQUVqQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7Z0JBQ1YsT0FBTyxhQUFhLENBQUMsT0FBTyxDQUFDO1lBQy9CLENBQUM7WUFFRCxxREFBcUQ7WUFDckQsSUFBSSxJQUFJLENBQUMsUUFBUSxLQUFLLFNBQVMsSUFBSSxJQUFJLENBQUMsUUFBUSxLQUFLLFlBQVksRUFBRSxDQUFDO2dCQUNsRSx3REFBd0Q7Z0JBQ3hELE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxDQUFDLG9CQUFvQixDQUFDLHFCQUFxQixDQUFDLENBQUM7Z0JBQzVFLElBQUksa0JBQWtCLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO29CQUNsQyxNQUFNLGVBQWUsR0FBRyxrQkFBa0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxXQUFXLElBQUksRUFBRSxDQUFDO29CQUNoRSxJQUFJLGVBQWUsQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLElBQUksZUFBZSxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDO3dCQUNuRixPQUFPLGFBQWEsQ0FBQyxTQUFTLENBQUM7b0JBQ2pDLENBQUM7Z0JBQ0gsQ0FBQztnQkFFRCxPQUFPLGFBQWEsQ0FBQyxHQUFHLENBQUM7WUFDM0IsQ0FBQztZQUVELGlFQUFpRTtZQUNqRSxJQUFJLElBQUksQ0FBQyxRQUFRLEtBQUssMEJBQTBCLElBQUksSUFBSSxDQUFDLFFBQVEsS0FBSyxzQkFBc0IsRUFBRSxDQUFDO2dCQUM3Riw2REFBNkQ7Z0JBQzdELE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxRQUFRLENBQUMsQ0FBQztnQkFDekQsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLFlBQVksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztvQkFDN0MsTUFBTSxXQUFXLEdBQUcsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLFdBQVcsSUFBSSxFQUFFLENBQUM7b0JBRXRELElBQUksV0FBVyxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsSUFBSSxXQUFXLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUM7d0JBQ3pFLE9BQU8sYUFBYSxDQUFDLE9BQU8sQ0FBQztvQkFDL0IsQ0FBQztvQkFFRCxJQUFJLFdBQVcsQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLElBQUksV0FBVyxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO3dCQUN2RSxPQUFPLGFBQWEsQ0FBQyxPQUFPLENBQUM7b0JBQy9CLENBQUM7Z0JBQ0gsQ0FBQztnQkFFRCwrQ0FBK0M7Z0JBQy9DLE9BQU8sYUFBYSxDQUFDLEdBQUcsQ0FBQztZQUMzQixDQUFDO1lBRUQsZ0RBQWdEO1lBRWhELE9BQU8sYUFBYSxDQUFDLE9BQU8sQ0FBQztRQUMvQixDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLE9BQU8sYUFBYSxDQUFDLE9BQU8sQ0FBQztRQUMvQixDQUFDO0lBQ0gsQ0FBQztDQUNGIn0=
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import * as plugins from '../plugins.js';
|
|
2
|
-
import { BaseDecoder } from './base.decoder.js';
|
|
3
|
-
/**
|
|
4
|
-
* A decoder specifically for XInvoice/XRechnung format.
|
|
5
|
-
* XRechnung is the German implementation of the European standard EN16931
|
|
6
|
-
* for electronic invoices to the German public sector.
|
|
7
|
-
*/
|
|
8
|
-
export declare class XInvoiceDecoder extends BaseDecoder {
|
|
9
|
-
private xmlDoc;
|
|
10
|
-
private namespaces;
|
|
11
|
-
constructor(xmlString: string);
|
|
12
|
-
/**
|
|
13
|
-
* Set up namespaces from the document
|
|
14
|
-
*/
|
|
15
|
-
private setupNamespaces;
|
|
16
|
-
/**
|
|
17
|
-
* Extract element text by tag name with namespace awareness
|
|
18
|
-
*/
|
|
19
|
-
private getElementText;
|
|
20
|
-
/**
|
|
21
|
-
* Converts XInvoice/XRechnung XML to a structured letter object
|
|
22
|
-
*/
|
|
23
|
-
getLetterData(): Promise<plugins.tsclass.business.ILetter>;
|
|
24
|
-
/**
|
|
25
|
-
* Extracts invoice items from XInvoice document
|
|
26
|
-
*/
|
|
27
|
-
private extractInvoiceItems;
|
|
28
|
-
}
|