@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.
Files changed (171) hide show
  1. package/dist_ts/00_commitinfo_data.d.ts +8 -0
  2. package/dist_ts/00_commitinfo_data.js +9 -0
  3. package/dist_ts/classes.decoder.d.ts +40 -0
  4. package/dist_ts/classes.decoder.js +320 -0
  5. package/dist_ts/classes.encoder.d.ts +51 -0
  6. package/dist_ts/classes.encoder.js +293 -0
  7. package/dist_ts/classes.xinvoice.d.ts +136 -0
  8. package/dist_ts/classes.xinvoice.js +352 -0
  9. package/dist_ts/einvoice.d.ts +217 -0
  10. package/dist_ts/einvoice.js +505 -0
  11. package/dist_ts/errors.d.ts +121 -0
  12. package/dist_ts/errors.js +241 -0
  13. package/dist_ts/formats/base/base.decoder.d.ts +32 -0
  14. package/dist_ts/formats/base/base.decoder.js +52 -0
  15. package/dist_ts/formats/base/base.encoder.d.ts +13 -0
  16. package/dist_ts/formats/base/base.encoder.js +7 -0
  17. package/dist_ts/formats/base/base.validator.d.ts +44 -0
  18. package/dist_ts/formats/base/base.validator.js +39 -0
  19. package/dist_ts/formats/base.decoder.d.ts +19 -0
  20. package/dist_ts/formats/base.decoder.js +130 -0
  21. package/dist_ts/formats/base.validator.d.ts +44 -0
  22. package/dist_ts/formats/base.validator.js +39 -0
  23. package/dist_ts/formats/cii/cii.decoder.d.ts +61 -0
  24. package/dist_ts/formats/cii/cii.decoder.js +111 -0
  25. package/dist_ts/formats/cii/cii.encoder.d.ts +43 -0
  26. package/dist_ts/formats/cii/cii.encoder.js +48 -0
  27. package/dist_ts/formats/cii/cii.types.d.ts +31 -0
  28. package/dist_ts/formats/cii/cii.types.js +40 -0
  29. package/dist_ts/formats/cii/cii.validator.d.ts +56 -0
  30. package/dist_ts/formats/cii/cii.validator.js +146 -0
  31. package/dist_ts/formats/cii/facturx/facturx.decoder.d.ts +43 -0
  32. package/dist_ts/formats/cii/facturx/facturx.decoder.js +207 -0
  33. package/dist_ts/formats/cii/facturx/facturx.encoder.d.ts +82 -0
  34. package/dist_ts/formats/cii/facturx/facturx.encoder.js +400 -0
  35. package/dist_ts/formats/cii/facturx/facturx.types.d.ts +10 -0
  36. package/dist_ts/formats/cii/facturx/facturx.types.js +15 -0
  37. package/dist_ts/formats/cii/facturx/facturx.validator.d.ts +32 -0
  38. package/dist_ts/formats/cii/facturx/facturx.validator.js +138 -0
  39. package/dist_ts/formats/cii/zugferd/zugferd.decoder.d.ts +43 -0
  40. package/dist_ts/formats/cii/zugferd/zugferd.decoder.js +218 -0
  41. package/dist_ts/formats/cii/zugferd/zugferd.encoder.d.ts +97 -0
  42. package/dist_ts/formats/cii/zugferd/zugferd.encoder.js +550 -0
  43. package/dist_ts/formats/cii/zugferd/zugferd.types.d.ts +10 -0
  44. package/dist_ts/formats/cii/zugferd/zugferd.types.js +15 -0
  45. package/dist_ts/formats/cii/zugferd/zugferd.v1.decoder.d.ts +49 -0
  46. package/dist_ts/formats/cii/zugferd/zugferd.v1.decoder.js +229 -0
  47. package/dist_ts/formats/cii/zugferd/zugferd.validator.d.ts +16 -0
  48. package/dist_ts/formats/cii/zugferd/zugferd.validator.js +29 -0
  49. package/dist_ts/formats/decoder.factory.d.ts +15 -0
  50. package/dist_ts/formats/decoder.factory.js +46 -0
  51. package/dist_ts/formats/factories/decoder.factory.d.ts +13 -0
  52. package/dist_ts/formats/factories/decoder.factory.js +56 -0
  53. package/dist_ts/formats/factories/encoder.factory.d.ts +14 -0
  54. package/dist_ts/formats/factories/encoder.factory.js +40 -0
  55. package/dist_ts/formats/factories/validator.factory.d.ts +12 -0
  56. package/dist_ts/formats/factories/validator.factory.js +110 -0
  57. package/dist_ts/formats/factorx.decoder.d.ts +18 -0
  58. package/dist_ts/formats/factorx.decoder.js +178 -0
  59. package/dist_ts/formats/factorx.encoder.d.ts +51 -0
  60. package/dist_ts/formats/factorx.encoder.js +293 -0
  61. package/dist_ts/formats/facturx.decoder.d.ts +18 -0
  62. package/dist_ts/formats/facturx.decoder.js +210 -0
  63. package/dist_ts/formats/facturx.encoder.d.ts +51 -0
  64. package/dist_ts/formats/facturx.encoder.js +293 -0
  65. package/dist_ts/formats/facturx.validator.d.ts +67 -0
  66. package/dist_ts/formats/facturx.validator.js +266 -0
  67. package/dist_ts/formats/pdf/extractors/associated.extractor.d.ts +14 -0
  68. package/dist_ts/formats/pdf/extractors/associated.extractor.js +68 -0
  69. package/dist_ts/formats/pdf/extractors/base.extractor.d.ts +92 -0
  70. package/dist_ts/formats/pdf/extractors/base.extractor.js +319 -0
  71. package/dist_ts/formats/pdf/extractors/index.d.ts +4 -0
  72. package/dist_ts/formats/pdf/extractors/index.js +5 -0
  73. package/dist_ts/formats/pdf/extractors/standard.extractor.d.ts +13 -0
  74. package/dist_ts/formats/pdf/extractors/standard.extractor.js +74 -0
  75. package/dist_ts/formats/pdf/extractors/text.extractor.d.ts +45 -0
  76. package/dist_ts/formats/pdf/extractors/text.extractor.js +151 -0
  77. package/dist_ts/formats/pdf/pdf.embedder.d.ts +69 -0
  78. package/dist_ts/formats/pdf/pdf.embedder.js +183 -0
  79. package/dist_ts/formats/pdf/pdf.extractor.d.ts +49 -0
  80. package/dist_ts/formats/pdf/pdf.extractor.js +98 -0
  81. package/dist_ts/formats/pdf/robust-pdf.extractor.d.ts +40 -0
  82. package/dist_ts/formats/pdf/robust-pdf.extractor.js +324 -0
  83. package/dist_ts/formats/ubl/en16931.ubl.validator.d.ts +18 -0
  84. package/dist_ts/formats/ubl/en16931.ubl.validator.js +169 -0
  85. package/dist_ts/formats/ubl/generic/ubl.encoder.d.ts +151 -0
  86. package/dist_ts/formats/ubl/generic/ubl.encoder.js +892 -0
  87. package/dist_ts/formats/ubl/ubl.decoder.d.ts +61 -0
  88. package/dist_ts/formats/ubl/ubl.decoder.js +95 -0
  89. package/dist_ts/formats/ubl/ubl.encoder.d.ts +38 -0
  90. package/dist_ts/formats/ubl/ubl.encoder.js +46 -0
  91. package/dist_ts/formats/ubl/ubl.types.d.ts +16 -0
  92. package/dist_ts/formats/ubl/ubl.types.js +21 -0
  93. package/dist_ts/formats/ubl/ubl.validator.d.ts +50 -0
  94. package/dist_ts/formats/ubl/ubl.validator.js +112 -0
  95. package/dist_ts/formats/ubl/xrechnung/xrechnung.decoder.d.ts +34 -0
  96. package/dist_ts/formats/ubl/xrechnung/xrechnung.decoder.js +424 -0
  97. package/dist_ts/formats/ubl/xrechnung/xrechnung.encoder.d.ts +75 -0
  98. package/dist_ts/formats/ubl/xrechnung/xrechnung.encoder.js +555 -0
  99. package/dist_ts/formats/ubl/xrechnung.validator.d.ts +15 -0
  100. package/dist_ts/formats/ubl/xrechnung.validator.js +107 -0
  101. package/dist_ts/formats/ubl.validator.d.ts +82 -0
  102. package/dist_ts/formats/ubl.validator.js +306 -0
  103. package/dist_ts/formats/utils/format.detector.d.ts +62 -0
  104. package/dist_ts/formats/utils/format.detector.js +249 -0
  105. package/dist_ts/formats/validation/en16931.validator.d.ts +23 -0
  106. package/dist_ts/formats/validation/en16931.validator.js +119 -0
  107. package/dist_ts/formats/validator.factory.d.ts +18 -0
  108. package/dist_ts/formats/validator.factory.js +78 -0
  109. package/dist_ts/formats/xinvoice.decoder.d.ts +28 -0
  110. package/dist_ts/formats/xinvoice.decoder.js +332 -0
  111. package/dist_ts/formats/xinvoice.encoder.d.ts +19 -0
  112. package/dist_ts/formats/xinvoice.encoder.js +282 -0
  113. package/dist_ts/index.d.ts +51 -0
  114. package/dist_ts/index.js +90 -0
  115. package/dist_ts/interfaces/common.d.ts +79 -0
  116. package/dist_ts/interfaces/common.js +24 -0
  117. package/dist_ts/interfaces.d.ts +87 -0
  118. package/dist_ts/interfaces.js +23 -0
  119. package/dist_ts/plugins.d.ts +14 -0
  120. package/dist_ts/plugins.js +31 -0
  121. package/npmextra.json +35 -0
  122. package/package.json +71 -0
  123. package/readme.hints.md +1107 -0
  124. package/readme.howtofixtests.md +38 -0
  125. package/readme.literature.md +1 -0
  126. package/readme.md +998 -0
  127. package/readme.plan.md +481 -0
  128. package/ts/00_commitinfo_data.ts +8 -0
  129. package/ts/einvoice.ts +603 -0
  130. package/ts/errors.ts +341 -0
  131. package/ts/formats/base/base.decoder.ts +68 -0
  132. package/ts/formats/base/base.encoder.ts +14 -0
  133. package/ts/formats/base/base.validator.ts +64 -0
  134. package/ts/formats/cii/cii.decoder.ts +139 -0
  135. package/ts/formats/cii/cii.encoder.ts +64 -0
  136. package/ts/formats/cii/cii.types.ts +44 -0
  137. package/ts/formats/cii/cii.validator.ts +171 -0
  138. package/ts/formats/cii/facturx/facturx.decoder.ts +243 -0
  139. package/ts/formats/cii/facturx/facturx.encoder.ts +483 -0
  140. package/ts/formats/cii/facturx/facturx.types.ts +18 -0
  141. package/ts/formats/cii/facturx/facturx.validator.ts +180 -0
  142. package/ts/formats/cii/zugferd/zugferd.decoder.ts +256 -0
  143. package/ts/formats/cii/zugferd/zugferd.encoder.ts +661 -0
  144. package/ts/formats/cii/zugferd/zugferd.types.ts +18 -0
  145. package/ts/formats/cii/zugferd/zugferd.v1.decoder.ts +267 -0
  146. package/ts/formats/cii/zugferd/zugferd.validator.ts +31 -0
  147. package/ts/formats/factories/decoder.factory.ts +62 -0
  148. package/ts/formats/factories/encoder.factory.ts +47 -0
  149. package/ts/formats/factories/validator.factory.ts +134 -0
  150. package/ts/formats/pdf/extractors/associated.extractor.ts +78 -0
  151. package/ts/formats/pdf/extractors/base.extractor.ts +355 -0
  152. package/ts/formats/pdf/extractors/index.ts +4 -0
  153. package/ts/formats/pdf/extractors/standard.extractor.ts +86 -0
  154. package/ts/formats/pdf/extractors/text.extractor.ts +162 -0
  155. package/ts/formats/pdf/pdf.embedder.ts +242 -0
  156. package/ts/formats/pdf/pdf.extractor.ts +141 -0
  157. package/ts/formats/ubl/en16931.ubl.validator.ts +216 -0
  158. package/ts/formats/ubl/generic/ubl.encoder.ts +1041 -0
  159. package/ts/formats/ubl/ubl.decoder.ts +121 -0
  160. package/ts/formats/ubl/ubl.encoder.ts +63 -0
  161. package/ts/formats/ubl/ubl.types.ts +22 -0
  162. package/ts/formats/ubl/ubl.validator.ts +133 -0
  163. package/ts/formats/ubl/xrechnung/xrechnung.decoder.ts +471 -0
  164. package/ts/formats/ubl/xrechnung/xrechnung.encoder.ts +619 -0
  165. package/ts/formats/ubl/xrechnung.validator.ts +185 -0
  166. package/ts/formats/utils/format.detector.ts +306 -0
  167. package/ts/formats/validation/en16931.validator.ts +135 -0
  168. package/ts/index.ts +164 -0
  169. package/ts/interfaces/common.ts +90 -0
  170. package/ts/interfaces.ts +98 -0
  171. package/ts/plugins.ts +61 -0
