@fin.cx/einvoice
Version:
A TypeScript module for creating, manipulating, and embedding XML data within PDF files specifically tailored for electronic invoice (einvoice) packages.
78 lines • 6.54 kB
JavaScript
import { InvoiceFormat } from '../interfaces.js';
import { BaseValidator } from './base.validator.js';
import { FacturXValidator } from './facturx.validator.js';
import { UBLValidator } from './ubl.validator.js';
import { DOMParser } from 'xmldom';
/**
* Factory to create the appropriate validator based on the XML format
*/
export class ValidatorFactory {
/**
* Creates a validator for the specified XML content
* @param xml XML content to validate
* @returns Appropriate validator instance
*/
static createValidator(xml) {
const format = ValidatorFactory.detectFormat(xml);
switch (format) {
case InvoiceFormat.UBL:
case InvoiceFormat.XRECHNUNG:
return new UBLValidator(xml);
case InvoiceFormat.CII:
case InvoiceFormat.ZUGFERD:
case InvoiceFormat.FACTURX:
return new FacturXValidator(xml);
// FatturaPA and other formats would be implemented here
default:
throw new Error(`Unsupported invoice format: ${format}`);
}
}
/**
* Detects the invoice format from XML content
* @param xml XML content to analyze
* @returns Detected invoice format
*/
static detectFormat(xml) {
try {
const doc = new DOMParser().parseFromString(xml, 'application/xml');
const root = doc.documentElement;
if (!root) {
return InvoiceFormat.UNKNOWN;
}
// UBL detection (Invoice or CreditNote root element)
if (root.nodeName === 'Invoice' || root.nodeName === 'CreditNote') {
// Check if it's XRechnung by looking at CustomizationID
const customizationNodes = root.getElementsByTagName('cbc:CustomizationID');
if (customizationNodes.length > 0) {
const customizationId = customizationNodes[0].textContent || '';
if (customizationId.includes('xrechnung') || customizationId.includes('XRechnung')) {
return InvoiceFormat.XRECHNUNG;
}
}
return InvoiceFormat.UBL;
}
// Factur-X/ZUGFeRD detection (CrossIndustryInvoice root element)
if (root.nodeName === 'rsm:CrossIndustryInvoice' || root.nodeName === 'CrossIndustryInvoice') {
// Check for profile to determine if it's Factur-X or ZUGFeRD
const profileNodes = root.getElementsByTagName('ram:ID');
for (let i = 0; i < profileNodes.length; i++) {
const profileText = profileNodes[i].textContent || '';
if (profileText.includes('factur-x') || profileText.includes('Factur-X')) {
return InvoiceFormat.FACTURX;
}
if (profileText.includes('zugferd') || profileText.includes('ZUGFeRD')) {
return InvoiceFormat.ZUGFERD;
}
}
// If no specific profile found, default to CII
return InvoiceFormat.CII;
}
// FatturaPA detection would be implemented here
return InvoiceFormat.UNKNOWN;
}
catch (error) {
return InvoiceFormat.UNKNOWN;
}
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsaWRhdG9yLmZhY3RvcnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9mb3JtYXRzL3ZhbGlkYXRvci5mYWN0b3J5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUVqRCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDcEQsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDMUQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ2xELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxRQUFRLENBQUM7QUFFbkM7O0dBRUc7QUFDSCxNQUFNLE9BQU8sZ0JBQWdCO0lBQzNCOzs7O09BSUc7SUFDSSxNQUFNLENBQUMsZUFBZSxDQUFDLEdBQVc7UUFDdkMsTUFBTSxNQUFNLEdBQUcsZ0JBQWdCLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBRWxELFFBQVEsTUFBTSxFQUFFLENBQUM7WUFDZixLQUFLLGFBQWEsQ0FBQyxHQUFHLENBQUM7WUFDdkIsS0FBSyxhQUFhLENBQUMsU0FBUztnQkFDMUIsT0FBTyxJQUFJLFlBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUUvQixLQUFLLGFBQWEsQ0FBQyxHQUFHLENBQUM7WUFDdkIsS0FBSyxhQUFhLENBQUMsT0FBTyxDQUFDO1lBQzNCLEtBQUssYUFBYSxDQUFDLE9BQU87Z0JBQ3hCLE9BQU8sSUFBSSxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUVuQyx3REFBd0Q7WUFFeEQ7Z0JBQ0UsTUFBTSxJQUFJLEtBQUssQ0FBQywrQkFBK0IsTUFBTSxFQUFFLENBQUMsQ0FBQztRQUM3RCxDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7O09BSUc7SUFDSyxNQUFNLENBQUMsWUFBWSxDQUFDLEdBQVc7UUFDckMsSUFBSSxDQUFDO1lBQ0gsTUFBTSxHQUFHLEdBQUcsSUFBSSxTQUFTLEVBQUUsQ0FBQyxlQUFlLENBQUMsR0FBRyxFQUFFLGlCQUFpQixDQUFDLENBQUM7WUFDcEUsTUFBTSxJQUFJLEdBQUcsR0FBRyxDQUFDLGVBQWUsQ0FBQztZQUVqQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7Z0JBQ1YsT0FBTyxhQUFhLENBQUMsT0FBTyxDQUFDO1lBQy9CLENBQUM7WUFFRCxxREFBcUQ7WUFDckQsSUFBSSxJQUFJLENBQUMsUUFBUSxLQUFLLFNBQVMsSUFBSSxJQUFJLENBQUMsUUFBUSxLQUFLLFlBQVksRUFBRSxDQUFDO2dCQUNsRSx3REFBd0Q7Z0JBQ3hELE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxDQUFDLG9CQUFvQixDQUFDLHFCQUFxQixDQUFDLENBQUM7Z0JBQzVFLElBQUksa0JBQWtCLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO29CQUNsQyxNQUFNLGVBQWUsR0FBRyxrQkFBa0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxXQUFXLElBQUksRUFBRSxDQUFDO29CQUNoRSxJQUFJLGVBQWUsQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLElBQUksZUFBZSxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDO3dCQUNuRixPQUFPLGFBQWEsQ0FBQyxTQUFTLENBQUM7b0JBQ2pDLENBQUM7Z0JBQ0gsQ0FBQztnQkFFRCxPQUFPLGFBQWEsQ0FBQyxHQUFHLENBQUM7WUFDM0IsQ0FBQztZQUVELGlFQUFpRTtZQUNqRSxJQUFJLElBQUksQ0FBQyxRQUFRLEtBQUssMEJBQTBCLElBQUksSUFBSSxDQUFDLFFBQVEsS0FBSyxzQkFBc0IsRUFBRSxDQUFDO2dCQUM3Riw2REFBNkQ7Z0JBQzdELE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxRQUFRLENBQUMsQ0FBQztnQkFDekQsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLFlBQVksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztvQkFDN0MsTUFBTSxXQUFXLEdBQUcsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLFdBQVcsSUFBSSxFQUFFLENBQUM7b0JBRXRELElBQUksV0FBVyxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsSUFBSSxXQUFXLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUM7d0JBQ3pFLE9BQU8sYUFBYSxDQUFDLE9BQU8sQ0FBQztvQkFDL0IsQ0FBQztvQkFFRCxJQUFJLFdBQVcsQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLElBQUksV0FBVyxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO3dCQUN2RSxPQUFPLGFBQWEsQ0FBQyxPQUFPLENBQUM7b0JBQy9CLENBQUM7Z0JBQ0gsQ0FBQztnQkFFRCwrQ0FBK0M7Z0JBQy9DLE9BQU8sYUFBYSxDQUFDLEdBQUcsQ0FBQztZQUMzQixDQUFDO1lBRUQsZ0RBQWdEO1lBRWhELE9BQU8sYUFBYSxDQUFDLE9BQU8sQ0FBQztRQUMvQixDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLE9BQU8sYUFBYSxDQUFDLE9BQU8sQ0FBQztRQUMvQixDQUFDO0lBQ0gsQ0FBQztDQUNGIn0=