@fin.cx/skr 1.1.0 → 1.2.1

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 (64) 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/index.d.ts +6 -0
  4. package/dist_ts/index.js +7 -1
  5. package/dist_ts/plugins.d.ts +8 -1
  6. package/dist_ts/plugins.js +10 -2
  7. package/dist_ts/skr.api.d.ts +70 -0
  8. package/dist_ts/skr.api.js +348 -1
  9. package/dist_ts/skr.classes.account.d.ts +28 -0
  10. package/dist_ts/skr.classes.account.js +87 -4
  11. package/dist_ts/skr.classes.journalentry.js +56 -4
  12. package/dist_ts/skr.classes.ledger.js +5 -1
  13. package/dist_ts/skr.export.accounts.d.ts +53 -0
  14. package/dist_ts/skr.export.accounts.js +111 -0
  15. package/dist_ts/skr.export.balances.d.ts +59 -0
  16. package/dist_ts/skr.export.balances.js +205 -0
  17. package/dist_ts/skr.export.d.ts +110 -0
  18. package/dist_ts/skr.export.js +315 -0
  19. package/dist_ts/skr.export.ledger.d.ts +95 -0
  20. package/dist_ts/skr.export.ledger.js +164 -0
  21. package/dist_ts/skr.export.pdf.d.ts +82 -0
  22. package/dist_ts/skr.export.pdf.js +548 -0
  23. package/dist_ts/skr.invoice.adapter.d.ts +98 -0
  24. package/dist_ts/skr.invoice.adapter.js +476 -0
  25. package/dist_ts/skr.invoice.booking.d.ts +102 -0
  26. package/dist_ts/skr.invoice.booking.js +578 -0
  27. package/dist_ts/skr.invoice.entity.d.ts +287 -0
  28. package/dist_ts/skr.invoice.entity.js +2 -0
  29. package/dist_ts/skr.invoice.mapper.d.ts +69 -0
  30. package/dist_ts/skr.invoice.mapper.js +401 -0
  31. package/dist_ts/skr.invoice.storage.d.ts +140 -0
  32. package/dist_ts/skr.invoice.storage.js +529 -0
  33. package/dist_ts/skr.postingkeys.d.ts +56 -0
  34. package/dist_ts/skr.postingkeys.js +196 -0
  35. package/dist_ts/skr.security.d.ts +65 -0
  36. package/dist_ts/skr.security.js +319 -0
  37. package/dist_ts/skr.types.d.ts +19 -0
  38. package/dist_ts/skr03.data.js +3 -1
  39. package/dist_ts/skr04.data.js +3 -1
  40. package/package.json +17 -12
  41. package/readme.hints.md +54 -1
  42. package/readme.md +207 -16
  43. package/ts/00_commitinfo_data.ts +8 -0
  44. package/ts/index.ts +6 -0
  45. package/ts/plugins.ts +22 -1
  46. package/ts/skr.api.ts +485 -0
  47. package/ts/skr.classes.account.ts +106 -3
  48. package/ts/skr.classes.journalentry.ts +78 -3
  49. package/ts/skr.classes.ledger.ts +4 -0
  50. package/ts/skr.export.accounts.ts +154 -0
  51. package/ts/skr.export.balances.ts +270 -0
  52. package/ts/skr.export.ledger.ts +249 -0
  53. package/ts/skr.export.pdf.ts +601 -0
  54. package/ts/skr.export.ts +443 -0
  55. package/ts/skr.invoice.adapter.ts +581 -0
  56. package/ts/skr.invoice.booking.ts +760 -0
  57. package/ts/skr.invoice.entity.ts +351 -0
  58. package/ts/skr.invoice.mapper.ts +486 -0
  59. package/ts/skr.invoice.storage.ts +710 -0
  60. package/ts/skr.postingkeys.ts +252 -0
  61. package/ts/skr.security.ts +405 -0
  62. package/ts/skr.types.ts +27 -0
  63. package/ts/skr03.data.ts +2 -0
  64. package/ts/skr04.data.ts +2 -0
