import * as plugins from './plugins.js'; /** * A class to convert a given ZUGFeRD XML string * into a structured ILetter with invoice data. * * Handles different invoice XML formats: * - ZUGFeRD/Factur-X (CII) * - UBL * - FatturaPA */ export class ZUGFeRDXmlDecoder { private xmlString: string; private xmlFormat: string; constructor(xmlString: string) { if (!xmlString) { throw new Error('No XML string provided to decoder'); } this.xmlString = xmlString; // Simple format detection based on string contents this.xmlFormat = this.detectFormat(); } /** * Detects the XML invoice format using simple string checks */ private detectFormat(): string { // ZUGFeRD/Factur-X (CII format) if (this.xmlString.includes('CrossIndustryInvoice') || this.xmlString.includes('un/cefact') || this.xmlString.includes('rsm:')) { return 'CII'; } // UBL format if (this.xmlString.includes('Invoice') || this.xmlString.includes('oasis:names:specification:ubl')) { return 'UBL'; } // FatturaPA format if (this.xmlString.includes('FatturaElettronica') || this.xmlString.includes('fatturapa.gov.it')) { return 'FatturaPA'; } // Default to generic return 'unknown'; } /** * Converts XML to a structured letter object */ public async getLetterData(): Promise { try { // Try using SmartXml from plugins as a fallback const smartxmlInstance = new plugins.smartxml.SmartXml(); return smartxmlInstance.parseXmlToObject(this.xmlString); } catch (error) { console.error('Error converting XML to letter data:', error); // If all else fails, return a minimal letter object return this.createDefaultLetter(); } } /** * Creates a default letter object with minimal data */ private createDefaultLetter(): plugins.tsclass.business.ILetter { // Create a default seller const seller: plugins.tsclass.business.IContact = { name: 'Unknown Seller', type: 'company', address: { streetName: 'Unknown', city: 'Unknown', country: 'Unknown', postalCode: 'Unknown', }, }; // Create a default buyer const buyer: plugins.tsclass.business.IContact = { name: 'Unknown Buyer', type: 'company', address: { streetName: 'Unknown', city: 'Unknown', country: 'Unknown', postalCode: 'Unknown', }, }; // Create default invoice data const invoiceData: plugins.tsclass.business.IInvoiceData = { id: 'Unknown', status: null, type: 'invoice', billedBy: seller, billedTo: buyer, deliveryDate: Date.now(), dueInDays: 30, periodOfPerformance: null, printResult: null, currency: 'EUR', notes: [], items: [ { name: 'Unknown Item', unitQuantity: 1, unitNetPrice: 0, vatPercentage: 0, position: 0, unitType: 'units', } ], reverseCharge: false, }; // Return a default letter return { versionInfo: { type: 'extracted', version: '1.0.0', }, type: 'invoice', date: Date.now(), subject: `Extracted Invoice (${this.xmlFormat} format)`, from: seller, to: buyer, content: { invoiceData: invoiceData, textData: null, timesheetData: null, contractData: null, }, needsCoverSheet: false, objectActions: [], pdf: null, incidenceId: null, language: null, legalContact: null, logoUrl: null, pdfAttachments: null, accentColor: null, }; } }