@fin.cx/skr
Version:
SKR03 and SKR04 German accounting standards for double-entry bookkeeping
476 lines • 39.3 kB
JavaScript
import * as plugins from './plugins.js';
/**
* Adapter for @fin.cx/einvoice library
* Handles parsing, validation, and format conversion of e-invoices
*/
export class InvoiceAdapter {
constructor() {
this.MAX_XML_SIZE = 10 * 1024 * 1024; // 10MB max
this.MAX_PDF_SIZE = 50 * 1024 * 1024; // 50MB max
this.logger = new plugins.smartlog.ConsoleLog();
}
/**
* Parse an invoice from file or buffer
*/
async parseInvoice(file, direction) {
try {
// Validate input size
if (Buffer.isBuffer(file)) {
if (file.length > this.MAX_XML_SIZE) {
throw new Error(`Invoice file too large: ${file.length} bytes (max ${this.MAX_XML_SIZE} bytes)`);
}
}
else if (typeof file === 'string' && file.length > this.MAX_XML_SIZE) {
throw new Error(`Invoice XML too large: ${file.length} characters (max ${this.MAX_XML_SIZE} characters)`);
}
// Parse the invoice using @fin.cx/einvoice
let einvoice;
if (typeof file === 'string') {
einvoice = await plugins.einvoice.EInvoice.fromXml(file);
}
else {
// Convert buffer to string first
const xmlString = file.toString('utf-8');
einvoice = await plugins.einvoice.EInvoice.fromXml(xmlString);
}
// Get detected format
const format = this.mapEInvoiceFormat(einvoice.format || 'xrechnung');
// Validate the invoice (takes ~2.2ms)
const validationResult = await this.validateInvoice(einvoice);
// Extract invoice data
const invoiceData = einvoice.toObject();
// Map to internal invoice model
const invoice = await this.mapToInternalModel(invoiceData, format, direction, validationResult);
// Store original XML content
invoice.xmlContent = einvoice.getXml();
// Calculate content hash
invoice.contentHash = await this.calculateContentHash(invoice.xmlContent);
// Classify tax scenario
invoice.taxScenario = this.classifyTaxScenario(invoice);
return invoice;
}
catch (error) {
this.logger.log('error', `Failed to parse invoice: ${error}`);
throw new Error(`Invoice parsing failed: ${error.message}`);
}
}
/**
* Validate an invoice using multi-level validation
*/
async validateInvoice(einvoice) {
// Perform multi-level validation
const validationResult = await einvoice.validate();
// Parse validation results into our structure
const syntaxResult = {
isValid: validationResult.syntax?.valid !== false,
errors: validationResult.syntax?.errors || [],
warnings: validationResult.syntax?.warnings || []
};
const semanticResult = {
isValid: validationResult.semantic?.valid !== false,
errors: validationResult.semantic?.errors || [],
warnings: validationResult.semantic?.warnings || []
};
const businessResult = {
isValid: validationResult.business?.valid !== false,
errors: validationResult.business?.errors || [],
warnings: validationResult.business?.warnings || []
};
const countryResult = {
isValid: validationResult.country?.valid !== false,
errors: validationResult.country?.errors || [],
warnings: validationResult.country?.warnings || []
};
return {
isValid: syntaxResult.isValid && semanticResult.isValid && businessResult.isValid,
syntax: {
valid: syntaxResult.isValid,
errors: syntaxResult.errors || [],
warnings: syntaxResult.warnings || []
},
semantic: {
valid: semanticResult.isValid,
errors: semanticResult.errors || [],
warnings: semanticResult.warnings || []
},
businessRules: {
valid: businessResult.isValid,
errors: businessResult.errors || [],
warnings: businessResult.warnings || []
},
countrySpecific: {
valid: countryResult.isValid,
errors: countryResult.errors || [],
warnings: countryResult.warnings || []
},
validatedAt: new Date(),
validatorVersion: '5.1.4'
};
}
/**
* Map EN16931 Business Terms to internal invoice model
*/
async mapToInternalModel(businessTerms, format, direction, validationResult) {
const invoice = {
// Identity
id: plugins.smartunique.shortId(),
direction,
format,
// EN16931 Business Terms
invoiceNumber: businessTerms.BT1_InvoiceNumber,
issueDate: new Date(businessTerms.BT2_IssueDate),
invoiceTypeCode: businessTerms.BT3_InvoiceTypeCode || '380',
currencyCode: businessTerms.BT5_CurrencyCode || 'EUR',
taxCurrencyCode: businessTerms.BT6_TaxCurrencyCode,
taxPointDate: businessTerms.BT7_TaxPointDate ? new Date(businessTerms.BT7_TaxPointDate) : undefined,
paymentDueDate: businessTerms.BT9_PaymentDueDate ? new Date(businessTerms.BT9_PaymentDueDate) : undefined,
buyerReference: businessTerms.BT10_BuyerReference,
projectReference: businessTerms.BT11_ProjectReference,
contractReference: businessTerms.BT12_ContractReference,
orderReference: businessTerms.BT13_OrderReference,
sellerOrderReference: businessTerms.BT14_SellerOrderReference,
// Parties
supplier: this.mapParty(businessTerms.BG4_Seller),
customer: this.mapParty(businessTerms.BG7_Buyer),
payee: businessTerms.BG10_Payee ? this.mapParty(businessTerms.BG10_Payee) : undefined,
// Line items
lines: this.mapInvoiceLines(businessTerms.BG25_InvoiceLines || []),
// Allowances and charges
allowances: this.mapAllowancesCharges(businessTerms.BG20_DocumentAllowances || [], true),
charges: this.mapAllowancesCharges(businessTerms.BG21_DocumentCharges || [], false),
// Amounts
lineNetAmount: parseFloat(businessTerms.BT106_SumOfLineNetAmounts || 0),
allowanceTotalAmount: parseFloat(businessTerms.BT107_AllowanceTotalAmount || 0),
chargeTotalAmount: parseFloat(businessTerms.BT108_ChargeTotalAmount || 0),
taxExclusiveAmount: parseFloat(businessTerms.BT109_TaxExclusiveAmount || 0),
taxInclusiveAmount: parseFloat(businessTerms.BT112_TaxInclusiveAmount || 0),
prepaidAmount: parseFloat(businessTerms.BT113_PrepaidAmount || 0),
payableAmount: parseFloat(businessTerms.BT115_PayableAmount || 0),
// VAT breakdown
vatBreakdown: this.mapVATBreakdown(businessTerms.BG23_VATBreakdown || []),
totalVATAmount: parseFloat(businessTerms.BT110_TotalVATAmount || 0),
// Payment
paymentTerms: this.mapPaymentTerms(businessTerms),
paymentMeans: this.mapPaymentMeans(businessTerms.BG16_PaymentInstructions),
// Notes
invoiceNote: businessTerms.BT22_InvoiceNote,
// Processing metadata
status: 'validated',
// Storage (to be filled later)
contentHash: '',
// Validation
validationResult,
// Audit trail
createdAt: new Date(),
createdBy: 'system',
// Metadata
metadata: {
importedAt: new Date(),
parserVersion: '5.1.4',
originalFormat: format
}
};
return invoice;
}
/**
* Map party information
*/
mapParty(partyData) {
if (!partyData) {
return {
id: '',
name: '',
address: { countryCode: 'DE' }
};
}
return {
id: partyData.BT29_SellerID || partyData.BT46_BuyerID || plugins.smartunique.shortId(),
name: partyData.BT27_SellerName || partyData.BT44_BuyerName || '',
address: {
street: partyData.BT35_SellerStreet || partyData.BT50_BuyerStreet,
city: partyData.BT37_SellerCity || partyData.BT52_BuyerCity,
postalCode: partyData.BT38_SellerPostalCode || partyData.BT53_BuyerPostalCode,
countryCode: partyData.BT40_SellerCountryCode || partyData.BT55_BuyerCountryCode || 'DE'
},
vatId: partyData.BT31_SellerVATID || partyData.BT48_BuyerVATID,
taxId: partyData.BT32_SellerTaxID || partyData.BT47_BuyerTaxID,
email: partyData.BT34_SellerEmail || partyData.BT49_BuyerEmail,
phone: partyData.BT33_SellerPhone,
bankAccount: this.mapBankAccount(partyData)
};
}
/**
* Map bank account information
*/
mapBankAccount(partyData) {
if (!partyData?.BT84_PaymentAccountID) {
return undefined;
}
return {
iban: partyData.BT84_PaymentAccountID,
bic: partyData.BT86_PaymentServiceProviderID,
accountHolder: partyData.BT85_PaymentAccountName
};
}
/**
* Map invoice lines
*/
mapInvoiceLines(linesData) {
return linesData.map((line, index) => ({
lineNumber: index + 1,
description: line.BT154_ItemDescription || '',
quantity: parseFloat(line.BT129_Quantity || 1),
unitPrice: parseFloat(line.BT146_NetPrice || 0),
netAmount: parseFloat(line.BT131_LineNetAmount || 0),
vatCategory: this.mapVATCategory(line.BT151_ItemVATCategory, line.BT152_ItemVATRate),
vatAmount: parseFloat(line.lineVATAmount || 0),
grossAmount: parseFloat(line.BT131_LineNetAmount || 0) + parseFloat(line.lineVATAmount || 0),
productCode: line.BT155_ItemSellerID,
allowances: this.mapLineAllowancesCharges(line.BG27_LineAllowances || [], true),
charges: this.mapLineAllowancesCharges(line.BG28_LineCharges || [], false)
}));
}
/**
* Map VAT category
*/
mapVATCategory(categoryCode, rate) {
const vatRate = typeof rate === 'string' ? parseFloat(rate) : rate;
return {
code: categoryCode || 'S',
rate: vatRate || 0,
exemptionReason: this.getExemptionReason(categoryCode)
};
}
/**
* Get exemption reason for VAT category
*/
getExemptionReason(categoryCode) {
const exemptionReasons = {
'E': 'Tax exempt',
'Z': 'Zero rated',
'AE': 'Reverse charge (§13b UStG)',
'K': 'Intra-EU supply',
'G': 'Export outside EU',
'O': 'Outside scope of tax',
'S': undefined // Standard rate, no exemption
};
return exemptionReasons[categoryCode];
}
/**
* Map VAT breakdown
*/
mapVATBreakdown(vatBreakdown) {
return vatBreakdown.map(vat => ({
vatCategory: this.mapVATCategory(vat.BT118_VATCategory, vat.BT119_VATRate),
taxableAmount: parseFloat(vat.BT116_TaxableAmount || 0),
taxAmount: parseFloat(vat.BT117_TaxAmount || 0)
}));
}
/**
* Map allowances and charges
*/
mapAllowancesCharges(data, isAllowance) {
return data.map(item => ({
reason: item.BT97_AllowanceReason || item.BT104_ChargeReason || '',
amount: parseFloat(item.BT92_AllowanceAmount || item.BT99_ChargeAmount || 0),
percentage: item.BT94_AllowancePercentage || item.BT101_ChargePercentage,
vatCategory: item.BT95_AllowanceVATCategory || item.BT102_ChargeVATCategory
? this.mapVATCategory(item.BT95_AllowanceVATCategory || item.BT102_ChargeVATCategory, item.BT96_AllowanceVATRate || item.BT103_ChargeVATRate)
: undefined,
vatAmount: parseFloat(item.allowanceVATAmount || item.chargeVATAmount || 0)
}));
}
/**
* Map line-level allowances and charges
*/
mapLineAllowancesCharges(data, isAllowance) {
return data.map(item => ({
reason: item.BT140_LineAllowanceReason || item.BT145_LineChargeReason || '',
amount: parseFloat(item.BT136_LineAllowanceAmount || item.BT141_LineChargeAmount || 0),
percentage: item.BT138_LineAllowancePercentage || item.BT143_LineChargePercentage
}));
}
/**
* Map payment terms
*/
mapPaymentTerms(businessTerms) {
if (!businessTerms.BT9_PaymentDueDate && !businessTerms.BT20_PaymentTerms) {
return undefined;
}
const paymentTerms = {
dueDate: businessTerms.BT9_PaymentDueDate
? new Date(businessTerms.BT9_PaymentDueDate)
: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000), // Default 30 days
paymentTermsNote: businessTerms.BT20_PaymentTerms
};
// Parse skonto from payment terms note if present
if (businessTerms.BT20_PaymentTerms) {
paymentTerms.skonto = this.parseSkontoTerms(businessTerms.BT20_PaymentTerms);
}
return paymentTerms;
}
/**
* Parse skonto terms from payment terms text
*/
parseSkontoTerms(paymentTermsText) {
const skontoTerms = [];
// Common German skonto patterns:
// "2% Skonto bei Zahlung innerhalb von 10 Tagen"
// "3% bei Zahlung bis 8 Tage, 2% bis 14 Tage"
const skontoPattern = /(\d+(?:\.\d+)?)\s*%.*?(\d+)\s*(?:Tag|Day)/gi;
let match;
while ((match = skontoPattern.exec(paymentTermsText)) !== null) {
skontoTerms.push({
percentage: parseFloat(match[1]),
days: parseInt(match[2]),
baseAmount: 0 // To be calculated based on invoice amount
});
}
return skontoTerms.length > 0 ? skontoTerms : undefined;
}
/**
* Map payment means
*/
mapPaymentMeans(paymentInstructions) {
if (!paymentInstructions) {
return undefined;
}
return {
code: paymentInstructions.BT81_PaymentMeansCode || '30', // 30 = Bank transfer
account: paymentInstructions.BT84_PaymentAccountID
? {
iban: paymentInstructions.BT84_PaymentAccountID,
bic: paymentInstructions.BT86_PaymentServiceProviderID,
accountHolder: paymentInstructions.BT85_PaymentAccountName
}
: undefined
};
}
/**
* Classify tax scenario based on invoice data
*/
classifyTaxScenario(invoice) {
const supplierCountry = invoice.supplier.address.countryCode;
const customerCountry = invoice.customer.address.countryCode;
const hasVAT = invoice.totalVATAmount > 0;
const vatCategories = invoice.vatBreakdown.map(vb => vb.vatCategory.code);
// Reverse charge
if (vatCategories.includes('AE')) {
return 'reverse_charge';
}
// Small business exemption
if (vatCategories.includes('E') && invoice.invoiceNote?.includes('§19')) {
return 'small_business';
}
// Export outside EU
if (vatCategories.includes('G') || (!this.isEUCountry(customerCountry) && supplierCountry === 'DE')) {
return 'export';
}
// Intra-EU transactions
if (supplierCountry !== customerCountry && this.isEUCountry(supplierCountry) && this.isEUCountry(customerCountry)) {
if (invoice.direction === 'outbound') {
return 'intra_eu_supply';
}
else {
return 'intra_eu_acquisition';
}
}
// Domestic exempt
if (!hasVAT && supplierCountry === 'DE' && customerCountry === 'DE') {
return 'domestic_exempt';
}
// Default: Domestic taxed
return 'domestic_taxed';
}
/**
* Check if country is in EU
*/
isEUCountry(countryCode) {
const euCountries = [
'AT', 'BE', 'BG', 'HR', 'CY', 'CZ', 'DK', 'EE', 'FI', 'FR',
'DE', 'GR', 'HU', 'IE', 'IT', 'LV', 'LT', 'LU', 'MT', 'NL',
'PL', 'PT', 'RO', 'SK', 'SI', 'ES', 'SE'
];
return euCountries.includes(countryCode);
}
/**
* Map e-invoice format from library format
*/
mapEInvoiceFormat(format) {
const formatMap = {
'xrechnung': 'xrechnung',
'zugferd': 'zugferd',
'factur-x': 'facturx',
'facturx': 'facturx',
'peppol': 'peppol',
'ubl': 'ubl'
};
return formatMap[format.toLowerCase()] || 'xrechnung';
}
/**
* Calculate content hash for the invoice
*/
async calculateContentHash(xmlContent) {
const hash = await plugins.smarthash.sha256FromString(xmlContent);
return hash;
}
/**
* Convert invoice to different format
*/
async convertFormat(invoice, targetFormat) {
try {
// Load from existing XML
const einvoice = await plugins.einvoice.EInvoice.fromXml(invoice.xmlContent);
// Convert to target format (takes ~0.6ms)
const convertedXml = await einvoice.exportXml(targetFormat);
return convertedXml;
}
catch (error) {
this.logger.log('error', `Failed to convert invoice format: ${error}`);
throw new Error(`Format conversion failed: ${error.message}`);
}
}
/**
* Generate invoice from internal data
*/
async generateInvoice(invoiceData, format) {
try {
// Create a new invoice instance
const einvoice = new plugins.einvoice.EInvoice();
// Set invoice data
const businessTerms = this.mapToBusinessTerms(invoiceData);
Object.assign(einvoice, businessTerms);
// Generate XML in requested format
const xml = await einvoice.exportXml(format);
// Generate PDF if ZUGFeRD or Factur-X
let pdf;
if (format === 'zugferd' || format === 'facturx') {
// Access the pdf property if it exists
if (einvoice.pdf && einvoice.pdf.buffer) {
pdf = Buffer.from(einvoice.pdf.buffer);
}
}
return { xml, pdf };
}
catch (error) {
this.logger.log('error', `Failed to generate invoice: ${error}`);
throw new Error(`Invoice generation failed: ${error.message}`);
}
}
/**
* Map internal invoice to EN16931 Business Terms
*/
mapToBusinessTerms(invoice) {
return {
BT1_InvoiceNumber: invoice.invoiceNumber,
BT2_IssueDate: invoice.issueDate?.toISOString(),
BT3_InvoiceTypeCode: invoice.invoiceTypeCode || '380',
BT5_CurrencyCode: invoice.currencyCode || 'EUR',
BT7_TaxPointDate: invoice.taxPointDate?.toISOString(),
BT9_PaymentDueDate: invoice.paymentDueDate?.toISOString(),
// Map other Business Terms...
// This would be a comprehensive mapping in production
};
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2tyLmludm9pY2UuYWRhcHRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3Nrci5pbnZvaWNlLmFkYXB0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFjeEM7OztHQUdHO0FBQ0gsTUFBTSxPQUFPLGNBQWM7SUFHekI7UUFJaUIsaUJBQVksR0FBRyxFQUFFLEdBQUcsSUFBSSxHQUFHLElBQUksQ0FBQyxDQUFDLFdBQVc7UUFDNUMsaUJBQVksR0FBRyxFQUFFLEdBQUcsSUFBSSxHQUFHLElBQUksQ0FBQyxDQUFDLFdBQVc7UUFKM0QsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLE9BQU8sQ0FBQyxRQUFRLENBQUMsVUFBVSxFQUFFLENBQUM7SUFDbEQsQ0FBQztJQUtEOztPQUVHO0lBQ0ksS0FBSyxDQUFDLFlBQVksQ0FDdkIsSUFBcUIsRUFDckIsU0FBNEI7UUFFNUIsSUFBSSxDQUFDO1lBQ0gsc0JBQXNCO1lBQ3RCLElBQUksTUFBTSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO2dCQUMxQixJQUFJLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO29CQUNwQyxNQUFNLElBQUksS0FBSyxDQUFDLDJCQUEyQixJQUFJLENBQUMsTUFBTSxlQUFlLElBQUksQ0FBQyxZQUFZLFNBQVMsQ0FBQyxDQUFDO2dCQUNuRyxDQUFDO1lBQ0gsQ0FBQztpQkFBTSxJQUFJLE9BQU8sSUFBSSxLQUFLLFFBQVEsSUFBSSxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztnQkFDdkUsTUFBTSxJQUFJLEtBQUssQ0FBQywwQkFBMEIsSUFBSSxDQUFDLE1BQU0sb0JBQW9CLElBQUksQ0FBQyxZQUFZLGNBQWMsQ0FBQyxDQUFDO1lBQzVHLENBQUM7WUFFRCwyQ0FBMkM7WUFDM0MsSUFBSSxRQUFRLENBQUM7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