@fin.cx/skr 1.1.0 → 1.2.0

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 (46) hide show
  1. package/dist_ts/index.d.ts +6 -0
  2. package/dist_ts/index.js +7 -1
  3. package/dist_ts/plugins.d.ts +8 -1
  4. package/dist_ts/plugins.js +10 -2
  5. package/dist_ts/skr.api.d.ts +70 -0
  6. package/dist_ts/skr.api.js +348 -1
  7. package/dist_ts/skr.export.accounts.d.ts +53 -0
  8. package/dist_ts/skr.export.accounts.js +111 -0
  9. package/dist_ts/skr.export.balances.d.ts +59 -0
  10. package/dist_ts/skr.export.balances.js +205 -0
  11. package/dist_ts/skr.export.d.ts +110 -0
  12. package/dist_ts/skr.export.js +315 -0
  13. package/dist_ts/skr.export.ledger.d.ts +95 -0
  14. package/dist_ts/skr.export.ledger.js +164 -0
  15. package/dist_ts/skr.export.pdf.d.ts +82 -0
  16. package/dist_ts/skr.export.pdf.js +548 -0
  17. package/dist_ts/skr.invoice.adapter.d.ts +98 -0
  18. package/dist_ts/skr.invoice.adapter.js +476 -0
  19. package/dist_ts/skr.invoice.booking.d.ts +102 -0
  20. package/dist_ts/skr.invoice.booking.js +556 -0
  21. package/dist_ts/skr.invoice.entity.d.ts +287 -0
  22. package/dist_ts/skr.invoice.entity.js +2 -0
  23. package/dist_ts/skr.invoice.mapper.d.ts +69 -0
  24. package/dist_ts/skr.invoice.mapper.js +401 -0
  25. package/dist_ts/skr.invoice.storage.d.ts +140 -0
  26. package/dist_ts/skr.invoice.storage.js +529 -0
  27. package/dist_ts/skr.security.d.ts +65 -0
  28. package/dist_ts/skr.security.js +319 -0
  29. package/dist_ts/skr.types.d.ts +1 -0
  30. package/package.json +17 -12
  31. package/readme.md +207 -16
  32. package/ts/index.ts +6 -0
  33. package/ts/plugins.ts +22 -1
  34. package/ts/skr.api.ts +485 -0
  35. package/ts/skr.export.accounts.ts +154 -0
  36. package/ts/skr.export.balances.ts +270 -0
  37. package/ts/skr.export.ledger.ts +249 -0
  38. package/ts/skr.export.pdf.ts +601 -0
  39. package/ts/skr.export.ts +443 -0
  40. package/ts/skr.invoice.adapter.ts +581 -0
  41. package/ts/skr.invoice.booking.ts +738 -0
  42. package/ts/skr.invoice.entity.ts +351 -0
  43. package/ts/skr.invoice.mapper.ts +486 -0
  44. package/ts/skr.invoice.storage.ts +710 -0
  45. package/ts/skr.security.ts +405 -0
  46. package/ts/skr.types.ts +1 -0
