@fin.cx/einvoice 5.0.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.d.ts +8 -0
- package/dist_ts/00_commitinfo_data.js +9 -0
- package/dist_ts/classes.decoder.d.ts +40 -0
- package/dist_ts/classes.decoder.js +320 -0
- package/dist_ts/classes.encoder.d.ts +51 -0
- package/dist_ts/classes.encoder.js +293 -0
- package/dist_ts/classes.xinvoice.d.ts +136 -0
- package/dist_ts/classes.xinvoice.js +352 -0
- package/dist_ts/einvoice.d.ts +217 -0
- package/dist_ts/einvoice.js +505 -0
- package/dist_ts/errors.d.ts +121 -0
- package/dist_ts/errors.js +241 -0
- package/dist_ts/formats/base/base.decoder.d.ts +32 -0
- package/dist_ts/formats/base/base.decoder.js +52 -0
- package/dist_ts/formats/base/base.encoder.d.ts +13 -0
- package/dist_ts/formats/base/base.encoder.js +7 -0
- package/dist_ts/formats/base/base.validator.d.ts +44 -0
- package/dist_ts/formats/base/base.validator.js +39 -0
- package/dist_ts/formats/base.decoder.d.ts +19 -0
- package/dist_ts/formats/base.decoder.js +130 -0
- package/dist_ts/formats/base.validator.d.ts +44 -0
- package/dist_ts/formats/base.validator.js +39 -0
- package/dist_ts/formats/cii/cii.decoder.d.ts +61 -0
- package/dist_ts/formats/cii/cii.decoder.js +111 -0
- package/dist_ts/formats/cii/cii.encoder.d.ts +43 -0
- package/dist_ts/formats/cii/cii.encoder.js +48 -0
- package/dist_ts/formats/cii/cii.types.d.ts +31 -0
- package/dist_ts/formats/cii/cii.types.js +40 -0
- package/dist_ts/formats/cii/cii.validator.d.ts +56 -0
- package/dist_ts/formats/cii/cii.validator.js +146 -0
- package/dist_ts/formats/cii/facturx/facturx.decoder.d.ts +43 -0
- package/dist_ts/formats/cii/facturx/facturx.decoder.js +207 -0
- package/dist_ts/formats/cii/facturx/facturx.encoder.d.ts +82 -0
- package/dist_ts/formats/cii/facturx/facturx.encoder.js +400 -0
- package/dist_ts/formats/cii/facturx/facturx.types.d.ts +10 -0
- package/dist_ts/formats/cii/facturx/facturx.types.js +15 -0
- package/dist_ts/formats/cii/facturx/facturx.validator.d.ts +32 -0
- package/dist_ts/formats/cii/facturx/facturx.validator.js +138 -0
- package/dist_ts/formats/cii/zugferd/zugferd.decoder.d.ts +43 -0
- package/dist_ts/formats/cii/zugferd/zugferd.decoder.js +218 -0
- package/dist_ts/formats/cii/zugferd/zugferd.encoder.d.ts +97 -0
- package/dist_ts/formats/cii/zugferd/zugferd.encoder.js +550 -0
- package/dist_ts/formats/cii/zugferd/zugferd.types.d.ts +10 -0
- package/dist_ts/formats/cii/zugferd/zugferd.types.js +15 -0
- package/dist_ts/formats/cii/zugferd/zugferd.v1.decoder.d.ts +49 -0
- package/dist_ts/formats/cii/zugferd/zugferd.v1.decoder.js +229 -0
- package/dist_ts/formats/cii/zugferd/zugferd.validator.d.ts +16 -0
- package/dist_ts/formats/cii/zugferd/zugferd.validator.js +29 -0
- package/dist_ts/formats/decoder.factory.d.ts +15 -0
- package/dist_ts/formats/decoder.factory.js +46 -0
- package/dist_ts/formats/factories/decoder.factory.d.ts +13 -0
- package/dist_ts/formats/factories/decoder.factory.js +56 -0
- package/dist_ts/formats/factories/encoder.factory.d.ts +14 -0
- package/dist_ts/formats/factories/encoder.factory.js +40 -0
- package/dist_ts/formats/factories/validator.factory.d.ts +12 -0
- package/dist_ts/formats/factories/validator.factory.js +110 -0
- package/dist_ts/formats/factorx.decoder.d.ts +18 -0
- package/dist_ts/formats/factorx.decoder.js +178 -0
- package/dist_ts/formats/factorx.encoder.d.ts +51 -0
- package/dist_ts/formats/factorx.encoder.js +293 -0
- package/dist_ts/formats/facturx.decoder.d.ts +18 -0
- package/dist_ts/formats/facturx.decoder.js +210 -0
- package/dist_ts/formats/facturx.encoder.d.ts +51 -0
- package/dist_ts/formats/facturx.encoder.js +293 -0
- package/dist_ts/formats/facturx.validator.d.ts +67 -0
- package/dist_ts/formats/facturx.validator.js +266 -0
- package/dist_ts/formats/pdf/extractors/associated.extractor.d.ts +14 -0
- package/dist_ts/formats/pdf/extractors/associated.extractor.js +68 -0
- package/dist_ts/formats/pdf/extractors/base.extractor.d.ts +92 -0
- package/dist_ts/formats/pdf/extractors/base.extractor.js +319 -0
- package/dist_ts/formats/pdf/extractors/index.d.ts +4 -0
- package/dist_ts/formats/pdf/extractors/index.js +5 -0
- package/dist_ts/formats/pdf/extractors/standard.extractor.d.ts +13 -0
- package/dist_ts/formats/pdf/extractors/standard.extractor.js +74 -0
- package/dist_ts/formats/pdf/extractors/text.extractor.d.ts +45 -0
- package/dist_ts/formats/pdf/extractors/text.extractor.js +151 -0
- package/dist_ts/formats/pdf/pdf.embedder.d.ts +69 -0
- package/dist_ts/formats/pdf/pdf.embedder.js +183 -0
- package/dist_ts/formats/pdf/pdf.extractor.d.ts +49 -0
- package/dist_ts/formats/pdf/pdf.extractor.js +98 -0
- package/dist_ts/formats/pdf/robust-pdf.extractor.d.ts +40 -0
- package/dist_ts/formats/pdf/robust-pdf.extractor.js +324 -0
- package/dist_ts/formats/ubl/en16931.ubl.validator.d.ts +18 -0
- package/dist_ts/formats/ubl/en16931.ubl.validator.js +169 -0
- package/dist_ts/formats/ubl/generic/ubl.encoder.d.ts +151 -0
- package/dist_ts/formats/ubl/generic/ubl.encoder.js +892 -0
- package/dist_ts/formats/ubl/ubl.decoder.d.ts +61 -0
- package/dist_ts/formats/ubl/ubl.decoder.js +95 -0
- package/dist_ts/formats/ubl/ubl.encoder.d.ts +38 -0
- package/dist_ts/formats/ubl/ubl.encoder.js +46 -0
- package/dist_ts/formats/ubl/ubl.types.d.ts +16 -0
- package/dist_ts/formats/ubl/ubl.types.js +21 -0
- package/dist_ts/formats/ubl/ubl.validator.d.ts +50 -0
- package/dist_ts/formats/ubl/ubl.validator.js +112 -0
- package/dist_ts/formats/ubl/xrechnung/xrechnung.decoder.d.ts +34 -0
- package/dist_ts/formats/ubl/xrechnung/xrechnung.decoder.js +424 -0
- package/dist_ts/formats/ubl/xrechnung/xrechnung.encoder.d.ts +75 -0
- package/dist_ts/formats/ubl/xrechnung/xrechnung.encoder.js +555 -0
- package/dist_ts/formats/ubl/xrechnung.validator.d.ts +15 -0
- package/dist_ts/formats/ubl/xrechnung.validator.js +107 -0
- package/dist_ts/formats/ubl.validator.d.ts +82 -0
- package/dist_ts/formats/ubl.validator.js +306 -0
- package/dist_ts/formats/utils/format.detector.d.ts +62 -0
- package/dist_ts/formats/utils/format.detector.js +249 -0
- package/dist_ts/formats/validation/en16931.validator.d.ts +23 -0
- package/dist_ts/formats/validation/en16931.validator.js +119 -0
- package/dist_ts/formats/validator.factory.d.ts +18 -0
- package/dist_ts/formats/validator.factory.js +78 -0
- package/dist_ts/formats/xinvoice.decoder.d.ts +28 -0
- package/dist_ts/formats/xinvoice.decoder.js +332 -0
- package/dist_ts/formats/xinvoice.encoder.d.ts +19 -0
- package/dist_ts/formats/xinvoice.encoder.js +282 -0
- package/dist_ts/index.d.ts +51 -0
- package/dist_ts/index.js +90 -0
- package/dist_ts/interfaces/common.d.ts +79 -0
- package/dist_ts/interfaces/common.js +24 -0
- package/dist_ts/interfaces.d.ts +87 -0
- package/dist_ts/interfaces.js +23 -0
- package/dist_ts/plugins.d.ts +14 -0
- package/dist_ts/plugins.js +31 -0
- package/npmextra.json +35 -0
- package/package.json +71 -0
- package/readme.hints.md +1107 -0
- package/readme.howtofixtests.md +38 -0
- package/readme.literature.md +1 -0
- package/readme.md +998 -0
- package/readme.plan.md +481 -0
- package/ts/00_commitinfo_data.ts +8 -0
- package/ts/einvoice.ts +603 -0
- package/ts/errors.ts +341 -0
- package/ts/formats/base/base.decoder.ts +68 -0
- package/ts/formats/base/base.encoder.ts +14 -0
- package/ts/formats/base/base.validator.ts +64 -0
- package/ts/formats/cii/cii.decoder.ts +139 -0
- package/ts/formats/cii/cii.encoder.ts +64 -0
- package/ts/formats/cii/cii.types.ts +44 -0
- package/ts/formats/cii/cii.validator.ts +171 -0
- package/ts/formats/cii/facturx/facturx.decoder.ts +243 -0
- package/ts/formats/cii/facturx/facturx.encoder.ts +483 -0
- package/ts/formats/cii/facturx/facturx.types.ts +18 -0
- package/ts/formats/cii/facturx/facturx.validator.ts +180 -0
- package/ts/formats/cii/zugferd/zugferd.decoder.ts +256 -0
- package/ts/formats/cii/zugferd/zugferd.encoder.ts +661 -0
- package/ts/formats/cii/zugferd/zugferd.types.ts +18 -0
- package/ts/formats/cii/zugferd/zugferd.v1.decoder.ts +267 -0
- package/ts/formats/cii/zugferd/zugferd.validator.ts +31 -0
- package/ts/formats/factories/decoder.factory.ts +62 -0
- package/ts/formats/factories/encoder.factory.ts +47 -0
- package/ts/formats/factories/validator.factory.ts +134 -0
- package/ts/formats/pdf/extractors/associated.extractor.ts +78 -0
- package/ts/formats/pdf/extractors/base.extractor.ts +355 -0
- package/ts/formats/pdf/extractors/index.ts +4 -0
- package/ts/formats/pdf/extractors/standard.extractor.ts +86 -0
- package/ts/formats/pdf/extractors/text.extractor.ts +162 -0
- package/ts/formats/pdf/pdf.embedder.ts +242 -0
- package/ts/formats/pdf/pdf.extractor.ts +141 -0
- package/ts/formats/ubl/en16931.ubl.validator.ts +216 -0
- package/ts/formats/ubl/generic/ubl.encoder.ts +1041 -0
- package/ts/formats/ubl/ubl.decoder.ts +121 -0
- package/ts/formats/ubl/ubl.encoder.ts +63 -0
- package/ts/formats/ubl/ubl.types.ts +22 -0
- package/ts/formats/ubl/ubl.validator.ts +133 -0
- package/ts/formats/ubl/xrechnung/xrechnung.decoder.ts +471 -0
- package/ts/formats/ubl/xrechnung/xrechnung.encoder.ts +619 -0
- package/ts/formats/ubl/xrechnung.validator.ts +185 -0
- package/ts/formats/utils/format.detector.ts +306 -0
- package/ts/formats/validation/en16931.validator.ts +135 -0
- package/ts/index.ts +164 -0
- package/ts/interfaces/common.ts +90 -0
- package/ts/interfaces.ts +98 -0
- package/ts/plugins.ts +61 -0
|
@@ -0,0 +1,619 @@
|
|
|
1
|
+
import { UBLEncoder } from '../generic/ubl.encoder.js';
|
|
2
|
+
import type { TInvoice, TCreditNote, TDebitNote } from '../../../interfaces/common.js';
|
|
3
|
+
import { DOMParser, XMLSerializer } from '../../../plugins.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Encoder for XRechnung (UBL) format
|
|
7
|
+
* Extends the generic UBL encoder with XRechnung-specific customizations
|
|
8
|
+
*/
|
|
9
|
+
export class XRechnungEncoder extends UBLEncoder {
|
|
10
|
+
/**
|
|
11
|
+
* Encodes a credit note into XRechnung XML
|
|
12
|
+
* @param creditNote Credit note to encode
|
|
13
|
+
* @returns XRechnung XML string
|
|
14
|
+
*/
|
|
15
|
+
protected async encodeCreditNote(creditNote: TCreditNote): Promise<string> {
|
|
16
|
+
// First get the base UBL XML
|
|
17
|
+
const baseXml = await super.encodeCreditNote(creditNote);
|
|
18
|
+
|
|
19
|
+
// Parse and modify for XRechnung
|
|
20
|
+
const doc = new DOMParser().parseFromString(baseXml, 'application/xml');
|
|
21
|
+
this.applyXRechnungCustomizations(doc, creditNote as unknown as TInvoice);
|
|
22
|
+
|
|
23
|
+
// Serialize back to string
|
|
24
|
+
return new XMLSerializer().serializeToString(doc);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Encodes a debit note (invoice) into XRechnung XML
|
|
29
|
+
* @param debitNote Debit note to encode
|
|
30
|
+
* @returns XRechnung XML string
|
|
31
|
+
*/
|
|
32
|
+
protected async encodeDebitNote(debitNote: TDebitNote): Promise<string> {
|
|
33
|
+
// First get the base UBL XML
|
|
34
|
+
const baseXml = await super.encodeDebitNote(debitNote);
|
|
35
|
+
|
|
36
|
+
// Parse and modify for XRechnung
|
|
37
|
+
const doc = new DOMParser().parseFromString(baseXml, 'application/xml');
|
|
38
|
+
this.applyXRechnungCustomizations(doc, debitNote as unknown as TInvoice);
|
|
39
|
+
|
|
40
|
+
// Serialize back to string
|
|
41
|
+
return new XMLSerializer().serializeToString(doc);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Applies XRechnung-specific customizations to the document
|
|
46
|
+
* @param doc XML document
|
|
47
|
+
* @param invoice Invoice data
|
|
48
|
+
*/
|
|
49
|
+
private applyXRechnungCustomizations(doc: Document, invoice: TInvoice): void {
|
|
50
|
+
const root = doc.documentElement;
|
|
51
|
+
|
|
52
|
+
// Extract metadata if available
|
|
53
|
+
const metadata = (invoice as any).metadata?.extensions;
|
|
54
|
+
|
|
55
|
+
// Update Customization ID to XRechnung 2.0
|
|
56
|
+
const customizationId = root.getElementsByTagName('cbc:CustomizationID')[0];
|
|
57
|
+
if (customizationId) {
|
|
58
|
+
customizationId.textContent = 'urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.0';
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Add or update Buyer Reference (required for XRechnung)
|
|
62
|
+
let buyerRef = root.getElementsByTagName('cbc:BuyerReference')[0];
|
|
63
|
+
const buyerReferenceValue = (invoice as any).buyerReference || metadata?.businessReferences?.buyerReference || invoice.id;
|
|
64
|
+
if (!buyerRef) {
|
|
65
|
+
// Find where to insert it (after DocumentCurrencyCode)
|
|
66
|
+
const currencyCode = root.getElementsByTagName('cbc:DocumentCurrencyCode')[0];
|
|
67
|
+
if (currencyCode) {
|
|
68
|
+
buyerRef = doc.createElement('cbc:BuyerReference');
|
|
69
|
+
buyerRef.textContent = buyerReferenceValue;
|
|
70
|
+
currencyCode.parentNode!.insertBefore(buyerRef, currencyCode.nextSibling);
|
|
71
|
+
}
|
|
72
|
+
} else if (!buyerRef.textContent || buyerRef.textContent.trim() === '') {
|
|
73
|
+
buyerRef.textContent = buyerReferenceValue;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Update payment terms to German
|
|
77
|
+
const paymentTermsNotes = root.getElementsByTagName('cac:PaymentTerms');
|
|
78
|
+
if (paymentTermsNotes.length > 0) {
|
|
79
|
+
const noteElement = paymentTermsNotes[0].getElementsByTagName('cbc:Note')[0];
|
|
80
|
+
if (noteElement && noteElement.textContent) {
|
|
81
|
+
noteElement.textContent = `Zahlung innerhalb von ${invoice.dueInDays || 30} Tagen`;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Add electronic address for parties if available
|
|
86
|
+
this.addElectronicAddressToParty(doc, 'cac:AccountingSupplierParty', invoice.from);
|
|
87
|
+
this.addElectronicAddressToParty(doc, 'cac:AccountingCustomerParty', invoice.to);
|
|
88
|
+
|
|
89
|
+
// Ensure payment reference is set
|
|
90
|
+
const paymentMeans = root.getElementsByTagName('cac:PaymentMeans')[0];
|
|
91
|
+
if (paymentMeans) {
|
|
92
|
+
let paymentId = paymentMeans.getElementsByTagName('cbc:PaymentID')[0];
|
|
93
|
+
if (!paymentId) {
|
|
94
|
+
paymentId = doc.createElement('cbc:PaymentID');
|
|
95
|
+
paymentId.textContent = invoice.id;
|
|
96
|
+
paymentMeans.appendChild(paymentId);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Add country code handling for German addresses
|
|
101
|
+
this.fixGermanCountryCodes(doc);
|
|
102
|
+
|
|
103
|
+
// Preserve business references from metadata
|
|
104
|
+
this.addBusinessReferences(doc, metadata?.businessReferences);
|
|
105
|
+
|
|
106
|
+
// Preserve payment information from metadata
|
|
107
|
+
this.enhancePaymentInformation(doc, metadata?.paymentInformation);
|
|
108
|
+
|
|
109
|
+
// Preserve date information from metadata
|
|
110
|
+
this.addDateInformation(doc, metadata?.dateInformation);
|
|
111
|
+
|
|
112
|
+
// Enhance party information with contact details
|
|
113
|
+
this.enhancePartyInformation(doc, invoice);
|
|
114
|
+
|
|
115
|
+
// Enhance line items with metadata
|
|
116
|
+
this.enhanceLineItems(doc, invoice);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Adds electronic address to party if not already present
|
|
121
|
+
* @param doc XML document
|
|
122
|
+
* @param partyType Party type selector
|
|
123
|
+
* @param party Party data
|
|
124
|
+
*/
|
|
125
|
+
private addElectronicAddressToParty(doc: Document, partyType: string, party: any): void {
|
|
126
|
+
const partyContainer = doc.getElementsByTagName(partyType)[0];
|
|
127
|
+
if (!partyContainer) return;
|
|
128
|
+
|
|
129
|
+
const partyElement = partyContainer.getElementsByTagName('cac:Party')[0];
|
|
130
|
+
if (!partyElement) return;
|
|
131
|
+
|
|
132
|
+
// Check if electronic address already exists
|
|
133
|
+
const existingEndpoint = partyElement.getElementsByTagName('cbc:EndpointID')[0];
|
|
134
|
+
if (!existingEndpoint && party.electronicAddress) {
|
|
135
|
+
// Add electronic address at the beginning of party element
|
|
136
|
+
const endpointNode = doc.createElement('cbc:EndpointID');
|
|
137
|
+
endpointNode.setAttribute('schemeID', party.electronicAddress.scheme || '0204');
|
|
138
|
+
endpointNode.textContent = party.electronicAddress.value;
|
|
139
|
+
|
|
140
|
+
// Insert as first child of party element
|
|
141
|
+
if (partyElement.firstChild) {
|
|
142
|
+
partyElement.insertBefore(endpointNode, partyElement.firstChild);
|
|
143
|
+
} else {
|
|
144
|
+
partyElement.appendChild(endpointNode);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Add GLN (Global Location Number) if available
|
|
149
|
+
if (party.gln && !existingEndpoint) {
|
|
150
|
+
const endpointNode = doc.createElement('cbc:EndpointID');
|
|
151
|
+
endpointNode.setAttribute('schemeID', '0088'); // GLN scheme ID
|
|
152
|
+
endpointNode.textContent = party.gln;
|
|
153
|
+
|
|
154
|
+
// Insert as first child of party element
|
|
155
|
+
if (partyElement.firstChild) {
|
|
156
|
+
partyElement.insertBefore(endpointNode, partyElement.firstChild);
|
|
157
|
+
} else {
|
|
158
|
+
partyElement.appendChild(endpointNode);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Add PartyIdentification for additional identifiers
|
|
163
|
+
if (party.additionalIdentifiers) {
|
|
164
|
+
for (const identifier of party.additionalIdentifiers) {
|
|
165
|
+
const partyId = doc.createElement('cac:PartyIdentification');
|
|
166
|
+
const id = doc.createElement('cbc:ID');
|
|
167
|
+
if (identifier.scheme) {
|
|
168
|
+
id.setAttribute('schemeID', identifier.scheme);
|
|
169
|
+
}
|
|
170
|
+
id.textContent = identifier.value;
|
|
171
|
+
partyId.appendChild(id);
|
|
172
|
+
|
|
173
|
+
// Insert after EndpointID or at beginning
|
|
174
|
+
const endpoint = partyElement.getElementsByTagName('cbc:EndpointID')[0];
|
|
175
|
+
if (endpoint && endpoint.nextSibling) {
|
|
176
|
+
partyElement.insertBefore(partyId, endpoint.nextSibling);
|
|
177
|
+
} else if (partyElement.firstChild) {
|
|
178
|
+
partyElement.insertBefore(partyId, partyElement.firstChild);
|
|
179
|
+
} else {
|
|
180
|
+
partyElement.appendChild(partyId);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Add company registration number to PartyLegalEntity
|
|
186
|
+
if (party.registrationDetails?.registrationId) {
|
|
187
|
+
let legalEntity = partyElement.getElementsByTagName('cac:PartyLegalEntity')[0];
|
|
188
|
+
if (!legalEntity) {
|
|
189
|
+
legalEntity = doc.createElement('cac:PartyLegalEntity');
|
|
190
|
+
// Insert after PostalAddress
|
|
191
|
+
const postalAddress = partyElement.getElementsByTagName('cac:PostalAddress')[0];
|
|
192
|
+
if (postalAddress && postalAddress.nextSibling) {
|
|
193
|
+
partyElement.insertBefore(legalEntity, postalAddress.nextSibling);
|
|
194
|
+
} else {
|
|
195
|
+
partyElement.appendChild(legalEntity);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Add registration name if not present
|
|
200
|
+
if (!legalEntity.getElementsByTagName('cbc:RegistrationName')[0]) {
|
|
201
|
+
const regName = doc.createElement('cbc:RegistrationName');
|
|
202
|
+
regName.textContent = party.registrationDetails.registrationName || party.name;
|
|
203
|
+
legalEntity.appendChild(regName);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Add company ID if not present
|
|
207
|
+
if (!legalEntity.getElementsByTagName('cbc:CompanyID')[0]) {
|
|
208
|
+
const companyId = doc.createElement('cbc:CompanyID');
|
|
209
|
+
companyId.textContent = party.registrationDetails.registrationId;
|
|
210
|
+
legalEntity.appendChild(companyId);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Fixes German country codes in the document
|
|
217
|
+
* @param doc XML document
|
|
218
|
+
*/
|
|
219
|
+
private fixGermanCountryCodes(doc: Document): void {
|
|
220
|
+
const countryNodes = doc.getElementsByTagName('cbc:IdentificationCode');
|
|
221
|
+
for (let i = 0; i < countryNodes.length; i++) {
|
|
222
|
+
const node = countryNodes[i];
|
|
223
|
+
if (node.textContent) {
|
|
224
|
+
const text = node.textContent.toLowerCase();
|
|
225
|
+
if (text === 'germany' || text === 'deutschland' || text === 'de') {
|
|
226
|
+
node.textContent = 'DE';
|
|
227
|
+
} else if (text.length > 2) {
|
|
228
|
+
// Try to use first 2 characters as country code
|
|
229
|
+
node.textContent = text.substring(0, 2).toUpperCase();
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Adds business references from metadata to the document
|
|
237
|
+
* @param doc XML document
|
|
238
|
+
* @param businessReferences Business references from metadata
|
|
239
|
+
*/
|
|
240
|
+
private addBusinessReferences(doc: Document, businessReferences?: any): void {
|
|
241
|
+
if (!businessReferences) return;
|
|
242
|
+
|
|
243
|
+
const root = doc.documentElement;
|
|
244
|
+
|
|
245
|
+
// Add OrderReference
|
|
246
|
+
if (businessReferences.orderReference && !root.getElementsByTagName('cac:OrderReference')[0]) {
|
|
247
|
+
const orderRef = doc.createElement('cac:OrderReference');
|
|
248
|
+
const orderId = doc.createElement('cbc:ID');
|
|
249
|
+
orderId.textContent = businessReferences.orderReference;
|
|
250
|
+
orderRef.appendChild(orderId);
|
|
251
|
+
|
|
252
|
+
// Insert after DocumentCurrencyCode
|
|
253
|
+
const currencyCode = root.getElementsByTagName('cbc:DocumentCurrencyCode')[0];
|
|
254
|
+
if (currencyCode && currencyCode.parentNode) {
|
|
255
|
+
currencyCode.parentNode.insertBefore(orderRef, currencyCode.nextSibling);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// Add ContractDocumentReference
|
|
260
|
+
if (businessReferences.contractReference && !root.getElementsByTagName('cac:ContractDocumentReference')[0]) {
|
|
261
|
+
const contractRef = doc.createElement('cac:ContractDocumentReference');
|
|
262
|
+
const contractId = doc.createElement('cbc:ID');
|
|
263
|
+
contractId.textContent = businessReferences.contractReference;
|
|
264
|
+
contractRef.appendChild(contractId);
|
|
265
|
+
|
|
266
|
+
// Insert after OrderReference or DocumentCurrencyCode
|
|
267
|
+
const orderRef = root.getElementsByTagName('cac:OrderReference')[0];
|
|
268
|
+
const insertAfter = orderRef || root.getElementsByTagName('cbc:DocumentCurrencyCode')[0];
|
|
269
|
+
if (insertAfter && insertAfter.parentNode) {
|
|
270
|
+
insertAfter.parentNode.insertBefore(contractRef, insertAfter.nextSibling);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// Add ProjectReference
|
|
275
|
+
if (businessReferences.projectReference && !root.getElementsByTagName('cac:ProjectReference')[0]) {
|
|
276
|
+
const projectRef = doc.createElement('cac:ProjectReference');
|
|
277
|
+
const projectId = doc.createElement('cbc:ID');
|
|
278
|
+
projectId.textContent = businessReferences.projectReference;
|
|
279
|
+
projectRef.appendChild(projectId);
|
|
280
|
+
|
|
281
|
+
// Insert after ContractDocumentReference or other refs
|
|
282
|
+
const contractRef = root.getElementsByTagName('cac:ContractDocumentReference')[0];
|
|
283
|
+
const orderRef = root.getElementsByTagName('cac:OrderReference')[0];
|
|
284
|
+
const insertAfter = contractRef || orderRef || root.getElementsByTagName('cbc:DocumentCurrencyCode')[0];
|
|
285
|
+
if (insertAfter && insertAfter.parentNode) {
|
|
286
|
+
insertAfter.parentNode.insertBefore(projectRef, insertAfter.nextSibling);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Enhances payment information from metadata
|
|
293
|
+
* @param doc XML document
|
|
294
|
+
* @param paymentInfo Payment information from metadata
|
|
295
|
+
*/
|
|
296
|
+
private enhancePaymentInformation(doc: Document, paymentInfo?: any): void {
|
|
297
|
+
if (!paymentInfo) return;
|
|
298
|
+
|
|
299
|
+
const root = doc.documentElement;
|
|
300
|
+
let paymentMeans = root.getElementsByTagName('cac:PaymentMeans')[0];
|
|
301
|
+
|
|
302
|
+
// Create PaymentMeans if it doesn't exist
|
|
303
|
+
if (!paymentMeans) {
|
|
304
|
+
paymentMeans = doc.createElement('cac:PaymentMeans');
|
|
305
|
+
// Insert before TaxTotal
|
|
306
|
+
const taxTotal = root.getElementsByTagName('cac:TaxTotal')[0];
|
|
307
|
+
if (taxTotal && taxTotal.parentNode) {
|
|
308
|
+
taxTotal.parentNode.insertBefore(paymentMeans, taxTotal);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// Add PaymentMeansCode
|
|
313
|
+
if (paymentInfo.paymentMeansCode && !paymentMeans.getElementsByTagName('cbc:PaymentMeansCode')[0]) {
|
|
314
|
+
const meansCode = doc.createElement('cbc:PaymentMeansCode');
|
|
315
|
+
meansCode.textContent = paymentInfo.paymentMeansCode;
|
|
316
|
+
paymentMeans.appendChild(meansCode);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// Add PaymentID
|
|
320
|
+
if (paymentInfo.paymentID && !paymentMeans.getElementsByTagName('cbc:PaymentID')[0]) {
|
|
321
|
+
const paymentId = doc.createElement('cbc:PaymentID');
|
|
322
|
+
paymentId.textContent = paymentInfo.paymentID;
|
|
323
|
+
paymentMeans.appendChild(paymentId);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// Add PaymentDueDate
|
|
327
|
+
if (paymentInfo.paymentDueDate && !paymentMeans.getElementsByTagName('cbc:PaymentDueDate')[0]) {
|
|
328
|
+
const dueDate = doc.createElement('cbc:PaymentDueDate');
|
|
329
|
+
dueDate.textContent = paymentInfo.paymentDueDate;
|
|
330
|
+
paymentMeans.appendChild(dueDate);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// Add IBAN and BIC
|
|
334
|
+
if (paymentInfo.iban || paymentInfo.bic) {
|
|
335
|
+
let payeeAccount = paymentMeans.getElementsByTagName('cac:PayeeFinancialAccount')[0];
|
|
336
|
+
if (!payeeAccount) {
|
|
337
|
+
payeeAccount = doc.createElement('cac:PayeeFinancialAccount');
|
|
338
|
+
paymentMeans.appendChild(payeeAccount);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// Add IBAN
|
|
342
|
+
if (paymentInfo.iban && !payeeAccount.getElementsByTagName('cbc:ID')[0]) {
|
|
343
|
+
const iban = doc.createElement('cbc:ID');
|
|
344
|
+
iban.textContent = paymentInfo.iban;
|
|
345
|
+
payeeAccount.appendChild(iban);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// Add account name (must come after ID but before FinancialInstitutionBranch)
|
|
349
|
+
if (paymentInfo.accountName && !payeeAccount.getElementsByTagName('cbc:Name')[0]) {
|
|
350
|
+
const accountName = doc.createElement('cbc:Name');
|
|
351
|
+
accountName.textContent = paymentInfo.accountName;
|
|
352
|
+
// Insert after ID but before FinancialInstitutionBranch
|
|
353
|
+
const id = payeeAccount.getElementsByTagName('cbc:ID')[0];
|
|
354
|
+
const finInstBranch = payeeAccount.getElementsByTagName('cac:FinancialInstitutionBranch')[0];
|
|
355
|
+
if (finInstBranch) {
|
|
356
|
+
payeeAccount.insertBefore(accountName, finInstBranch);
|
|
357
|
+
} else if (id && id.nextSibling) {
|
|
358
|
+
payeeAccount.insertBefore(accountName, id.nextSibling);
|
|
359
|
+
} else {
|
|
360
|
+
payeeAccount.appendChild(accountName);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// Add BIC and bank name
|
|
365
|
+
if (paymentInfo.bic || paymentInfo.bankName) {
|
|
366
|
+
let finInstBranch = payeeAccount.getElementsByTagName('cac:FinancialInstitutionBranch')[0];
|
|
367
|
+
if (!finInstBranch) {
|
|
368
|
+
finInstBranch = doc.createElement('cac:FinancialInstitutionBranch');
|
|
369
|
+
payeeAccount.appendChild(finInstBranch);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// Add BIC as branch ID
|
|
373
|
+
if (paymentInfo.bic && !finInstBranch.getElementsByTagName('cbc:ID')[0]) {
|
|
374
|
+
const bicElement = doc.createElement('cbc:ID');
|
|
375
|
+
bicElement.textContent = paymentInfo.bic;
|
|
376
|
+
finInstBranch.appendChild(bicElement);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// Add bank name
|
|
380
|
+
if (paymentInfo.bankName && !finInstBranch.getElementsByTagName('cbc:Name')[0]) {
|
|
381
|
+
const bankNameElement = doc.createElement('cbc:Name');
|
|
382
|
+
bankNameElement.textContent = paymentInfo.bankName;
|
|
383
|
+
finInstBranch.appendChild(bankNameElement);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// Add payment terms with discount if available
|
|
389
|
+
if (paymentInfo.paymentTermsNote && paymentInfo.paymentTermsNote.includes('early payment')) {
|
|
390
|
+
let paymentTerms = root.getElementsByTagName('cac:PaymentTerms')[0];
|
|
391
|
+
if (!paymentTerms) {
|
|
392
|
+
paymentTerms = doc.createElement('cac:PaymentTerms');
|
|
393
|
+
// Insert before PaymentMeans
|
|
394
|
+
const paymentMeans = root.getElementsByTagName('cac:PaymentMeans')[0];
|
|
395
|
+
if (paymentMeans && paymentMeans.parentNode) {
|
|
396
|
+
paymentMeans.parentNode.insertBefore(paymentTerms, paymentMeans);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// Update or add note
|
|
401
|
+
let note = paymentTerms.getElementsByTagName('cbc:Note')[0];
|
|
402
|
+
if (!note) {
|
|
403
|
+
note = doc.createElement('cbc:Note');
|
|
404
|
+
paymentTerms.appendChild(note);
|
|
405
|
+
}
|
|
406
|
+
note.textContent = paymentInfo.paymentTermsNote;
|
|
407
|
+
|
|
408
|
+
// Add discount percent if available
|
|
409
|
+
if (paymentInfo.discountPercent && !paymentTerms.getElementsByTagName('cbc:SettlementDiscountPercent')[0]) {
|
|
410
|
+
const discountElement = doc.createElement('cbc:SettlementDiscountPercent');
|
|
411
|
+
discountElement.textContent = paymentInfo.discountPercent;
|
|
412
|
+
paymentTerms.appendChild(discountElement);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Adds date information from metadata
|
|
419
|
+
* @param doc XML document
|
|
420
|
+
* @param dateInfo Date information from metadata
|
|
421
|
+
*/
|
|
422
|
+
private addDateInformation(doc: Document, dateInfo?: any): void {
|
|
423
|
+
if (!dateInfo) return;
|
|
424
|
+
|
|
425
|
+
const root = doc.documentElement;
|
|
426
|
+
|
|
427
|
+
// Add InvoicePeriod
|
|
428
|
+
if ((dateInfo.periodStart || dateInfo.periodEnd) && !root.getElementsByTagName('cac:InvoicePeriod')[0]) {
|
|
429
|
+
const invoicePeriod = doc.createElement('cac:InvoicePeriod');
|
|
430
|
+
|
|
431
|
+
if (dateInfo.periodStart) {
|
|
432
|
+
const startDate = doc.createElement('cbc:StartDate');
|
|
433
|
+
startDate.textContent = dateInfo.periodStart;
|
|
434
|
+
invoicePeriod.appendChild(startDate);
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
if (dateInfo.periodEnd) {
|
|
438
|
+
const endDate = doc.createElement('cbc:EndDate');
|
|
439
|
+
endDate.textContent = dateInfo.periodEnd;
|
|
440
|
+
invoicePeriod.appendChild(endDate);
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
// Insert after business references or DocumentCurrencyCode
|
|
444
|
+
const projectRef = root.getElementsByTagName('cac:ProjectReference')[0];
|
|
445
|
+
const contractRef = root.getElementsByTagName('cac:ContractDocumentReference')[0];
|
|
446
|
+
const orderRef = root.getElementsByTagName('cac:OrderReference')[0];
|
|
447
|
+
const insertAfter = projectRef || contractRef || orderRef || root.getElementsByTagName('cbc:DocumentCurrencyCode')[0];
|
|
448
|
+
if (insertAfter && insertAfter.parentNode) {
|
|
449
|
+
insertAfter.parentNode.insertBefore(invoicePeriod, insertAfter.nextSibling);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
// Add Delivery with ActualDeliveryDate
|
|
454
|
+
if (dateInfo.deliveryDate && !root.getElementsByTagName('cac:Delivery')[0]) {
|
|
455
|
+
const delivery = doc.createElement('cac:Delivery');
|
|
456
|
+
const deliveryDate = doc.createElement('cbc:ActualDeliveryDate');
|
|
457
|
+
deliveryDate.textContent = dateInfo.deliveryDate;
|
|
458
|
+
delivery.appendChild(deliveryDate);
|
|
459
|
+
|
|
460
|
+
// Insert before PaymentMeans
|
|
461
|
+
const paymentMeans = root.getElementsByTagName('cac:PaymentMeans')[0];
|
|
462
|
+
if (paymentMeans && paymentMeans.parentNode) {
|
|
463
|
+
paymentMeans.parentNode.insertBefore(delivery, paymentMeans);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* Enhances party information with contact details from metadata
|
|
470
|
+
* @param doc XML document
|
|
471
|
+
* @param invoice Invoice data
|
|
472
|
+
*/
|
|
473
|
+
private enhancePartyInformation(doc: Document, invoice: TInvoice): void {
|
|
474
|
+
// Enhance supplier party
|
|
475
|
+
this.addContactToParty(doc, 'cac:AccountingSupplierParty', (invoice.from as any)?.metadata?.contactInformation);
|
|
476
|
+
|
|
477
|
+
// Enhance customer party
|
|
478
|
+
this.addContactToParty(doc, 'cac:AccountingCustomerParty', (invoice.to as any)?.metadata?.contactInformation);
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* Adds contact information to a party
|
|
483
|
+
* @param doc XML document
|
|
484
|
+
* @param partySelector Party selector
|
|
485
|
+
* @param contactInfo Contact information from metadata
|
|
486
|
+
*/
|
|
487
|
+
private addContactToParty(doc: Document, partySelector: string, contactInfo?: any): void {
|
|
488
|
+
if (!contactInfo) return;
|
|
489
|
+
|
|
490
|
+
const partyContainer = doc.getElementsByTagName(partySelector)[0];
|
|
491
|
+
if (!partyContainer) return;
|
|
492
|
+
|
|
493
|
+
const party = partyContainer.getElementsByTagName('cac:Party')[0];
|
|
494
|
+
if (!party) return;
|
|
495
|
+
|
|
496
|
+
// Check if Contact already exists
|
|
497
|
+
let contact = party.getElementsByTagName('cac:Contact')[0];
|
|
498
|
+
if (!contact && (contactInfo.name || contactInfo.phone || contactInfo.email)) {
|
|
499
|
+
contact = doc.createElement('cac:Contact');
|
|
500
|
+
|
|
501
|
+
// Insert after PartyName
|
|
502
|
+
const partyName = party.getElementsByTagName('cac:PartyName')[0];
|
|
503
|
+
if (partyName && partyName.parentNode) {
|
|
504
|
+
partyName.parentNode.insertBefore(contact, partyName.nextSibling);
|
|
505
|
+
} else {
|
|
506
|
+
party.appendChild(contact);
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
if (contact) {
|
|
511
|
+
// Add contact name
|
|
512
|
+
if (contactInfo.name && !contact.getElementsByTagName('cbc:Name')[0]) {
|
|
513
|
+
const name = doc.createElement('cbc:Name');
|
|
514
|
+
name.textContent = contactInfo.name;
|
|
515
|
+
contact.appendChild(name);
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
// Add telephone
|
|
519
|
+
if (contactInfo.phone && !contact.getElementsByTagName('cbc:Telephone')[0]) {
|
|
520
|
+
const phone = doc.createElement('cbc:Telephone');
|
|
521
|
+
phone.textContent = contactInfo.phone;
|
|
522
|
+
contact.appendChild(phone);
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
// Add email
|
|
526
|
+
if (contactInfo.email && !contact.getElementsByTagName('cbc:ElectronicMail')[0]) {
|
|
527
|
+
const email = doc.createElement('cbc:ElectronicMail');
|
|
528
|
+
email.textContent = contactInfo.email;
|
|
529
|
+
contact.appendChild(email);
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
/**
|
|
535
|
+
* Enhances line items with metadata
|
|
536
|
+
* @param doc XML document
|
|
537
|
+
* @param invoice Invoice data
|
|
538
|
+
*/
|
|
539
|
+
private enhanceLineItems(doc: Document, invoice: TInvoice): void {
|
|
540
|
+
const invoiceLines = doc.getElementsByTagName('cac:InvoiceLine');
|
|
541
|
+
|
|
542
|
+
for (let i = 0; i < invoiceLines.length && i < invoice.items.length; i++) {
|
|
543
|
+
const line = invoiceLines[i];
|
|
544
|
+
const item = invoice.items[i];
|
|
545
|
+
const itemMetadata = (item as any).metadata;
|
|
546
|
+
|
|
547
|
+
if (!itemMetadata) continue;
|
|
548
|
+
|
|
549
|
+
const itemElement = line.getElementsByTagName('cac:Item')[0];
|
|
550
|
+
if (!itemElement) continue;
|
|
551
|
+
|
|
552
|
+
// Add item description
|
|
553
|
+
if (itemMetadata.description && !itemElement.getElementsByTagName('cbc:Description')[0]) {
|
|
554
|
+
const desc = doc.createElement('cbc:Description');
|
|
555
|
+
desc.textContent = itemMetadata.description;
|
|
556
|
+
// Insert before Name
|
|
557
|
+
const name = itemElement.getElementsByTagName('cbc:Name')[0];
|
|
558
|
+
if (name && name.parentNode) {
|
|
559
|
+
name.parentNode.insertBefore(desc, name);
|
|
560
|
+
} else {
|
|
561
|
+
itemElement.appendChild(desc);
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
// Add SellersItemIdentification
|
|
566
|
+
if (itemMetadata.buyerItemID && !itemElement.getElementsByTagName('cac:SellersItemIdentification')[0]) {
|
|
567
|
+
const sellerId = doc.createElement('cac:SellersItemIdentification');
|
|
568
|
+
const id = doc.createElement('cbc:ID');
|
|
569
|
+
id.textContent = item.articleNumber || itemMetadata.buyerItemID;
|
|
570
|
+
sellerId.appendChild(id);
|
|
571
|
+
itemElement.appendChild(sellerId);
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
// Add BuyersItemIdentification
|
|
575
|
+
if (itemMetadata.buyerItemID && !itemElement.getElementsByTagName('cac:BuyersItemIdentification')[0]) {
|
|
576
|
+
const buyerId = doc.createElement('cac:BuyersItemIdentification');
|
|
577
|
+
const id = doc.createElement('cbc:ID');
|
|
578
|
+
id.textContent = itemMetadata.buyerItemID;
|
|
579
|
+
buyerId.appendChild(id);
|
|
580
|
+
itemElement.appendChild(buyerId);
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
// Add StandardItemIdentification
|
|
584
|
+
if (itemMetadata.standardItemID && !itemElement.getElementsByTagName('cac:StandardItemIdentification')[0]) {
|
|
585
|
+
const standardId = doc.createElement('cac:StandardItemIdentification');
|
|
586
|
+
const id = doc.createElement('cbc:ID');
|
|
587
|
+
id.textContent = itemMetadata.standardItemID;
|
|
588
|
+
standardId.appendChild(id);
|
|
589
|
+
itemElement.appendChild(standardId);
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
// Add CommodityClassification
|
|
593
|
+
if (itemMetadata.commodityClassification && !itemElement.getElementsByTagName('cac:CommodityClassification')[0]) {
|
|
594
|
+
const classification = doc.createElement('cac:CommodityClassification');
|
|
595
|
+
const code = doc.createElement('cbc:ItemClassificationCode');
|
|
596
|
+
code.textContent = itemMetadata.commodityClassification;
|
|
597
|
+
classification.appendChild(code);
|
|
598
|
+
itemElement.appendChild(classification);
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
// Add additional item properties
|
|
602
|
+
if (itemMetadata.additionalProperties) {
|
|
603
|
+
for (const [propName, propValue] of Object.entries(itemMetadata.additionalProperties)) {
|
|
604
|
+
const additionalProp = doc.createElement('cac:AdditionalItemProperty');
|
|
605
|
+
|
|
606
|
+
const nameElement = doc.createElement('cbc:Name');
|
|
607
|
+
nameElement.textContent = propName;
|
|
608
|
+
additionalProp.appendChild(nameElement);
|
|
609
|
+
|
|
610
|
+
const valueElement = doc.createElement('cbc:Value');
|
|
611
|
+
valueElement.textContent = propValue as string;
|
|
612
|
+
additionalProp.appendChild(valueElement);
|
|
613
|
+
|
|
614
|
+
itemElement.appendChild(additionalProp);
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
}
|