UNPKG

@fin.cx/skr

Version:

SKR03 and SKR04 German accounting standards for double-entry bookkeeping

556 lines 46 kB
import * as plugins from './plugins.js'; import { JournalEntry } from './skr.classes.journalentry.js'; import { SKRInvoiceMapper } from './skr.invoice.mapper.js'; /** * Automatic booking engine for invoices * Creates journal entries from invoice data based on SKR mapping rules */ export class InvoiceBookingEngine { constructor(skrType) { this.skrType = skrType; this.mapper = new SKRInvoiceMapper(skrType); this.logger = new plugins.smartlog.ConsoleLog(); } /** * Book an invoice to the ledger */ async bookInvoice(invoice, bookingRules, options) { try { // Get complete booking rules const rules = this.mapper.mapInvoiceToSKR(invoice, bookingRules); // Calculate confidence const confidence = this.mapper.calculateConfidence(invoice, rules); // Check if auto-booking is allowed if (options?.autoBook && confidence < (options.confidenceThreshold || 80)) { return { success: false, confidence, warnings: [`Confidence score ${confidence}% is below threshold ${options.confidenceThreshold || 80}%`] }; } // Validate invoice before booking if (!options?.skipValidation) { const validationErrors = this.validateInvoice(invoice); if (validationErrors.length > 0) { return { success: false, confidence, errors: validationErrors }; } } // Build journal entry const journalEntry = await this.buildJournalEntry(invoice, rules, options); // Create booking info const bookingInfo = { journalEntryId: journalEntry.id, transactionIds: journalEntry.transactionIds || [], bookedAt: new Date(), bookedBy: 'system', bookingRules: { vendorAccount: rules.vendorControlAccount, customerAccount: rules.customerControlAccount, expenseAccounts: this.getUsedExpenseAccounts(invoice, rules), revenueAccounts: this.getUsedRevenueAccounts(invoice, rules), vatAccounts: this.getUsedVATAccounts(invoice, rules) }, confidence, autoBooked: options?.autoBook || false }; // Post the journal entry // TODO: When MongoDB transactions are available, wrap this in a transaction // Example: await db.withTransaction(async (session) => { ... }) try { await journalEntry.validate(); await journalEntry.post(); // Mark invoice as posted if we have a reference to it if (invoice.status !== 'posted') { invoice.status = 'posted'; } } catch (postError) { this.logger.log('error', `Failed to post journal entry: ${postError}`); throw postError; // Re-throw to trigger rollback when transactions are available } return { success: true, journalEntry, bookingInfo, confidence, warnings: this.generateWarnings(invoice, rules) }; } catch (error) { this.logger.log('error', `Failed to book invoice: ${error}`); return { success: false, confidence: 0, errors: [`Booking failed: ${error.message}`] }; } } /** * Build journal entry from invoice */ async buildJournalEntry(invoice, rules, options) { const lines = []; const isInbound = invoice.direction === 'inbound'; const isCredit = invoice.invoiceTypeCode === '381'; // Credit note // Determine if we need to reverse the normal booking direction const reverseDirection = isCredit; if (isInbound) { // Inbound invoice (AP) lines.push(...this.buildAPEntry(invoice, rules, reverseDirection)); } else { // Outbound invoice (AR) lines.push(...this.buildAREntry(invoice, rules, reverseDirection)); } // Create journal entry const journalData = { date: options?.bookingDate || invoice.issueDate, description: this.buildDescription(invoice), reference: options?.bookingReference || invoice.invoiceNumber, lines, skrType: this.skrType }; const journalEntry = new JournalEntry(journalData); return journalEntry; } /** * Build AP (Accounts Payable) journal entry lines */ buildAPEntry(invoice, rules, reverseDirection) { const lines = []; // Group lines by account const accountGroups = this.groupLinesByAccount(invoice, rules); // Create expense/asset entries for (const [accountNumber, group] of Object.entries(accountGroups)) { const amount = group.reduce((sum, line) => sum + line.netAmount, 0); if (reverseDirection) { // Credit note: credit expense account lines.push({ accountNumber, credit: Math.abs(amount), description: this.getAccountDescription(accountNumber, group) }); } else { // Regular invoice: debit expense account lines.push({ accountNumber, debit: Math.abs(amount), description: this.getAccountDescription(accountNumber, group) }); } } // Create VAT entries const vatLines = this.buildVATLines(invoice, rules, 'input', reverseDirection); lines.push(...vatLines); // Create vendor control account entry const controlAccount = this.mapper.getControlAccount(invoice, rules); const totalAmount = Math.abs(invoice.payableAmount); if (reverseDirection) { // Credit note: debit vendor account lines.push({ accountNumber: controlAccount, debit: totalAmount, description: `${invoice.supplier.name} - Credit Note ${invoice.invoiceNumber}` }); } else { // Regular invoice: credit vendor account lines.push({ accountNumber: controlAccount, credit: totalAmount, description: `${invoice.supplier.name} - Invoice ${invoice.invoiceNumber}` }); } return lines; } /** * Build AR (Accounts Receivable) journal entry lines */ buildAREntry(invoice, rules, reverseDirection) { const lines = []; // Group lines by account const accountGroups = this.groupLinesByAccount(invoice, rules); // Create revenue entries for (const [accountNumber, group] of Object.entries(accountGroups)) { const amount = group.reduce((sum, line) => sum + line.netAmount, 0); if (reverseDirection) { // Credit note: debit revenue account lines.push({ accountNumber, debit: Math.abs(amount), description: this.getAccountDescription(accountNumber, group) }); } else { // Regular invoice: credit revenue account lines.push({ accountNumber, credit: Math.abs(amount), description: this.getAccountDescription(accountNumber, group) }); } } // Create VAT entries const vatLines = this.buildVATLines(invoice, rules, 'output', reverseDirection); lines.push(...vatLines); // Create customer control account entry const controlAccount = this.mapper.getControlAccount(invoice, rules); const totalAmount = Math.abs(invoice.payableAmount); if (reverseDirection) { // Credit note: credit customer account lines.push({ accountNumber: controlAccount, credit: totalAmount, description: `${invoice.customer.name} - Credit Note ${invoice.invoiceNumber}` }); } else { // Regular invoice: debit customer account lines.push({ accountNumber: controlAccount, debit: totalAmount, description: `${invoice.customer.name} - Invoice ${invoice.invoiceNumber}` }); } return lines; } /** * Build VAT lines */ buildVATLines(invoice, rules, direction, reverseDirection) { const lines = []; const taxScenario = invoice.taxScenario || 'domestic_taxed'; // Handle reverse charge specially if (taxScenario === 'reverse_charge') { return this.buildReverseChargeVATLines(invoice, rules); } // Standard VAT booking for (const vatBreak of invoice.vatBreakdown) { if (vatBreak.taxAmount === 0) continue; const vatAccount = this.mapper.getVATAccount(vatBreak.vatCategory, direction, taxScenario); const amount = Math.abs(vatBreak.taxAmount); const description = `VAT ${vatBreak.vatCategory.rate}%`; if (direction === 'input') { // Input VAT (Vorsteuer) if (reverseDirection) { lines.push({ accountNumber: vatAccount, credit: amount, description }); } else { lines.push({ accountNumber: vatAccount, debit: amount, description }); } } else { // Output VAT (Umsatzsteuer) if (reverseDirection) { lines.push({ accountNumber: vatAccount, debit: amount, description }); } else { lines.push({ accountNumber: vatAccount, credit: amount, description }); } } } return lines; } /** * Calculate VAT amount from taxable amount and rate */ calculateVAT(taxableAmount, rate) { return Math.round(taxableAmount * rate / 100 * 100) / 100; // Round to 2 decimals } /** * Calculate effective VAT rate for the invoice (weighted average) */ calculateEffectiveVATRate(invoice) { const totalTaxable = invoice.vatBreakdown.reduce((sum, vb) => sum + vb.taxableAmount, 0); if (totalTaxable === 0) { return 19; // Default to standard German VAT rate } // Calculate weighted average VAT rate const weightedRate = invoice.vatBreakdown.reduce((sum, vb) => { return sum + (vb.vatCategory.rate * vb.taxableAmount); }, 0); return Math.round(weightedRate / totalTaxable * 100) / 100; } /** * Build reverse charge VAT lines (§13b UStG) */ buildReverseChargeVATLines(invoice, rules) { const lines = []; // For reverse charge, we book both input and output VAT for (const vatBreak of invoice.vatBreakdown) { // For reverse charge, calculate VAT if not provided const amount = vatBreak.taxAmount > 0 ? Math.abs(vatBreak.taxAmount) : this.calculateVAT(Math.abs(vatBreak.taxableAmount), vatBreak.vatCategory.rate); // Input VAT (deductible) const inputVATAccount = this.mapper.getVATAccount(vatBreak.vatCategory, 'input', 'reverse_charge'); // Output VAT (payable) const outputVATAccount = this.mapper.getVATAccount(vatBreak.vatCategory, 'output', 'reverse_charge'); lines.push({ accountNumber: inputVATAccount, debit: amount, description: `Reverse charge input VAT ${vatBreak.vatCategory.rate}%` }, { accountNumber: outputVATAccount, credit: amount, description: `Reverse charge output VAT ${vatBreak.vatCategory.rate}%` }); } return lines; } /** * Group invoice lines by account */ groupLinesByAccount(invoice, rules) { const groups = {}; for (const line of invoice.lines) { const account = this.mapper.mapInvoiceLineToAccount(line, invoice, rules); if (!groups[account]) { groups[account] = []; } groups[account].push(line); } return groups; } /** * Book payment for an invoice */ async bookPayment(invoice, payment, rules) { try { const lines = []; const isInbound = invoice.direction === 'inbound'; const controlAccount = this.mapper.getControlAccount(invoice, rules); // Check for skonto const skontoAmount = payment.skontoTaken || 0; const paymentAmount = payment.amount; const fullAmount = paymentAmount + skontoAmount; if (isInbound) { // Payment for vendor invoice lines.push({ accountNumber: controlAccount, debit: fullAmount, description: `Payment to ${invoice.supplier.name}` }, { accountNumber: '1000', // Bank account (would be configurable) credit: paymentAmount, description: `Bank payment ${payment.endToEndId || payment.paymentId}` }); // Book skonto if taken if (skontoAmount > 0) { const skontoAccounts = this.mapper.getSkontoAccounts(invoice); lines.push({ accountNumber: skontoAccounts.skontoAccount, credit: skontoAmount, description: `Skonto received` }); // VAT correction for skonto if (rules.skontoMethod === 'gross') { const effectiveRate = this.calculateEffectiveVATRate(invoice); const vatCorrection = Math.round(skontoAmount * effectiveRate / (100 + effectiveRate) * 100) / 100; lines.push({ accountNumber: skontoAccounts.vatCorrectionAccount, credit: vatCorrection, description: `Skonto VAT correction` }); } } } else { // Payment from customer lines.push({ accountNumber: '1000', // Bank account debit: paymentAmount, description: `Payment from ${invoice.customer.name}` }, { accountNumber: controlAccount, credit: fullAmount, description: `Customer payment ${payment.endToEndId || payment.paymentId}` }); // Book skonto if granted if (skontoAmount > 0) { const skontoAccounts = this.mapper.getSkontoAccounts(invoice); lines.push({ accountNumber: skontoAccounts.skontoAccount, debit: skontoAmount, description: `Skonto granted` }); // VAT correction for skonto if (rules.skontoMethod === 'gross') { const effectiveRate = this.calculateEffectiveVATRate(invoice); const vatCorrection = Math.round(skontoAmount * effectiveRate / (100 + effectiveRate) * 100) / 100; lines.push({ accountNumber: skontoAccounts.vatCorrectionAccount, debit: vatCorrection, description: `Skonto VAT correction` }); } } } // Create journal entry for payment const journalData = { date: payment.paymentDate, description: `Payment for invoice ${invoice.invoiceNumber}`, reference: payment.endToEndId || payment.remittanceInfo || payment.paymentId, lines, skrType: this.skrType }; const journalEntry = new JournalEntry(journalData); await journalEntry.validate(); await journalEntry.post(); return { success: true, journalEntry, confidence: 100 }; } catch (error) { this.logger.log('error', `Failed to book payment: ${error}`); return { success: false, confidence: 0, errors: [`Payment booking failed: ${error.message}`] }; } } /** * Validate invoice before booking */ validateInvoice(invoice) { const errors = []; // Check required fields if (!invoice.invoiceNumber) { errors.push('Invoice number is required'); } if (!invoice.issueDate) { errors.push('Issue date is required'); } if (!invoice.supplier || !invoice.supplier.name) { errors.push('Supplier information is required'); } if (!invoice.customer || !invoice.customer.name) { errors.push('Customer information is required'); } if (invoice.lines.length === 0) { errors.push('Invoice must have at least one line item'); } // Validate amounts const calculatedNet = invoice.lines.reduce((sum, line) => sum + line.netAmount, 0); const tolerance = 0.01; if (Math.abs(calculatedNet - invoice.lineNetAmount) > tolerance) { errors.push(`Line net amount mismatch: calculated ${calculatedNet}, stated ${invoice.lineNetAmount}`); } // Validate VAT const calculatedVAT = invoice.vatBreakdown.reduce((sum, vb) => sum + vb.taxAmount, 0); if (Math.abs(calculatedVAT - invoice.totalVATAmount) > tolerance) { errors.push(`VAT amount mismatch: calculated ${calculatedVAT}, stated ${invoice.totalVATAmount}`); } // Validate total const calculatedTotal = invoice.taxExclusiveAmount + invoice.totalVATAmount; if (Math.abs(calculatedTotal - invoice.taxInclusiveAmount) > tolerance) { errors.push(`Total amount mismatch: calculated ${calculatedTotal}, stated ${invoice.taxInclusiveAmount}`); } return errors; } /** * Generate warnings for the booking */ generateWarnings(invoice, rules) { const warnings = []; // Warn about default account usage const hasDefaultAccounts = invoice.lines.some(line => !line.accountNumber && !line.productCode); if (hasDefaultAccounts) { warnings.push('Some lines are using default expense/revenue accounts'); } // Warn about mixed VAT rates if (invoice.vatBreakdown.length > 1) { warnings.push('Invoice contains mixed VAT rates'); } // Warn about reverse charge if (invoice.taxScenario === 'reverse_charge') { warnings.push('Reverse charge procedure applied - verify VAT treatment'); } // Warn about credit notes if (invoice.invoiceTypeCode === '381') { warnings.push('This is a credit note - amounts will be reversed'); } // Warn about foreign currency if (invoice.currencyCode !== 'EUR') { warnings.push(`Invoice is in foreign currency: ${invoice.currencyCode}`); } return warnings; } /** * Build description for journal entry */ buildDescription(invoice) { const type = invoice.invoiceTypeCode === '381' ? 'Credit Note' : 'Invoice'; const party = invoice.direction === 'inbound' ? invoice.supplier.name : invoice.customer.name; return `${type} ${invoice.invoiceNumber} - ${party}`; } /** * Get account description for a group of lines */ getAccountDescription(accountNumber, lines) { if (lines.length === 1) { return lines[0].description; } return `${this.mapper.getAccountDescription(accountNumber)} (${lines.length} items)`; } /** * Get used expense accounts */ getUsedExpenseAccounts(invoice, rules) { if (invoice.direction !== 'inbound') return []; const accounts = new Set(); for (const line of invoice.lines) { const account = this.mapper.mapInvoiceLineToAccount(line, invoice, rules); accounts.add(account); } return Array.from(accounts); } /** * Get used revenue accounts */ getUsedRevenueAccounts(invoice, rules) { if (invoice.direction !== 'outbound') return []; const accounts = new Set(); for (const line of invoice.lines) { const account = this.mapper.mapInvoiceLineToAccount(line, invoice, rules); accounts.add(account); } return Array.from(accounts); } /** * Get used VAT accounts */ getUsedVATAccounts(invoice, rules) { const accounts = new Set(); const direction = invoice.direction === 'inbound' ? 'input' : 'output'; const taxScenario = invoice.taxScenario || 'domestic_taxed'; for (const vatBreak of invoice.vatBreakdown) { const account = this.mapper.getVATAccount(vatBreak.vatCategory, direction, taxScenario); accounts.add(account); } // Add reverse charge accounts if applicable if (taxScenario === 'reverse_charge') { for (const vatBreak of invoice.vatBreakdown) { const inputAccount = this.mapper.getVATAccount(vatBreak.vatCategory, 'input', 'reverse_charge'); const outputAccount = this.mapper.getVATAccount(vatBreak.vatCategory, 'output', 'reverse_charge'); accounts.add(inputAccount); accounts.add(outputAccount); } } return Array.from(accounts); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2tyLmludm9pY2UuYm9va2luZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3Nrci5pbnZvaWNlLmJvb2tpbmcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFDeEMsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQzdELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBa0MzRDs7O0dBR0c7QUFDSCxNQUFNLE9BQU8sb0JBQW9CO0lBSy9CLFlBQVksT0FBaUI7UUFDM0IsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7UUFDdkIsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzVDLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxPQUFPLENBQUMsUUFBUSxDQUFDLFVBQVUsRUFBRSxDQUFDO0lBQ2xELENBQUM7SUFFRDs7T0FFRztJQUNJLEtBQUssQ0FBQyxXQUFXLENBQ3RCLE9BQWlCLEVBQ2pCLFlBQXFDLEVBQ3JDLE9BQXlCO1FBRXpCLElBQUksQ0FBQztZQUNILDZCQUE2QjtZQUM3QixNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLGVBQWUsQ0FBQyxPQUFPLEVBQUUsWUFBWSxDQUFDLENBQUM7WUFFakUsdUJBQXVCO1lBQ3ZCLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsbUJBQW1CLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBRW5FLG1DQUFtQztZQUNuQyxJQUFJLE9BQU8sRUFBRSxRQUFRLElBQUksVUFBVSxHQUFHLENBQUMsT0FBTyxDQUFDLG1CQUFtQixJQUFJLEVBQUUsQ0FBQyxFQUFFLENBQUM7Z0JBQzFFLE9BQU87b0JBQ0wsT0FBTyxFQUFFLEtBQUs7b0JBQ2QsVUFBVTtvQkFDVixRQUFRLEVBQUUsQ0FB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