@@ -0,0 +1,471 @@
1
+ import { UBLBaseDecoder } from '../ubl.decoder.js';
2
+ import type { TInvoice, TCreditNote, TDebitNote } from '../../../interfaces/common.js';
3
+ import { business, finance } from '../../../plugins.js';
4
+ import { UBLDocumentType } from '../ubl.types.js';
5
+ import { EN16931Validator } from '../../validation/en16931.validator.js';
6
+
7
+ /**
8
+ * Decoder for XRechnung (UBL) format
9
+ * Implements decoding of XRechnung invoices to TInvoice
10
+ */
11
+ export class XRechnungDecoder extends UBLBaseDecoder {
12
+ /**
13
+ * Decodes a UBL credit note
14
+ * @returns Promise resolving to a TCreditNote object
15
+ */
16
+ protected async decodeCreditNote(): Promise<TCreditNote> {
17
+ // Extract common data
18
+ const commonData = await this.extractCommonData();
19
+
20
+ // Return the invoice data as a credit note
21
+ return {
22
+ ...commonData,
23
+ accountingDocType: 'creditnote' as const
24
+ } as unknown as TCreditNote;
25
+ }
26
+
27
+ /**
28
+ * Decodes a UBL debit note (invoice)
29
+ * @returns Promise resolving to a TDebitNote object
30
+ */
31
+ protected async decodeDebitNote(): Promise<TDebitNote> {
32
+ // Extract common data
33
+ const commonData = await this.extractCommonData();
34
+
35
+ // Return the invoice data as a debit note
36
+ return {
37
+ ...commonData,
38
+ accountingDocType: 'debitnote' as const
39
+ } as unknown as TDebitNote;
40
+ }
41
+
42
+ /**
43
+ * Extracts common invoice data from XRechnung XML
44
+ * @returns Common invoice data
45
+ */
46
+ private async extractCommonData(): Promise<Partial<TInvoice>> {
47
+ try {
48
+ // Default values
49
+ const invoiceId = this.getText('//cbc:ID', this.doc) || `INV-${Date.now()}`;
50
+ const issueDateText = this.getText('//cbc:IssueDate', this.doc);
51
+ const issueDate = issueDateText ? new Date(issueDateText).getTime() : Date.now();
52
+ const currencyCode = this.getText('//cbc:DocumentCurrencyCode', this.doc) || 'EUR';
53
+
54
+ // Extract payment terms
55
+ let dueInDays = 30; // Default
56
+ const dueDateText = this.getText('//cac:PaymentTerms/cbc:PaymentDueDate', this.doc);
57
+ if (dueDateText) {
58
+ const dueDateObj = new Date(dueDateText);
59
+ const issueDateObj = new Date(issueDate);
60
+ const diffTime = Math.abs(dueDateObj.getTime() - issueDateObj.getTime());
61
+ dueInDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
62
+ }
63
+
64
+ // Extract items
65
+ const items: finance.TAccountingDocItem[] = [];
66
+ const invoiceLines = this.select('//cac:InvoiceLine', this.doc);
67
+
68
+ if (invoiceLines && Array.isArray(invoiceLines)) {
69
+ for (let i = 0; i < invoiceLines.length; i++) {
70
+ const line = invoiceLines[i];
71
+
72
+ const position = i + 1;
73
+ const name = this.getText('./cac:Item/cbc:Name', line) || `Item ${position}`;
74
+ const description = this.getText('./cac:Item/cbc:Description', line) || '';
75
+ const articleNumber = this.getText('./cac:Item/cac:SellersItemIdentification/cbc:ID', line) || '';
76
+ const buyerItemID = this.getText('./cac:Item/cac:BuyersItemIdentification/cbc:ID', line) || '';
77
+ const standardItemID = this.getText('./cac:Item/cac:StandardItemIdentification/cbc:ID', line) || '';
78
+ const commodityClassification = this.getText('./cac:Item/cac:CommodityClassification/cbc:ItemClassificationCode', line) || '';
79
+ const unitType = this.getText('./cbc:InvoicedQuantity/@unitCode', line) || 'EA';
80
+
81
+ let unitQuantity = 1;
82
+ const quantityText = this.getText('./cbc:InvoicedQuantity', line);
83
+ if (quantityText) {
84
+ unitQuantity = parseFloat(quantityText) || 1;
85
+ }
86
+
87
+ let unitNetPrice = 0;
88
+ const priceText = this.getText('./cac:Price/cbc:PriceAmount', line);
89
+ if (priceText) {
90
+ unitNetPrice = parseFloat(priceText) || 0;
91
+ }
92
+
93
+ let vatPercentage = 0;
94
+ const percentText = this.getText('./cac:Item/cac:ClassifiedTaxCategory/cbc:Percent', line);
95
+ if (percentText) {
96
+ vatPercentage = parseFloat(percentText) || 0;
97
+ }
98
+
99
+ // Create item with extended metadata
100
+ const item: finance.TAccountingDocItem & { metadata?: any } = {
101
+ position,
102
+ name,
103
+ articleNumber,
104
+ unitType,
105
+ unitQuantity,
106
+ unitNetPrice,
107
+ vatPercentage
108
+ };
109
+
110
+ // Extract order line reference
111
+ const orderLineReference = this.getText('./cac:OrderLineReference/cac:OrderReference/cbc:ID', line) || '';
112
+ const orderLineReferenceId = this.getText('./cac:OrderLineReference/cbc:LineID', line) || '';
113
+
114
+ // Extract additional item properties
115
+ const additionalProps: Record<string, string> = {};
116
+ const propNodes = this.select('./cac:Item/cac:AdditionalItemProperty', line);
117
+ if (propNodes && Array.isArray(propNodes)) {
118
+ for (const propNode of propNodes) {
119
+ const propName = this.getText('./cbc:Name', propNode);
120
+ const propValue = this.getText('./cbc:Value', propNode);
121
+ if (propName && propValue) {
122
+ additionalProps[propName] = propValue;
123
+ }
124
+ }
125
+ }
126
+
127
+ // Store additional item data in metadata
128
+ if (description || buyerItemID || standardItemID || commodityClassification || orderLineReference || Object.keys(additionalProps).length > 0) {
129
+ item.metadata = {
130
+ description,
131
+ buyerItemID,
132
+ standardItemID,
133
+ commodityClassification,
134
+ orderLineReference,
135
+ orderLineReferenceId,
136
+ additionalProperties: additionalProps
137
+ };
138
+ }
139
+
140
+ items.push(item);
141
+ }
142
+ }
143
+
144
+ // Extract business references
145
+ const buyerReference = this.getText('//cbc:BuyerReference', this.doc);
146
+ const orderReference = this.getText('//cac:OrderReference/cbc:ID', this.doc);
147
+ const contractReference = this.getText('//cac:ContractDocumentReference/cbc:ID', this.doc);
148
+ const projectReference = this.getText('//cac:ProjectReference/cbc:ID', this.doc);
149
+
150
+ // Extract payment information
151
+ const paymentMeansCode = this.getText('//cac:PaymentMeans/cbc:PaymentMeansCode', this.doc);
152
+ const paymentID = this.getText('//cac:PaymentMeans/cbc:PaymentID', this.doc);
153
+ const paymentDueDate = this.getText('//cac:PaymentMeans/cbc:PaymentDueDate', this.doc);
154
+ const iban = this.getText('//cac:PaymentMeans/cac:PayeeFinancialAccount/cbc:ID', this.doc);
155
+ const bic = this.getText('//cac:PaymentMeans/cac:PayeeFinancialAccount/cac:FinancialInstitutionBranch/cbc:ID', this.doc);
156
+ const bankName = this.getText('//cac:PaymentMeans/cac:PayeeFinancialAccount/cac:FinancialInstitutionBranch/cbc:Name', this.doc);
157
+ const accountName = this.getText('//cac:PaymentMeans/cac:PayeeFinancialAccount/cbc:Name', this.doc);
158
+
159
+ // Extract payment terms with discount
160
+ const paymentTermsNote = this.getText('//cac:PaymentTerms/cbc:Note', this.doc);
161
+ const discountPercent = this.getText('//cac:PaymentTerms/cbc:SettlementDiscountPercent', this.doc);
162
+
163
+ // Extract period information
164
+ const periodStart = this.getText('//cac:InvoicePeriod/cbc:StartDate', this.doc);
165
+ const periodEnd = this.getText('//cac:InvoicePeriod/cbc:EndDate', this.doc);
166
+ const deliveryDate = this.getText('//cac:Delivery/cbc:ActualDeliveryDate', this.doc);
167
+
168
+ // Extract notes (excluding PaymentTerms notes)
169
+ const allNotes: string[] = [];
170
+ const noteNodes = this.select('//cbc:Note[not(parent::cac:PaymentTerms)]', this.doc);
171
+ if (noteNodes && Array.isArray(noteNodes)) {
172
+ for (let i = 0; i < noteNodes.length; i++) {
173
+ const noteText = noteNodes[i].textContent || '';
174
+ if (noteText) {
175
+ allNotes.push(noteText);
176
+ }
177
+ }
178
+ }
179
+
180
+ // Extract subject and notes separately
181
+ // If we have notes, the first one might be the subject
182
+ let subject = `Invoice ${invoiceId}`;
183
+ let notes = [...allNotes];
184
+
185
+ // If the first note doesn't look like a payment term or other standard note,
186
+ // treat it as the subject
187
+ if (allNotes.length > 0 && !allNotes[0].toLowerCase().includes('due in') &&
188
+ !allNotes[0].toLowerCase().includes('payment')) {
189
+ subject = allNotes[0];
190
+ notes = allNotes.slice(1); // Remove subject from notes
191
+ }
192
+
193
+ // Extract seller and buyer information
194
+ const seller = this.extractParty('//cac:AccountingSupplierParty/cac:Party');
195
+ const buyer = this.extractParty('//cac:AccountingCustomerParty/cac:Party');
196
+
197
+ // Create the common invoice data with metadata for business references
198
+ const invoiceData: any = {
199
+ type: 'accounting-doc' as const,
200
+ accountingDocType: 'invoice' as const,
201
+ id: invoiceId,
202
+ accountingDocId: invoiceId,
203
+ date: issueDate,
204
+ accountingDocStatus: 'issued' as const,
205
+ versionInfo: {
206
+ type: 'final',
207
+ version: '1.0.0'
208
+ },
209
+ language: 'en',
210
+ incidenceId: invoiceId,
211
+ from: seller,
212
+ to: buyer,
213
+ subject: subject,
214
+ items: items,
215
+ dueInDays: dueInDays,
216
+ reverseCharge: false,
217
+ currency: currencyCode as finance.TCurrency,
218
+ notes: notes,
219
+ objectActions: [],
220
+ metadata: {
221
+ format: 'xrechnung' as any,
222
+ version: '1.0.0',
223
+ extensions: {
224
+ businessReferences: {
225
+ buyerReference,
226
+ orderReference,
227
+ contractReference,
228
+ projectReference
229
+ },
230
+ paymentInformation: {
231
+ paymentMeansCode,
232
+ paymentID,
233
+ paymentDueDate,
234
+ iban,
235
+ bic,
236
+ bankName,
237
+ accountName,
238
+ paymentTermsNote,
239
+ discountPercent
240
+ },
241
+ dateInformation: {
242
+ periodStart,
243
+ periodEnd,
244
+ deliveryDate
245
+ }
246
+ }
247
+ }
248
+ };
249
+
250
+ // Validate mandatory EN16931 fields unless validation is skipped
251
+ if (!this.skipValidation) {
252
+ EN16931Validator.validateMandatoryFields(invoiceData);
253
+ }
254
+
255
+ return invoiceData;
256
+ } catch (error) {
257
+ // Re-throw validation errors
258
+ if (error.message && error.message.includes('EN16931 validation failed')) {
259
+ throw error;
260
+ }
261
+
262
+ console.error('Error extracting common data:', error);
263
+ // Return default data
264
+ return {
265
+ type: 'accounting-doc' as const,
266
+ accountingDocType: 'invoice' as const,
267
+ id: `INV-${Date.now()}`,
268
+ accountingDocId: `INV-${Date.now()}`,
269
+ date: Date.now(),
270
+ accountingDocStatus: 'issued' as const,
271
+ versionInfo: {
272
+ type: 'final',
273
+ version: '1.0.0'
274
+ },
275
+ language: 'en',
276
+ incidenceId: `INV-${Date.now()}`,
277
+ from: this.createEmptyContact(),
278
+ to: this.createEmptyContact(),
279
+ subject: 'Invoice',
280
+ items: [],
281
+ dueInDays: 30,
282
+ reverseCharge: false,
283
+ currency: 'EUR',
284
+ notes: [],
285
+ objectActions: []
286
+ };
287
+ }
288
+ }
289
+
290
+ /**
291
+ * Extracts party information from XML
292
+ * @param partyPath XPath to the party element
293
+ * @returns TContact object
294
+ */
295
+ private extractParty(partyPath: string): business.TContact {
296
+ try {
297
+ // Default values
298
+ let name = '';
299
+ let streetName = '';
300
+ let houseNumber = '0';
301
+ let city = '';
302
+ let postalCode = '';
303
+ let country = '';
304
+ let countryCode = '';
305
+ let vatId = '';
306
+ let registrationId = '';
307
+ let registrationName = '';
308
+ let contactPhone = '';
309
+ let contactEmail = '';
310
+ let contactName = '';
311
+ let gln = '';
312
+ const additionalIdentifiers: any[] = [];
313
+
314
+ // Try to extract party information
315
+ const partyNodes = this.select(partyPath, this.doc);
316
+
317
+ if (partyNodes && Array.isArray(partyNodes) && partyNodes.length > 0) {
318
+ const party = partyNodes[0];
319
+
320
+ // Extract GLN from EndpointID
321
+ const endpointId = this.getText('./cbc:EndpointID[@schemeID="0088"]', party);
322
+ if (endpointId) {
323
+ gln = endpointId;
324
+ }
325
+
326
+ // Extract additional party identifications
327
+ const partyIdNodes = this.select('./cac:PartyIdentification', party);
328
+ if (partyIdNodes && Array.isArray(partyIdNodes)) {
329
+ for (const idNode of partyIdNodes) {
330
+ const idValue = this.getText('./cbc:ID', idNode);
331
+ const idElement = (idNode as Element).getElementsByTagName('cbc:ID')[0];
332
+ const schemeId = idElement?.getAttribute('schemeID');
333
+ if (idValue) {
334
+ additionalIdentifiers.push({
335
+ value: idValue,
336
+ scheme: schemeId || ''
337
+ });
338
+ }
339
+ }
340
+ }
341
+
342
+ // Extract name
343
+ name = this.getText('./cac:PartyName/cbc:Name', party) || '';
344
+
345
+ // Extract address
346
+ const addressNodes = this.select('./cac:PostalAddress', party);
347
+ if (addressNodes && Array.isArray(addressNodes) && addressNodes.length > 0) {
348
+ const address = addressNodes[0];
349
+
350
+ streetName = this.getText('./cbc:StreetName', address) || '';
351
+ houseNumber = this.getText('./cbc:BuildingNumber', address) || '0';
352
+ city = this.getText('./cbc:CityName', address) || '';
353
+ postalCode = this.getText('./cbc:PostalZone', address) || '';
354
+
355
+ const countryNodes = this.select('./cac:Country', address);
356
+ if (countryNodes && Array.isArray(countryNodes) && countryNodes.length > 0) {
357
+ const countryNode = countryNodes[0];
358
+ country = this.getText('./cbc:Name', countryNode) || '';
359
+ countryCode = this.getText('./cbc:IdentificationCode', countryNode) || '';
360
+ }
361
+ }
362
+
363
+ // Extract tax information
364
+ const taxSchemeNodes = this.select('./cac:PartyTaxScheme', party);
365
+ if (taxSchemeNodes && Array.isArray(taxSchemeNodes) && taxSchemeNodes.length > 0) {
366
+ vatId = this.getText('./cbc:CompanyID', taxSchemeNodes[0]) || '';
367
+ }
368
+
369
+ // Extract registration information
370
+ const legalEntityNodes = this.select('./cac:PartyLegalEntity', party);
371
+ if (legalEntityNodes && Array.isArray(legalEntityNodes) && legalEntityNodes.length > 0) {
372
+ registrationId = this.getText('./cbc:CompanyID', legalEntityNodes[0]) || '';
373
+ registrationName = this.getText('./cbc:RegistrationName', legalEntityNodes[0]) || name;
374
+ }
375
+
376
+ // Extract contact information
377
+ const contactNodes = this.select('./cac:Contact', party);
378
+ if (contactNodes && Array.isArray(contactNodes) && contactNodes.length > 0) {
379
+ const contact = contactNodes[0];
380
+ contactPhone = this.getText('./cbc:Telephone', contact) || '';
381
+ contactEmail = this.getText('./cbc:ElectronicMail', contact) || '';
382
+ contactName = this.getText('./cbc:Name', contact) || '';
383
+ }
384
+ }
385
+
386
+ // Create contact with additional metadata for contact information
387
+ const contact: business.TContact & { metadata?: any } = {
388
+ type: 'company',
389
+ name: name,
390
+ description: '',
391
+ address: {
392
+ streetName: streetName,
393
+ houseNumber: houseNumber,
394
+ city: city,
395
+ postalCode: postalCode,
396
+ country: country,
397
+ countryCode: countryCode
398
+ },
399
+ status: 'active',
400
+ foundedDate: {
401
+ year: 2000,
402
+ month: 1,
403
+ day: 1
404
+ },
405
+ registrationDetails: {
406
+ vatId: vatId,
407
+ registrationId: registrationId,
408
+ registrationName: registrationName
409
+ }
410
+ };
411
+
412
+ // Store contact information and additional identifiers in metadata if available
413
+ const metadata: any = {};
414
+
415
+ if (contactPhone || contactEmail || contactName) {
416
+ metadata.contactInformation = {
417
+ phone: contactPhone,
418
+ email: contactEmail,
419
+ name: contactName
420
+ };
421
+ }
422
+
423
+ if (gln) {
424
+ (contact as any).gln = gln;
425
+ }
426
+
427
+ if (additionalIdentifiers.length > 0) {
428
+ (contact as any).additionalIdentifiers = additionalIdentifiers;
429
+ }
430
+
431
+ if (Object.keys(metadata).length > 0) {
432
+ contact.metadata = metadata;
433
+ }
434
+
435
+ return contact;
436
+ } catch (error) {
437
+ console.error('Error extracting party information:', error);
438
+ return this.createEmptyContact();
439
+ }
440
+ }
441
+
442
+ /**
443
+ * Creates an empty TContact object
444
+ * @returns Empty TContact object
445
+ */
446
+ private createEmptyContact(): business.TContact {
447
+ return {
448
+ type: 'company',
449
+ name: '',
450
+ description: '',
451
+ address: {
452
+ streetName: '',
453
+ houseNumber: '0',
454
+ city: '',
455
+ country: '',
456
+ postalCode: ''
457
+ },
458
+ status: 'active',
459
+ foundedDate: {
460
+ year: 2000,
461
+ month: 1,
462
+ day: 1
463
+ },
464
+ registrationDetails: {
465
+ vatId: '',
466
+ registrationId: '',
467
+ registrationName: ''
468
+ }
469
+ };
470
+ }
471
+ }