import { BaseEncoder } from '../base/base.encoder.js'; import type { TInvoice, TCreditNote, TDebitNote } from '../../interfaces/common.js'; import { UBLDocumentType, UBL_NAMESPACES } from './ubl.types.js'; /** * Base encoder for UBL-based invoice formats */ export abstract class UBLBaseEncoder extends BaseEncoder { /** * Encodes a TInvoice object into UBL XML * @param invoice TInvoice object to encode * @returns UBL XML string */ public async encode(invoice: TInvoice): Promise { // TInvoice is always an invoice, treat it as debit note for encoding return this.encodeDebitNote(invoice as unknown as TDebitNote); } /** * Encodes a TCreditNote object into UBL XML * @param creditNote TCreditNote object to encode * @returns UBL XML string */ protected abstract encodeCreditNote(creditNote: TCreditNote): Promise; /** * Encodes a TDebitNote object into UBL XML * @param debitNote TDebitNote object to encode * @returns UBL XML string */ protected abstract encodeDebitNote(debitNote: TDebitNote): Promise; /** * Creates the XML declaration and root element * @param documentType UBL document type * @returns XML string with declaration and root element */ protected createXmlRoot(documentType: UBLDocumentType): string { return ` <${documentType} xmlns="urn:oasis:names:specification:ubl:schema:xsd:${documentType}-2" xmlns:cac="${UBL_NAMESPACES.CAC}" xmlns:cbc="${UBL_NAMESPACES.CBC}"> `; } /** * Formats a date as an ISO string (YYYY-MM-DD) * @param timestamp Timestamp to format * @returns Formatted date string */ protected formatDate(timestamp: number): string { // Ensure timestamp is valid if (!timestamp || isNaN(timestamp)) { timestamp = Date.now(); } const date = new Date(timestamp); // Check if date is valid if (isNaN(date.getTime())) { return new Date().toISOString().split('T')[0]; } return date.toISOString().split('T')[0]; } }