@@ -0,0 +1,556 @@
1
+ import * as plugins from './plugins.js';
2
+ import { JournalEntry } from './skr.classes.journalentry.js';
3
+ import { SKRInvoiceMapper } from './skr.invoice.mapper.js';
4
+ /**
5
+ * Automatic booking engine for invoices
6
+ * Creates journal entries from invoice data based on SKR mapping rules
7
+ */
8
+ export class InvoiceBookingEngine {
9
+ constructor(skrType) {
10
+ this.skrType = skrType;
11
+ this.mapper = new SKRInvoiceMapper(skrType);
12
+ this.logger = new plugins.smartlog.ConsoleLog();
13
+ }
14
+ /**
15
+ * Book an invoice to the ledger
16
+ */
17
+ async bookInvoice(invoice, bookingRules, options) {
18
+ try {
19
+ // Get complete booking rules
20
+ const rules = this.mapper.mapInvoiceToSKR(invoice, bookingRules);
21
+ // Calculate confidence
22
+ const confidence = this.mapper.calculateConfidence(invoice, rules);
23
+ // Check if auto-booking is allowed
24
+ if (options?.autoBook && confidence < (options.confidenceThreshold || 80)) {
25
+ return {
26
+ success: false,
27
+ confidence,
28
+ warnings: [`Confidence score ${confidence}% is below threshold ${options.confidenceThreshold || 80}%`]
29
+ };
30
+ }
31
+ // Validate invoice before booking
32
+ if (!options?.skipValidation) {
33
+ const validationErrors = this.validateInvoice(invoice);
34
+ if (validationErrors.length > 0) {
35
+ return {
36
+ success: false,
37
+ confidence,
38
+ errors: validationErrors
39
+ };
40
+ }
41
+ }
42
+ // Build journal entry
43
+ const journalEntry = await this.buildJournalEntry(invoice, rules, options);
44
+ // Create booking info
45
+ const bookingInfo = {
46
+ journalEntryId: journalEntry.id,
47
+ transactionIds: journalEntry.transactionIds || [],
48
+ bookedAt: new Date(),
49
+ bookedBy: 'system',
50
+ bookingRules: {
51
+ vendorAccount: rules.vendorControlAccount,
52
+ customerAccount: rules.customerControlAccount,
53
+ expenseAccounts: this.getUsedExpenseAccounts(invoice, rules),
54
+ revenueAccounts: this.getUsedRevenueAccounts(invoice, rules),
55
+ vatAccounts: this.getUsedVATAccounts(invoice, rules)
56
+ },
57
+ confidence,
58
+ autoBooked: options?.autoBook || false
59
+ };
60
+ // Post the journal entry
61
+ // TODO: When MongoDB transactions are available, wrap this in a transaction
62
+ // Example: await db.withTransaction(async (session) => { ... })
63
+ try {
64
+ await journalEntry.validate();
65
+ await journalEntry.post();
66
+ // Mark invoice as posted if we have a reference to it
67
+ if (invoice.status !== 'posted') {
68
+ invoice.status = 'posted';
69
+ }
70
+ }
71
+ catch (postError) {
72
+ this.logger.log('error', `Failed to post journal entry: ${postError}`);
73
+ throw postError; // Re-throw to trigger rollback when transactions are available
74
+ }
75
+ return {
76
+ success: true,
77
+ journalEntry,
78
+ bookingInfo,
79
+ confidence,
80
+ warnings: this.generateWarnings(invoice, rules)
81
+ };
82
+ }
83
+ catch (error) {
84
+ this.logger.log('error', `Failed to book invoice: ${error}`);
85
+ return {
86
+ success: false,
87
+ confidence: 0,
88
+ errors: [`Booking failed: ${error.message}`]
89
+ };
90
+ }
91
+ }
92
+ /**
93
+ * Build journal entry from invoice
94
+ */
95
+ async buildJournalEntry(invoice, rules, options) {
96
+ const lines = [];
97
+ const isInbound = invoice.direction === 'inbound';
98
+ const isCredit = invoice.invoiceTypeCode === '381'; // Credit note
99
+ // Determine if we need to reverse the normal booking direction
100
+ const reverseDirection = isCredit;
101
+ if (isInbound) {
102
+ // Inbound invoice (AP)
103
+ lines.push(...this.buildAPEntry(invoice, rules, reverseDirection));
104
+ }
105
+ else {
106
+ // Outbound invoice (AR)
107
+ lines.push(...this.buildAREntry(invoice, rules, reverseDirection));
108
+ }
109
+ // Create journal entry
110
+ const journalData = {
111
+ date: options?.bookingDate || invoice.issueDate,
112
+ description: this.buildDescription(invoice),
113
+ reference: options?.bookingReference || invoice.invoiceNumber,
114
+ lines,
115
+ skrType: this.skrType
116
+ };
117
+ const journalEntry = new JournalEntry(journalData);
118
+ return journalEntry;
119
+ }
120
+ /**
121
+ * Build AP (Accounts Payable) journal entry lines
122
+ */
123
+ buildAPEntry(invoice, rules, reverseDirection) {
124
+ const lines = [];
125
+ // Group lines by account
126
+ const accountGroups = this.groupLinesByAccount(invoice, rules);
127
+ // Create expense/asset entries
128
+ for (const [accountNumber, group] of Object.entries(accountGroups)) {
129
+ const amount = group.reduce((sum, line) => sum + line.netAmount, 0);
130
+ if (reverseDirection) {
131
+ // Credit note: credit expense account
132
+ lines.push({
133
+ accountNumber,
134
+ credit: Math.abs(amount),
135
+ description: this.getAccountDescription(accountNumber, group)
136
+ });
137
+ }
138
+ else {
139
+ // Regular invoice: debit expense account
140
+ lines.push({
141
+ accountNumber,
142
+ debit: Math.abs(amount),
143
+ description: this.getAccountDescription(accountNumber, group)
144
+ });
145
+ }
146
+ }
147
+ // Create VAT entries
148
+ const vatLines = this.buildVATLines(invoice, rules, 'input', reverseDirection);
149
+ lines.push(...vatLines);
150
+ // Create vendor control account entry
151
+ const controlAccount = this.mapper.getControlAccount(invoice, rules);
152
+ const totalAmount = Math.abs(invoice.payableAmount);
153
+ if (reverseDirection) {
154
+ // Credit note: debit vendor account
155
+ lines.push({
156
+ accountNumber: controlAccount,
157
+ debit: totalAmount,
158
+ description: `${invoice.supplier.name} - Credit Note ${invoice.invoiceNumber}`
159
+ });
160
+ }
161
+ else {
162
+ // Regular invoice: credit vendor account
163
+ lines.push({
164
+ accountNumber: controlAccount,
165
+ credit: totalAmount,
166
+ description: `${invoice.supplier.name} - Invoice ${invoice.invoiceNumber}`
167
+ });
168
+ }
169
+ return lines;
170
+ }
171
+ /**
172
+ * Build AR (Accounts Receivable) journal entry lines
173
+ */
174
+ buildAREntry(invoice, rules, reverseDirection) {
175
+ const lines = [];
176
+ // Group lines by account
177
+ const accountGroups = this.groupLinesByAccount(invoice, rules);
178
+ // Create revenue entries
179
+ for (const [accountNumber, group] of Object.entries(accountGroups)) {
180
+ const amount = group.reduce((sum, line) => sum + line.netAmount, 0);
181
+ if (reverseDirection) {
182
+ // Credit note: debit revenue account
183
+ lines.push({
184
+ accountNumber,
185
+ debit: Math.abs(amount),
186
+ description: this.getAccountDescription(accountNumber, group)
187
+ });
188
+ }
189
+ else {
190
+ // Regular invoice: credit revenue account
191
+ lines.push({
192
+ accountNumber,
193
+ credit: Math.abs(amount),
194
+ description: this.getAccountDescription(accountNumber, group)
195
+ });
196
+ }
197
+ }
198
+ // Create VAT entries
199
+ const vatLines = this.buildVATLines(invoice, rules, 'output', reverseDirection);
200
+ lines.push(...vatLines);
201
+ // Create customer control account entry
202
+ const controlAccount = this.mapper.getControlAccount(invoice, rules);
203
+ const totalAmount = Math.abs(invoice.payableAmount);
204
+ if (reverseDirection) {
205
+ // Credit note: credit customer account
206
+ lines.push({
207
+ accountNumber: controlAccount,
208
+ credit: totalAmount,
209
+ description: `${invoice.customer.name} - Credit Note ${invoice.invoiceNumber}`
210
+ });
211
+ }
212
+ else {
213
+ // Regular invoice: debit customer account
214
+ lines.push({
215
+ accountNumber: controlAccount,
216
+ debit: totalAmount,
217
+ description: `${invoice.customer.name} - Invoice ${invoice.invoiceNumber}`
218
+ });
219
+ }
220
+ return lines;
221
+ }
222
+ /**
223
+ * Build VAT lines
224
+ */
225
+ buildVATLines(invoice, rules, direction, reverseDirection) {
226
+ const lines = [];
227
+ const taxScenario = invoice.taxScenario || 'domestic_taxed';
228
+ // Handle reverse charge specially
229
+ if (taxScenario === 'reverse_charge') {
230
+ return this.buildReverseChargeVATLines(invoice, rules);
231
+ }
232
+ // Standard VAT booking
233
+ for (const vatBreak of invoice.vatBreakdown) {
234
+ if (vatBreak.taxAmount === 0)
235
+ continue;
236
+ const vatAccount = this.mapper.getVATAccount(vatBreak.vatCategory, direction, taxScenario);
237
+ const amount = Math.abs(vatBreak.taxAmount);
238
+ const description = `VAT ${vatBreak.vatCategory.rate}%`;
239
+ if (direction === 'input') {
240
+ // Input VAT (Vorsteuer)
241
+ if (reverseDirection) {
242
+ lines.push({ accountNumber: vatAccount, credit: amount, description });
243
+ }
244
+ else {
245
+ lines.push({ accountNumber: vatAccount, debit: amount, description });
246
+ }
247
+ }
248
+ else {
249
+ // Output VAT (Umsatzsteuer)
250
+ if (reverseDirection) {
251
+ lines.push({ accountNumber: vatAccount, debit: amount, description });
252
+ }
253
+ else {
254
+ lines.push({ accountNumber: vatAccount, credit: amount, description });
255
+ }
256
+ }
257
+ }
258
+ return lines;
259
+ }
260
+ /**
261
+ * Calculate VAT amount from taxable amount and rate
262
+ */
263
+ calculateVAT(taxableAmount, rate) {
264
+ return Math.round(taxableAmount * rate / 100 * 100) / 100; // Round to 2 decimals
265
+ }
266
+ /**
267
+ * Calculate effective VAT rate for the invoice (weighted average)
268
+ */
269
+ calculateEffectiveVATRate(invoice) {
270
+ const totalTaxable = invoice.vatBreakdown.reduce((sum, vb) => sum + vb.taxableAmount, 0);
271
+ if (totalTaxable === 0) {
272
+ return 19; // Default to standard German VAT rate
273
+ }
274
+ // Calculate weighted average VAT rate
275
+ const weightedRate = invoice.vatBreakdown.reduce((sum, vb) => {
276
+ return sum + (vb.vatCategory.rate * vb.taxableAmount);
277
+ }, 0);
278
+ return Math.round(weightedRate / totalTaxable * 100) / 100;
279
+ }
280
+ /**
281
+ * Build reverse charge VAT lines (§13b UStG)
282
+ */
283
+ buildReverseChargeVATLines(invoice, rules) {
284
+ const lines = [];
285
+ // For reverse charge, we book both input and output VAT
286
+ for (const vatBreak of invoice.vatBreakdown) {
287
+ // For reverse charge, calculate VAT if not provided
288
+ const amount = vatBreak.taxAmount > 0
289
+ ? Math.abs(vatBreak.taxAmount)
290
+ : this.calculateVAT(Math.abs(vatBreak.taxableAmount), vatBreak.vatCategory.rate);
291
+ // Input VAT (deductible)
292
+ const inputVATAccount = this.mapper.getVATAccount(vatBreak.vatCategory, 'input', 'reverse_charge');
293
+ // Output VAT (payable)
294
+ const outputVATAccount = this.mapper.getVATAccount(vatBreak.vatCategory, 'output', 'reverse_charge');
295
+ lines.push({
296
+ accountNumber: inputVATAccount,
297
+ debit: amount,
298
+ description: `Reverse charge input VAT ${vatBreak.vatCategory.rate}%`
299
+ }, {
300
+ accountNumber: outputVATAccount,
301
+ credit: amount,
302
+ description: `Reverse charge output VAT ${vatBreak.vatCategory.rate}%`
303
+ });
304
+ }
305
+ return lines;
306
+ }
307
+ /**
308
+ * Group invoice lines by account
309
+ */
310
+ groupLinesByAccount(invoice, rules) {
311
+ const groups = {};
312
+ for (const line of invoice.lines) {
313
+ const account = this.mapper.mapInvoiceLineToAccount(line, invoice, rules);
314
+ if (!groups[account]) {
315
+ groups[account] = [];
316
+ }
317
+ groups[account].push(line);
318
+ }
319
+ return groups;
320
+ }
321
+ /**
322
+ * Book payment for an invoice
323
+ */
324
+ async bookPayment(invoice, payment, rules) {
325
+ try {
326
+ const lines = [];
327
+ const isInbound = invoice.direction === 'inbound';
328
+ const controlAccount = this.mapper.getControlAccount(invoice, rules);
329
+ // Check for skonto
330
+ const skontoAmount = payment.skontoTaken || 0;
331
+ const paymentAmount = payment.amount;
332
+ const fullAmount = paymentAmount + skontoAmount;
333
+ if (isInbound) {
334
+ // Payment for vendor invoice
335
+ lines.push({
336
+ accountNumber: controlAccount,
337
+ debit: fullAmount,
338
+ description: `Payment to ${invoice.supplier.name}`
339
+ }, {
340
+ accountNumber: '1000', // Bank account (would be configurable)
341
+ credit: paymentAmount,
342
+ description: `Bank payment ${payment.endToEndId || payment.paymentId}`
343
+ });
344
+ // Book skonto if taken
345
+ if (skontoAmount > 0) {
346
+ const skontoAccounts = this.mapper.getSkontoAccounts(invoice);
347
+ lines.push({
348
+ accountNumber: skontoAccounts.skontoAccount,
349
+ credit: skontoAmount,
350
+ description: `Skonto received`
351
+ });
352
+ // VAT correction for skonto
353
+ if (rules.skontoMethod === 'gross') {
354
+ const effectiveRate = this.calculateEffectiveVATRate(invoice);
355
+ const vatCorrection = Math.round(skontoAmount * effectiveRate / (100 + effectiveRate) * 100) / 100;
356
+ lines.push({
357
+ accountNumber: skontoAccounts.vatCorrectionAccount,
358
+ credit: vatCorrection,
359
+ description: `Skonto VAT correction`
360
+ });
361
+ }
362
+ }
363
+ }
364
+ else {
365
+ // Payment from customer
366
+ lines.push({
367
+ accountNumber: '1000', // Bank account
368
+ debit: paymentAmount,
369
+ description: `Payment from ${invoice.customer.name}`
370
+ }, {
371
+ accountNumber: controlAccount,
372
+ credit: fullAmount,
373
+ description: `Customer payment ${payment.endToEndId || payment.paymentId}`
374
+ });
375
+ // Book skonto if granted
376
+ if (skontoAmount > 0) {
377
+ const skontoAccounts = this.mapper.getSkontoAccounts(invoice);
378
+ lines.push({
379
+ accountNumber: skontoAccounts.skontoAccount,
380
+ debit: skontoAmount,
381
+ description: `Skonto granted`
382
+ });
383
+ // VAT correction for skonto
384
+ if (rules.skontoMethod === 'gross') {
385
+ const effectiveRate = this.calculateEffectiveVATRate(invoice);
386
+ const vatCorrection = Math.round(skontoAmount * effectiveRate / (100 + effectiveRate) * 100) / 100;
387
+ lines.push({
388
+ accountNumber: skontoAccounts.vatCorrectionAccount,
389
+ debit: vatCorrection,
390
+ description: `Skonto VAT correction`
391
+ });
392
+ }
393
+ }
394
+ }
395
+ // Create journal entry for payment
396
+ const journalData = {
397
+ date: payment.paymentDate,
398
+ description: `Payment for invoice ${invoice.invoiceNumber}`,
399
+ reference: payment.endToEndId || payment.remittanceInfo || payment.paymentId,
400
+ lines,
401
+ skrType: this.skrType
402
+ };
403
+ const journalEntry = new JournalEntry(journalData);
404
+ await journalEntry.validate();
405
+ await journalEntry.post();
406
+ return {
407
+ success: true,
408
+ journalEntry,
409
+ confidence: 100
410
+ };
411
+ }
412
+ catch (error) {
413
+ this.logger.log('error', `Failed to book payment: ${error}`);
414
+ return {
415
+ success: false,
416
+ confidence: 0,
417
+ errors: [`Payment booking failed: ${error.message}`]
418
+ };
419
+ }
420
+ }
421
+ /**
422
+ * Validate invoice before booking
423
+ */
424
+ validateInvoice(invoice) {
425
+ const errors = [];
426
+ // Check required fields
427
+ if (!invoice.invoiceNumber) {
428
+ errors.push('Invoice number is required');
429
+ }
430
+ if (!invoice.issueDate) {
431
+ errors.push('Issue date is required');
432
+ }
433
+ if (!invoice.supplier || !invoice.supplier.name) {
434
+ errors.push('Supplier information is required');
435
+ }
436
+ if (!invoice.customer || !invoice.customer.name) {
437
+ errors.push('Customer information is required');
438
+ }
439
+ if (invoice.lines.length === 0) {
440
+ errors.push('Invoice must have at least one line item');
441
+ }
442
+ // Validate amounts
443
+ const calculatedNet = invoice.lines.reduce((sum, line) => sum + line.netAmount, 0);
444
+ const tolerance = 0.01;
445
+ if (Math.abs(calculatedNet - invoice.lineNetAmount) > tolerance) {
446
+ errors.push(`Line net amount mismatch: calculated ${calculatedNet}, stated ${invoice.lineNetAmount}`);
447
+ }
448
+ // Validate VAT
449
+ const calculatedVAT = invoice.vatBreakdown.reduce((sum, vb) => sum + vb.taxAmount, 0);
450
+ if (Math.abs(calculatedVAT - invoice.totalVATAmount) > tolerance) {
451
+ errors.push(`VAT amount mismatch: calculated ${calculatedVAT}, stated ${invoice.totalVATAmount}`);
452
+ }
453
+ // Validate total
454
+ const calculatedTotal = invoice.taxExclusiveAmount + invoice.totalVATAmount;
455
+ if (Math.abs(calculatedTotal - invoice.taxInclusiveAmount) > tolerance) {
456
+ errors.push(`Total amount mismatch: calculated ${calculatedTotal}, stated ${invoice.taxInclusiveAmount}`);
457
+ }
458
+ return errors;
459
+ }
460
+ /**
461
+ * Generate warnings for the booking
462
+ */
463
+ generateWarnings(invoice, rules) {
464
+ const warnings = [];
465
+ // Warn about default account usage
466
+ const hasDefaultAccounts = invoice.lines.some(line => !line.accountNumber && !line.productCode);
467
+ if (hasDefaultAccounts) {
468
+ warnings.push('Some lines are using default expense/revenue accounts');
469
+ }
470
+ // Warn about mixed VAT rates
471
+ if (invoice.vatBreakdown.length > 1) {
472
+ warnings.push('Invoice contains mixed VAT rates');
473
+ }
474
+ // Warn about reverse charge
475
+ if (invoice.taxScenario === 'reverse_charge') {
476
+ warnings.push('Reverse charge procedure applied - verify VAT treatment');
477
+ }
478
+ // Warn about credit notes
479
+ if (invoice.invoiceTypeCode === '381') {
480
+ warnings.push('This is a credit note - amounts will be reversed');
481
+ }
482
+ // Warn about foreign currency
483
+ if (invoice.currencyCode !== 'EUR') {
484
+ warnings.push(`Invoice is in foreign currency: ${invoice.currencyCode}`);
485
+ }
486
+ return warnings;
487
+ }
488
+ /**
489
+ * Build description for journal entry
490
+ */
491
+ buildDescription(invoice) {
492
+ const type = invoice.invoiceTypeCode === '381' ? 'Credit Note' : 'Invoice';
493
+ const party = invoice.direction === 'inbound'
494
+ ? invoice.supplier.name
495
+ : invoice.customer.name;
496
+ return `${type} ${invoice.invoiceNumber} - ${party}`;
497
+ }
498
+ /**
499
+ * Get account description for a group of lines
500
+ */
501
+ getAccountDescription(accountNumber, lines) {
502
+ if (lines.length === 1) {
503
+ return lines[0].description;
504
+ }
505
+ return `${this.mapper.getAccountDescription(accountNumber)} (${lines.length} items)`;
506
+ }
507
+ /**
508
+ * Get used expense accounts
509
+ */
510
+ getUsedExpenseAccounts(invoice, rules) {
511
+ if (invoice.direction !== 'inbound')
512
+ return [];
513
+ const accounts = new Set();
514
+ for (const line of invoice.lines) {
515
+ const account = this.mapper.mapInvoiceLineToAccount(line, invoice, rules);
516
+ accounts.add(account);
517
+ }
518
+ return Array.from(accounts);
519
+ }
520
+ /**
521
+ * Get used revenue accounts
522
+ */
523
+ getUsedRevenueAccounts(invoice, rules) {
524
+ if (invoice.direction !== 'outbound')
525
+ return [];
526
+ const accounts = new Set();
527
+ for (const line of invoice.lines) {
528
+ const account = this.mapper.mapInvoiceLineToAccount(line, invoice, rules);
529
+ accounts.add(account);
530
+ }
531
+ return Array.from(accounts);
532
+ }
533
+ /**
534
+ * Get used VAT accounts
535
+ */
536
+ getUsedVATAccounts(invoice, rules) {
537
+ const accounts = new Set();
538
+ const direction = invoice.direction === 'inbound' ? 'input' : 'output';
539
+ const taxScenario = invoice.taxScenario || 'domestic_taxed';
540
+ for (const vatBreak of invoice.vatBreakdown) {
541
+ const account = this.mapper.getVATAccount(vatBreak.vatCategory, direction, taxScenario);
542
+ accounts.add(account);
543
+ }
544
+ // Add reverse charge accounts if applicable
545
+ if (taxScenario === 'reverse_charge') {
546
+ for (const vatBreak of invoice.vatBreakdown) {
547
+ const inputAccount = this.mapper.getVATAccount(vatBreak.vatCategory, 'input', 'reverse_charge');
548
+ const outputAccount = this.mapper.getVATAccount(vatBreak.vatCategory, 'output', 'reverse_charge');
549
+ accounts.add(inputAccount);
550
+ accounts.add(outputAccount);
551
+ }
552
+ }
553
+ return Array.from(accounts);
554
+ }
555
+ }
556
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2tyLmludm9pY2UuYm9va2luZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3Nrci5pbnZvaWNlLmJvb2tpbmcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFDeEMsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQzdELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBa0MzRDs7O0dBR0c7QUFDSCxNQUFNLE9BQU8sb0JBQW9CO0lBSy9CLFlBQVksT0FBaUI7UUFDM0IsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7UUFDdkIsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzVDLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxPQUFPLENBQUMsUUFBUSxDQUFDLFVBQVUsRUFBRSxDQUFDO0lBQ2xELENBQUM7SUFFRDs7T0FFRztJQUNJLEtBQUssQ0FBQyxXQUFXLENBQ3RCLE9BQWlCLEVBQ2pCLFlBQXFDLEVBQ3JDLE9BQXlCO1FBRXpCLElBQUksQ0FBQztZQUNILDZCQUE2QjtZQUM3QixNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLGVBQWUsQ0FBQyxPQUFPLEVBQUUsWUFBWSxDQUFDLENBQUM7WUFFakUsdUJBQXVCO1lBQ3ZCLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsbUJBQW1CLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBRW5FLG1DQUFtQztZQUNuQyxJQUFJLE9BQU8sRUFBRSxRQUFRLElBQUksVUFBVSxHQUFHLENBQUMsT0FBTyxDQUFDLG1CQUFtQixJQUFJLEVBQUUsQ0FBQyxFQUFFLENBQUM7Z0JBQzFFLE9BQU87b0JBQ0wsT0FBTyxFQUFFLEtBQUs7b0JBQ2QsVUFBVTtvQkFDVixRQUFRLEVBQUUsQ0FB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