@@ -0,0 +1,98 @@
1
+ import type { IInvoice, TInvoiceFormat, TInvoiceDirection } from './skr.invoice.entity.js';
2
+ /**
3
+ * Adapter for @fin.cx/einvoice library
4
+ * Handles parsing, validation, and format conversion of e-invoices
5
+ */
6
+ export declare class InvoiceAdapter {
7
+ private logger;
8
+ constructor();
9
+ private readonly MAX_XML_SIZE;
10
+ private readonly MAX_PDF_SIZE;
11
+ /**
12
+ * Parse an invoice from file or buffer
13
+ */
14
+ parseInvoice(file: Buffer | string, direction: TInvoiceDirection): Promise<IInvoice>;
15
+ /**
16
+ * Validate an invoice using multi-level validation
17
+ */
18
+ private validateInvoice;
19
+ /**
20
+ * Map EN16931 Business Terms to internal invoice model
21
+ */
22
+ private mapToInternalModel;
23
+ /**
24
+ * Map party information
25
+ */
26
+ private mapParty;
27
+ /**
28
+ * Map bank account information
29
+ */
30
+ private mapBankAccount;
31
+ /**
32
+ * Map invoice lines
33
+ */
34
+ private mapInvoiceLines;
35
+ /**
36
+ * Map VAT category
37
+ */
38
+ private mapVATCategory;
39
+ /**
40
+ * Get exemption reason for VAT category
41
+ */
42
+ private getExemptionReason;
43
+ /**
44
+ * Map VAT breakdown
45
+ */
46
+ private mapVATBreakdown;
47
+ /**
48
+ * Map allowances and charges
49
+ */
50
+ private mapAllowancesCharges;
51
+ /**
52
+ * Map line-level allowances and charges
53
+ */
54
+ private mapLineAllowancesCharges;
55
+ /**
56
+ * Map payment terms
57
+ */
58
+ private mapPaymentTerms;
59
+ /**
60
+ * Parse skonto terms from payment terms text
61
+ */
62
+ private parseSkontoTerms;
63
+ /**
64
+ * Map payment means
65
+ */
66
+ private mapPaymentMeans;
67
+ /**
68
+ * Classify tax scenario based on invoice data
69
+ */
70
+ private classifyTaxScenario;
71
+ /**
72
+ * Check if country is in EU
73
+ */
74
+ private isEUCountry;
75
+ /**
76
+ * Map e-invoice format from library format
77
+ */
78
+ private mapEInvoiceFormat;
79
+ /**
80
+ * Calculate content hash for the invoice
81
+ */
82
+ private calculateContentHash;
83
+ /**
84
+ * Convert invoice to different format
85
+ */
86
+ convertFormat(invoice: IInvoice, targetFormat: TInvoiceFormat): Promise<string>;
87
+ /**
88
+ * Generate invoice from internal data
89
+ */
90
+ generateInvoice(invoiceData: Partial<IInvoice>, format: TInvoiceFormat): Promise<{
91
+ xml: string;
92
+ pdf?: Buffer;
93
+ }>;
94
+ /**
95
+ * Map internal invoice to EN16931 Business Terms
96
+ */
97
+ private mapToBusinessTerms;
98
+ }
@@ -0,0 +1,476 @@
1
+ import * as plugins from './plugins.js';
2
+ /**
3
+ * Adapter for @fin.cx/einvoice library
4
+ * Handles parsing, validation, and format conversion of e-invoices
5
+ */
6
+ export class InvoiceAdapter {
7
+ constructor() {
8
+ this.MAX_XML_SIZE = 10 * 1024 * 1024; // 10MB max
9
+ this.MAX_PDF_SIZE = 50 * 1024 * 1024; // 50MB max
10
+ this.logger = new plugins.smartlog.ConsoleLog();
11
+ }
12
+ /**
13
+ * Parse an invoice from file or buffer
14
+ */
15
+ async parseInvoice(file, direction) {
16
+ try {
17
+ // Validate input size
18
+ if (Buffer.isBuffer(file)) {
19
+ if (file.length > this.MAX_XML_SIZE) {
20
+ throw new Error(`Invoice file too large: ${file.length} bytes (max ${this.MAX_XML_SIZE} bytes)`);
21
+ }
22
+ }
23
+ else if (typeof file === 'string' && file.length > this.MAX_XML_SIZE) {
24
+ throw new Error(`Invoice XML too large: ${file.length} characters (max ${this.MAX_XML_SIZE} characters)`);
25
+ }
26
+ // Parse the invoice using @fin.cx/einvoice
27
+ let einvoice;
28
+ if (typeof file === 'string') {
29
+ einvoice = await plugins.einvoice.EInvoice.fromXml(file);
30
+ }
31
+ else {
32
+ // Convert buffer to string first
33
+ const xmlString = file.toString('utf-8');
34
+ einvoice = await plugins.einvoice.EInvoice.fromXml(xmlString);
35
+ }
36
+ // Get detected format
37
+ const format = this.mapEInvoiceFormat(einvoice.format || 'xrechnung');
38
+ // Validate the invoice (takes ~2.2ms)
39
+ const validationResult = await this.validateInvoice(einvoice);
40
+ // Extract invoice data
41
+ const invoiceData = einvoice.toObject();
42
+ // Map to internal invoice model
43
+ const invoice = await this.mapToInternalModel(invoiceData, format, direction, validationResult);
44
+ // Store original XML content
45
+ invoice.xmlContent = einvoice.getXml();
46
+ // Calculate content hash
47
+ invoice.contentHash = await this.calculateContentHash(invoice.xmlContent);
48
+ // Classify tax scenario
49
+ invoice.taxScenario = this.classifyTaxScenario(invoice);
50
+ return invoice;
51
+ }
52
+ catch (error) {
53
+ this.logger.log('error', `Failed to parse invoice: ${error}`);
54
+ throw new Error(`Invoice parsing failed: ${error.message}`);
55
+ }
56
+ }
57
+ /**
58
+ * Validate an invoice using multi-level validation
59
+ */
60
+ async validateInvoice(einvoice) {
61
+ // Perform multi-level validation
62
+ const validationResult = await einvoice.validate();
63
+ // Parse validation results into our structure
64
+ const syntaxResult = {
65
+ isValid: validationResult.syntax?.valid !== false,
66
+ errors: validationResult.syntax?.errors || [],
67
+ warnings: validationResult.syntax?.warnings || []
68
+ };
69
+ const semanticResult = {
70
+ isValid: validationResult.semantic?.valid !== false,
71
+ errors: validationResult.semantic?.errors || [],
72
+ warnings: validationResult.semantic?.warnings || []
73
+ };
74
+ const businessResult = {
75
+ isValid: validationResult.business?.valid !== false,
76
+ errors: validationResult.business?.errors || [],
77
+ warnings: validationResult.business?.warnings || []
78
+ };
79
+ const countryResult = {
80
+ isValid: validationResult.country?.valid !== false,
81
+ errors: validationResult.country?.errors || [],
82
+ warnings: validationResult.country?.warnings || []
83
+ };
84
+ return {
85
+ isValid: syntaxResult.isValid && semanticResult.isValid && businessResult.isValid,
86
+ syntax: {
87
+ valid: syntaxResult.isValid,
88
+ errors: syntaxResult.errors || [],
89
+ warnings: syntaxResult.warnings || []
90
+ },
91
+ semantic: {
92
+ valid: semanticResult.isValid,
93
+ errors: semanticResult.errors || [],
94
+ warnings: semanticResult.warnings || []
95
+ },
96
+ businessRules: {
97
+ valid: businessResult.isValid,
98
+ errors: businessResult.errors || [],
99
+ warnings: businessResult.warnings || []
100
+ },
101
+ countrySpecific: {
102
+ valid: countryResult.isValid,
103
+ errors: countryResult.errors || [],
104
+ warnings: countryResult.warnings || []
105
+ },
106
+ validatedAt: new Date(),
107
+ validatorVersion: '5.1.4'
108
+ };
109
+ }
110
+ /**
111
+ * Map EN16931 Business Terms to internal invoice model
112
+ */
113
+ async mapToInternalModel(businessTerms, format, direction, validationResult) {
114
+ const invoice = {
115
+ // Identity
116
+ id: plugins.smartunique.shortId(),
117
+ direction,
118
+ format,
119
+ // EN16931 Business Terms
120
+ invoiceNumber: businessTerms.BT1_InvoiceNumber,
121
+ issueDate: new Date(businessTerms.BT2_IssueDate),
122
+ invoiceTypeCode: businessTerms.BT3_InvoiceTypeCode || '380',
123
+ currencyCode: businessTerms.BT5_CurrencyCode || 'EUR',
124
+ taxCurrencyCode: businessTerms.BT6_TaxCurrencyCode,
125
+ taxPointDate: businessTerms.BT7_TaxPointDate ? new Date(businessTerms.BT7_TaxPointDate) : undefined,
126
+ paymentDueDate: businessTerms.BT9_PaymentDueDate ? new Date(businessTerms.BT9_PaymentDueDate) : undefined,
127
+ buyerReference: businessTerms.BT10_BuyerReference,
128
+ projectReference: businessTerms.BT11_ProjectReference,
129
+ contractReference: businessTerms.BT12_ContractReference,
130
+ orderReference: businessTerms.BT13_OrderReference,
131
+ sellerOrderReference: businessTerms.BT14_SellerOrderReference,
132
+ // Parties
133
+ supplier: this.mapParty(businessTerms.BG4_Seller),
134
+ customer: this.mapParty(businessTerms.BG7_Buyer),
135
+ payee: businessTerms.BG10_Payee ? this.mapParty(businessTerms.BG10_Payee) : undefined,
136
+ // Line items
137
+ lines: this.mapInvoiceLines(businessTerms.BG25_InvoiceLines || []),
138
+ // Allowances and charges
139
+ allowances: this.mapAllowancesCharges(businessTerms.BG20_DocumentAllowances || [], true),
140
+ charges: this.mapAllowancesCharges(businessTerms.BG21_DocumentCharges || [], false),
141
+ // Amounts
142
+ lineNetAmount: parseFloat(businessTerms.BT106_SumOfLineNetAmounts || 0),
143
+ allowanceTotalAmount: parseFloat(businessTerms.BT107_AllowanceTotalAmount || 0),
144
+ chargeTotalAmount: parseFloat(businessTerms.BT108_ChargeTotalAmount || 0),
145
+ taxExclusiveAmount: parseFloat(businessTerms.BT109_TaxExclusiveAmount || 0),
146
+ taxInclusiveAmount: parseFloat(businessTerms.BT112_TaxInclusiveAmount || 0),
147
+ prepaidAmount: parseFloat(businessTerms.BT113_PrepaidAmount || 0),
148
+ payableAmount: parseFloat(businessTerms.BT115_PayableAmount || 0),
149
+ // VAT breakdown
150
+ vatBreakdown: this.mapVATBreakdown(businessTerms.BG23_VATBreakdown || []),
151
+ totalVATAmount: parseFloat(businessTerms.BT110_TotalVATAmount || 0),
152
+ // Payment
153
+ paymentTerms: this.mapPaymentTerms(businessTerms),
154
+ paymentMeans: this.mapPaymentMeans(businessTerms.BG16_PaymentInstructions),
155
+ // Notes
156
+ invoiceNote: businessTerms.BT22_InvoiceNote,
157
+ // Processing metadata
158
+ status: 'validated',
159
+ // Storage (to be filled later)
160
+ contentHash: '',
161
+ // Validation
162
+ validationResult,
163
+ // Audit trail
164
+ createdAt: new Date(),
165
+ createdBy: 'system',
166
+ // Metadata
167
+ metadata: {
168
+ importedAt: new Date(),
169
+ parserVersion: '5.1.4',
170
+ originalFormat: format
171
+ }
172
+ };
173
+ return invoice;
174
+ }
175
+ /**
176
+ * Map party information
177
+ */
178
+ mapParty(partyData) {
179
+ if (!partyData) {
180
+ return {
181
+ id: '',
182
+ name: '',
183
+ address: { countryCode: 'DE' }
184
+ };
185
+ }
186
+ return {
187
+ id: partyData.BT29_SellerID || partyData.BT46_BuyerID || plugins.smartunique.shortId(),
188
+ name: partyData.BT27_SellerName || partyData.BT44_BuyerName || '',
189
+ address: {
190
+ street: partyData.BT35_SellerStreet || partyData.BT50_BuyerStreet,
191
+ city: partyData.BT37_SellerCity || partyData.BT52_BuyerCity,
192
+ postalCode: partyData.BT38_SellerPostalCode || partyData.BT53_BuyerPostalCode,
193
+ countryCode: partyData.BT40_SellerCountryCode || partyData.BT55_BuyerCountryCode || 'DE'
194
+ },
195
+ vatId: partyData.BT31_SellerVATID || partyData.BT48_BuyerVATID,
196
+ taxId: partyData.BT32_SellerTaxID || partyData.BT47_BuyerTaxID,
197
+ email: partyData.BT34_SellerEmail || partyData.BT49_BuyerEmail,
198
+ phone: partyData.BT33_SellerPhone,
199
+ bankAccount: this.mapBankAccount(partyData)
200
+ };
201
+ }
202
+ /**
203
+ * Map bank account information
204
+ */
205
+ mapBankAccount(partyData) {
206
+ if (!partyData?.BT84_PaymentAccountID) {
207
+ return undefined;
208
+ }
209
+ return {
210
+ iban: partyData.BT84_PaymentAccountID,
211
+ bic: partyData.BT86_PaymentServiceProviderID,
212
+ accountHolder: partyData.BT85_PaymentAccountName
213
+ };
214
+ }
215
+ /**
216
+ * Map invoice lines
217
+ */
218
+ mapInvoiceLines(linesData) {
219
+ return linesData.map((line, index) => ({
220
+ lineNumber: index + 1,
221
+ description: line.BT154_ItemDescription || '',
222
+ quantity: parseFloat(line.BT129_Quantity || 1),
223
+ unitPrice: parseFloat(line.BT146_NetPrice || 0),
224
+ netAmount: parseFloat(line.BT131_LineNetAmount || 0),
225
+ vatCategory: this.mapVATCategory(line.BT151_ItemVATCategory, line.BT152_ItemVATRate),
226
+ vatAmount: parseFloat(line.lineVATAmount || 0),
227
+ grossAmount: parseFloat(line.BT131_LineNetAmount || 0) + parseFloat(line.lineVATAmount || 0),
228
+ productCode: line.BT155_ItemSellerID,
229
+ allowances: this.mapLineAllowancesCharges(line.BG27_LineAllowances || [], true),
230
+ charges: this.mapLineAllowancesCharges(line.BG28_LineCharges || [], false)
231
+ }));
232
+ }
233
+ /**
234
+ * Map VAT category
235
+ */
236
+ mapVATCategory(categoryCode, rate) {
237
+ const vatRate = typeof rate === 'string' ? parseFloat(rate) : rate;
238
+ return {
239
+ code: categoryCode || 'S',
240
+ rate: vatRate || 0,
241
+ exemptionReason: this.getExemptionReason(categoryCode)
242
+ };
243
+ }
244
+ /**
245
+ * Get exemption reason for VAT category
246
+ */
247
+ getExemptionReason(categoryCode) {
248
+ const exemptionReasons = {
249
+ 'E': 'Tax exempt',
250
+ 'Z': 'Zero rated',
251
+ 'AE': 'Reverse charge (§13b UStG)',
252
+ 'K': 'Intra-EU supply',
253
+ 'G': 'Export outside EU',
254
+ 'O': 'Outside scope of tax',
255
+ 'S': undefined // Standard rate, no exemption
256
+ };
257
+ return exemptionReasons[categoryCode];
258
+ }
259
+ /**
260
+ * Map VAT breakdown
261
+ */
262
+ mapVATBreakdown(vatBreakdown) {
263
+ return vatBreakdown.map(vat => ({
264
+ vatCategory: this.mapVATCategory(vat.BT118_VATCategory, vat.BT119_VATRate),
265
+ taxableAmount: parseFloat(vat.BT116_TaxableAmount || 0),
266
+ taxAmount: parseFloat(vat.BT117_TaxAmount || 0)
267
+ }));
268
+ }
269
+ /**
270
+ * Map allowances and charges
271
+ */
272
+ mapAllowancesCharges(data, isAllowance) {
273
+ return data.map(item => ({
274
+ reason: item.BT97_AllowanceReason || item.BT104_ChargeReason || '',
275
+ amount: parseFloat(item.BT92_AllowanceAmount || item.BT99_ChargeAmount || 0),
276
+ percentage: item.BT94_AllowancePercentage || item.BT101_ChargePercentage,
277
+ vatCategory: item.BT95_AllowanceVATCategory || item.BT102_ChargeVATCategory
278
+ ? this.mapVATCategory(item.BT95_AllowanceVATCategory || item.BT102_ChargeVATCategory, item.BT96_AllowanceVATRate || item.BT103_ChargeVATRate)
279
+ : undefined,
280
+ vatAmount: parseFloat(item.allowanceVATAmount || item.chargeVATAmount || 0)
281
+ }));
282
+ }
283
+ /**
284
+ * Map line-level allowances and charges
285
+ */
286
+ mapLineAllowancesCharges(data, isAllowance) {
287
+ return data.map(item => ({
288
+ reason: item.BT140_LineAllowanceReason || item.BT145_LineChargeReason || '',
289
+ amount: parseFloat(item.BT136_LineAllowanceAmount || item.BT141_LineChargeAmount || 0),
290
+ percentage: item.BT138_LineAllowancePercentage || item.BT143_LineChargePercentage
291
+ }));
292
+ }
293
+ /**
294
+ * Map payment terms
295
+ */
296
+ mapPaymentTerms(businessTerms) {
297
+ if (!businessTerms.BT9_PaymentDueDate && !businessTerms.BT20_PaymentTerms) {
298
+ return undefined;
299
+ }
300
+ const paymentTerms = {
301
+ dueDate: businessTerms.BT9_PaymentDueDate
302
+ ? new Date(businessTerms.BT9_PaymentDueDate)
303
+ : new Date(Date.now() + 30 * 24 * 60 * 60 * 1000), // Default 30 days
304
+ paymentTermsNote: businessTerms.BT20_PaymentTerms
305
+ };
306
+ // Parse skonto from payment terms note if present
307
+ if (businessTerms.BT20_PaymentTerms) {
308
+ paymentTerms.skonto = this.parseSkontoTerms(businessTerms.BT20_PaymentTerms);
309
+ }
310
+ return paymentTerms;
311
+ }
312
+ /**
313
+ * Parse skonto terms from payment terms text
314
+ */
315
+ parseSkontoTerms(paymentTermsText) {
316
+ const skontoTerms = [];
317
+ // Common German skonto patterns:
318
+ // "2% Skonto bei Zahlung innerhalb von 10 Tagen"
319
+ // "3% bei Zahlung bis 8 Tage, 2% bis 14 Tage"
320
+ const skontoPattern = /(\d+(?:\.\d+)?)\s*%.*?(\d+)\s*(?:Tag|Day)/gi;
321
+ let match;
322
+ while ((match = skontoPattern.exec(paymentTermsText)) !== null) {
323
+ skontoTerms.push({
324
+ percentage: parseFloat(match[1]),
325
+ days: parseInt(match[2]),
326
+ baseAmount: 0 // To be calculated based on invoice amount
327
+ });
328
+ }
329
+ return skontoTerms.length > 0 ? skontoTerms : undefined;
330
+ }
331
+ /**
332
+ * Map payment means
333
+ */
334
+ mapPaymentMeans(paymentInstructions) {
335
+ if (!paymentInstructions) {
336
+ return undefined;
337
+ }
338
+ return {
339
+ code: paymentInstructions.BT81_PaymentMeansCode || '30', // 30 = Bank transfer
340
+ account: paymentInstructions.BT84_PaymentAccountID
341
+ ? {
342
+ iban: paymentInstructions.BT84_PaymentAccountID,
343
+ bic: paymentInstructions.BT86_PaymentServiceProviderID,
344
+ accountHolder: paymentInstructions.BT85_PaymentAccountName
345
+ }
346
+ : undefined
347
+ };
348
+ }
349
+ /**
350
+ * Classify tax scenario based on invoice data
351
+ */
352
+ classifyTaxScenario(invoice) {
353
+ const supplierCountry = invoice.supplier.address.countryCode;
354
+ const customerCountry = invoice.customer.address.countryCode;
355
+ const hasVAT = invoice.totalVATAmount > 0;
356
+ const vatCategories = invoice.vatBreakdown.map(vb => vb.vatCategory.code);
357
+ // Reverse charge
358
+ if (vatCategories.includes('AE')) {
359
+ return 'reverse_charge';
360
+ }
361
+ // Small business exemption
362
+ if (vatCategories.includes('E') && invoice.invoiceNote?.includes('§19')) {
363
+ return 'small_business';
364
+ }
365
+ // Export outside EU
366
+ if (vatCategories.includes('G') || (!this.isEUCountry(customerCountry) && supplierCountry === 'DE')) {
367
+ return 'export';
368
+ }
369
+ // Intra-EU transactions
370
+ if (supplierCountry !== customerCountry && this.isEUCountry(supplierCountry) && this.isEUCountry(customerCountry)) {
371
+ if (invoice.direction === 'outbound') {
372
+ return 'intra_eu_supply';
373
+ }
374
+ else {
375
+ return 'intra_eu_acquisition';
376
+ }
377
+ }
378
+ // Domestic exempt
379
+ if (!hasVAT && supplierCountry === 'DE' && customerCountry === 'DE') {
380
+ return 'domestic_exempt';
381
+ }
382
+ // Default: Domestic taxed
383
+ return 'domestic_taxed';
384
+ }
385
+ /**
386
+ * Check if country is in EU
387
+ */
388
+ isEUCountry(countryCode) {
389
+ const euCountries = [
390
+ 'AT', 'BE', 'BG', 'HR', 'CY', 'CZ', 'DK', 'EE', 'FI', 'FR',
391
+ 'DE', 'GR', 'HU', 'IE', 'IT', 'LV', 'LT', 'LU', 'MT', 'NL',
392
+ 'PL', 'PT', 'RO', 'SK', 'SI', 'ES', 'SE'
393
+ ];
394
+ return euCountries.includes(countryCode);
395
+ }
396
+ /**
397
+ * Map e-invoice format from library format
398
+ */
399
+ mapEInvoiceFormat(format) {
400
+ const formatMap = {
401
+ 'xrechnung': 'xrechnung',
402
+ 'zugferd': 'zugferd',
403
+ 'factur-x': 'facturx',
404
+ 'facturx': 'facturx',
405
+ 'peppol': 'peppol',
406
+ 'ubl': 'ubl'
407
+ };
408
+ return formatMap[format.toLowerCase()] || 'xrechnung';
409
+ }
410
+ /**
411
+ * Calculate content hash for the invoice
412
+ */
413
+ async calculateContentHash(xmlContent) {
414
+ const hash = await plugins.smarthash.sha256FromString(xmlContent);
415
+ return hash;
416
+ }
417
+ /**
418
+ * Convert invoice to different format
419
+ */
420
+ async convertFormat(invoice, targetFormat) {
421
+ try {
422
+ // Load from existing XML
423
+ const einvoice = await plugins.einvoice.EInvoice.fromXml(invoice.xmlContent);
424
+ // Convert to target format (takes ~0.6ms)
425
+ const convertedXml = await einvoice.exportXml(targetFormat);
426
+ return convertedXml;
427
+ }
428
+ catch (error) {
429
+ this.logger.log('error', `Failed to convert invoice format: ${error}`);
430
+ throw new Error(`Format conversion failed: ${error.message}`);
431
+ }
432
+ }
433
+ /**
434
+ * Generate invoice from internal data
435
+ */
436
+ async generateInvoice(invoiceData, format) {
437
+ try {
438
+ // Create a new invoice instance
439
+ const einvoice = new plugins.einvoice.EInvoice();
440
+ // Set invoice data
441
+ const businessTerms = this.mapToBusinessTerms(invoiceData);
442
+ Object.assign(einvoice, businessTerms);
443
+ // Generate XML in requested format
444
+ const xml = await einvoice.exportXml(format);
445
+ // Generate PDF if ZUGFeRD or Factur-X
446
+ let pdf;
447
+ if (format === 'zugferd' || format === 'facturx') {
448
+ // Access the pdf property if it exists
449
+ if (einvoice.pdf && einvoice.pdf.buffer) {
450
+ pdf = Buffer.from(einvoice.pdf.buffer);
451
+ }
452
+ }
453
+ return { xml, pdf };
454
+ }
455
+ catch (error) {
456
+ this.logger.log('error', `Failed to generate invoice: ${error}`);
457
+ throw new Error(`Invoice generation failed: ${error.message}`);
458
+ }
459
+ }
460
+ /**
461
+ * Map internal invoice to EN16931 Business Terms
462
+ */
463
+ mapToBusinessTerms(invoice) {
464
+ return {
465
+ BT1_InvoiceNumber: invoice.invoiceNumber,
466
+ BT2_IssueDate: invoice.issueDate?.toISOString(),
467
+ BT3_InvoiceTypeCode: invoice.invoiceTypeCode || '380',
468
+ BT5_CurrencyCode: invoice.currencyCode || 'EUR',
469
+ BT7_TaxPointDate: invoice.taxPointDate?.toISOString(),
470
+ BT9_PaymentDueDate: invoice.paymentDueDate?.toISOString(),
471
+ // Map other Business Terms...
472
+ // This would be a comprehensive mapping in production
473
+ };
474
+ }
475
+ }
476
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2tyLmludm9pY2UuYWRhcHRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3Nrci5pbnZvaWNlLmFkYXB0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFjeEM7OztHQUdHO0FBQ0gsTUFBTSxPQUFPLGNBQWM7SUFHekI7UUFJaUIsaUJBQVksR0FBRyxFQUFFLEdBQUcsSUFBSSxHQUFHLElBQUksQ0FBQyxDQUFDLFdBQVc7UUFDNUMsaUJBQVksR0FBRyxFQUFFLEdBQUcsSUFBSSxHQUFHLElBQUksQ0FBQyxDQUFDLFdBQVc7UUFKM0QsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLE9BQU8sQ0FBQyxRQUFRLENBQUMsVUFBVSxFQUFFLENBQUM7SUFDbEQsQ0FBQztJQUtEOztPQUVHO0lBQ0ksS0FBSyxDQUFDLFlBQVksQ0FDdkIsSUFBcUIsRUFDckIsU0FBNEI7UUFFNUIsSUFBSSxDQUFDO1lBQ0gsc0JBQXNCO1lBQ3RCLElBQUksTUFBTSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO2dCQUMxQixJQUFJLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO29CQUNwQyxNQUFNLElBQUksS0FBSyxDQUFDLDJCQUEyQixJQUFJLENBQUMsTUFBTSxlQUFlLElBQUksQ0FBQyxZQUFZLFNBQVMsQ0FBQyxDQUFDO2dCQUNuRyxDQUFDO1lBQ0gsQ0FBQztpQkFBTSxJQUFJLE9BQU8sSUFBSSxLQUFLLFFBQVEsSUFBSSxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztnQkFDdkUsTUFBTSxJQUFJLEtBQUssQ0FBQywwQkFBMEIsSUFBSSxDQUFDLE1BQU0sb0JBQW9CLElBQUksQ0FBQyxZQUFZLGNBQWMsQ0FBQyxDQUFDO1lBQzVHLENBQUM7WUFFRCwyQ0FBMkM7WUFDM0MsSUFBSSxRQUFRLENBQUM7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