feat(compliance): improve compliance
This commit is contained in:
@@ -354,8 +354,8 @@ export class UBLEncoder extends UBLBaseEncoder {
|
|||||||
const categoryId = invoice.reverseCharge ? 'AE' : 'S';
|
const categoryId = invoice.reverseCharge ? 'AE' : 'S';
|
||||||
this.appendElement(doc, taxCategoryNode, 'cbc:ID', categoryId);
|
this.appendElement(doc, taxCategoryNode, 'cbc:ID', categoryId);
|
||||||
|
|
||||||
// Add percent
|
// Add percent with 2 decimal places
|
||||||
this.appendElement(doc, taxCategoryNode, 'cbc:Percent', rate.toString());
|
this.appendElement(doc, taxCategoryNode, 'cbc:Percent', rate.toFixed(2));
|
||||||
|
|
||||||
// Add tax exemption reason if reverse charge
|
// Add tax exemption reason if reverse charge
|
||||||
if (invoice.reverseCharge) {
|
if (invoice.reverseCharge) {
|
||||||
@@ -474,8 +474,8 @@ export class UBLEncoder extends UBLBaseEncoder {
|
|||||||
const categoryId = invoice.reverseCharge ? 'AE' : 'S';
|
const categoryId = invoice.reverseCharge ? 'AE' : 'S';
|
||||||
this.appendElement(doc, classifiedTaxCategoryNode, 'cbc:ID', categoryId);
|
this.appendElement(doc, classifiedTaxCategoryNode, 'cbc:ID', categoryId);
|
||||||
|
|
||||||
// Tax percent
|
// Tax percent with 2 decimal places
|
||||||
this.appendElement(doc, classifiedTaxCategoryNode, 'cbc:Percent', item.vatPercentage.toString());
|
this.appendElement(doc, classifiedTaxCategoryNode, 'cbc:Percent', item.vatPercentage.toFixed(2));
|
||||||
|
|
||||||
// Tax scheme
|
// Tax scheme
|
||||||
const taxSchemeNode = doc.createElement('cac:TaxScheme');
|
const taxSchemeNode = doc.createElement('cac:TaxScheme');
|
||||||
@@ -637,6 +637,13 @@ export class UBLEncoder extends UBLBaseEncoder {
|
|||||||
paymentMeans.appendChild(paymentId);
|
paymentMeans.appendChild(paymentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add PaymentDueDate
|
||||||
|
if (paymentInfo.paymentDueDate && !paymentMeans.getElementsByTagName('cbc:PaymentDueDate')[0]) {
|
||||||
|
const dueDate = doc.createElement('cbc:PaymentDueDate');
|
||||||
|
dueDate.textContent = paymentInfo.paymentDueDate;
|
||||||
|
paymentMeans.appendChild(dueDate);
|
||||||
|
}
|
||||||
|
|
||||||
// Add IBAN and BIC
|
// Add IBAN and BIC
|
||||||
if (paymentInfo.iban || paymentInfo.bic) {
|
if (paymentInfo.iban || paymentInfo.bic) {
|
||||||
let payeeAccount = paymentMeans.getElementsByTagName('cac:PayeeFinancialAccount')[0];
|
let payeeAccount = paymentMeans.getElementsByTagName('cac:PayeeFinancialAccount')[0];
|
||||||
@@ -652,37 +659,42 @@ export class UBLEncoder extends UBLBaseEncoder {
|
|||||||
payeeAccount.appendChild(iban);
|
payeeAccount.appendChild(iban);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add BIC
|
// Add account name (must come after ID but before FinancialInstitutionBranch)
|
||||||
if (paymentInfo.bic) {
|
if (paymentInfo.accountName && !payeeAccount.getElementsByTagName('cbc:Name')[0]) {
|
||||||
|
const accountName = doc.createElement('cbc:Name');
|
||||||
|
accountName.textContent = paymentInfo.accountName;
|
||||||
|
// Insert after ID but before FinancialInstitutionBranch
|
||||||
|
const id = payeeAccount.getElementsByTagName('cbc:ID')[0];
|
||||||
|
const finInstBranch = payeeAccount.getElementsByTagName('cac:FinancialInstitutionBranch')[0];
|
||||||
|
if (finInstBranch) {
|
||||||
|
payeeAccount.insertBefore(accountName, finInstBranch);
|
||||||
|
} else if (id && id.nextSibling) {
|
||||||
|
payeeAccount.insertBefore(accountName, id.nextSibling);
|
||||||
|
} else {
|
||||||
|
payeeAccount.appendChild(accountName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add BIC and bank name
|
||||||
|
if (paymentInfo.bic || paymentInfo.bankName) {
|
||||||
let finInstBranch = payeeAccount.getElementsByTagName('cac:FinancialInstitutionBranch')[0];
|
let finInstBranch = payeeAccount.getElementsByTagName('cac:FinancialInstitutionBranch')[0];
|
||||||
if (!finInstBranch) {
|
if (!finInstBranch) {
|
||||||
finInstBranch = doc.createElement('cac:FinancialInstitutionBranch');
|
finInstBranch = doc.createElement('cac:FinancialInstitutionBranch');
|
||||||
payeeAccount.appendChild(finInstBranch);
|
payeeAccount.appendChild(finInstBranch);
|
||||||
}
|
}
|
||||||
|
|
||||||
let finInst = finInstBranch.getElementsByTagName('cac:FinancialInstitution')[0];
|
// Add BIC as branch ID
|
||||||
if (!finInst) {
|
if (paymentInfo.bic && !finInstBranch.getElementsByTagName('cbc:ID')[0]) {
|
||||||
finInst = doc.createElement('cac:FinancialInstitution');
|
const bicElement = doc.createElement('cbc:ID');
|
||||||
finInstBranch.appendChild(finInst);
|
bicElement.textContent = paymentInfo.bic;
|
||||||
|
finInstBranch.appendChild(bicElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!finInst.getElementsByTagName('cbc:ID')[0]) {
|
// Add bank name
|
||||||
const bic = doc.createElement('cbc:ID');
|
if (paymentInfo.bankName && !finInstBranch.getElementsByTagName('cbc:Name')[0]) {
|
||||||
bic.textContent = paymentInfo.bic;
|
const bankNameElement = doc.createElement('cbc:Name');
|
||||||
finInst.appendChild(bic);
|
bankNameElement.textContent = paymentInfo.bankName;
|
||||||
}
|
finInstBranch.appendChild(bankNameElement);
|
||||||
}
|
|
||||||
|
|
||||||
// Add account name
|
|
||||||
if (paymentInfo.accountName && !payeeAccount.getElementsByTagName('cbc:Name')[0]) {
|
|
||||||
const accountName = doc.createElement('cbc:Name');
|
|
||||||
accountName.textContent = paymentInfo.accountName;
|
|
||||||
// Insert after ID
|
|
||||||
const id = payeeAccount.getElementsByTagName('cbc:ID')[0];
|
|
||||||
if (id && id.nextSibling) {
|
|
||||||
payeeAccount.insertBefore(accountName, id.nextSibling);
|
|
||||||
} else {
|
|
||||||
payeeAccount.appendChild(accountName);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -773,10 +785,69 @@ export class UBLEncoder extends UBLBaseEncoder {
|
|||||||
*/
|
*/
|
||||||
private enhancePartyInformationUBL(doc: Document, invoice: TInvoice): void {
|
private enhancePartyInformationUBL(doc: Document, invoice: TInvoice): void {
|
||||||
// Enhance supplier party
|
// Enhance supplier party
|
||||||
this.addContactToPartyUBL(doc, 'cac:AccountingSupplierParty', (invoice.from as any)?.metadata?.contactInformation);
|
this.enhancePartyUBL(doc, 'cac:AccountingSupplierParty', invoice.from);
|
||||||
|
|
||||||
// Enhance customer party
|
// Enhance customer party
|
||||||
this.addContactToPartyUBL(doc, 'cac:AccountingCustomerParty', (invoice.to as any)?.metadata?.contactInformation);
|
this.enhancePartyUBL(doc, 'cac:AccountingCustomerParty', invoice.to);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enhances a party with GLN, additional identifiers, and contact info
|
||||||
|
* @param doc XML document
|
||||||
|
* @param partySelector Party selector
|
||||||
|
* @param partyData Party data
|
||||||
|
*/
|
||||||
|
private enhancePartyUBL(doc: Document, partySelector: string, partyData: any): void {
|
||||||
|
if (!partyData) return;
|
||||||
|
|
||||||
|
const partyContainer = doc.getElementsByTagName(partySelector)[0];
|
||||||
|
if (!partyContainer) return;
|
||||||
|
|
||||||
|
const party = partyContainer.getElementsByTagName('cac:Party')[0];
|
||||||
|
if (!party) return;
|
||||||
|
|
||||||
|
// Add GLN if available
|
||||||
|
if (partyData.gln && !party.getElementsByTagName('cbc:EndpointID')[0]) {
|
||||||
|
const endpointNode = doc.createElement('cbc:EndpointID');
|
||||||
|
endpointNode.setAttribute('schemeID', '0088'); // GLN scheme ID
|
||||||
|
endpointNode.textContent = partyData.gln;
|
||||||
|
|
||||||
|
// Insert as first child
|
||||||
|
if (party.firstChild) {
|
||||||
|
party.insertBefore(endpointNode, party.firstChild);
|
||||||
|
} else {
|
||||||
|
party.appendChild(endpointNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add additional identifiers
|
||||||
|
if (partyData.additionalIdentifiers && Array.isArray(partyData.additionalIdentifiers)) {
|
||||||
|
for (const identifier of partyData.additionalIdentifiers) {
|
||||||
|
const partyId = doc.createElement('cac:PartyIdentification');
|
||||||
|
const id = doc.createElement('cbc:ID');
|
||||||
|
if (identifier.scheme) {
|
||||||
|
id.setAttribute('schemeID', identifier.scheme);
|
||||||
|
}
|
||||||
|
id.textContent = identifier.value;
|
||||||
|
partyId.appendChild(id);
|
||||||
|
|
||||||
|
// Insert after EndpointID or at beginning
|
||||||
|
const endpoint = party.getElementsByTagName('cbc:EndpointID')[0];
|
||||||
|
if (endpoint && endpoint.nextSibling) {
|
||||||
|
party.insertBefore(partyId, endpoint.nextSibling);
|
||||||
|
} else if (party.firstChild) {
|
||||||
|
party.insertBefore(partyId, party.firstChild);
|
||||||
|
} else {
|
||||||
|
party.appendChild(partyId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add contact information from metadata if not already present
|
||||||
|
const contactInfo = partyData.metadata?.contactInformation;
|
||||||
|
if (contactInfo) {
|
||||||
|
this.addContactToPartyUBL(doc, partySelector, contactInfo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -847,6 +918,34 @@ export class UBLEncoder extends UBLBaseEncoder {
|
|||||||
|
|
||||||
if (!itemMetadata) continue;
|
if (!itemMetadata) continue;
|
||||||
|
|
||||||
|
// Add OrderLineReference if available
|
||||||
|
if (itemMetadata.orderLineReference && !line.getElementsByTagName('cac:OrderLineReference')[0]) {
|
||||||
|
const orderLineRef = doc.createElement('cac:OrderLineReference');
|
||||||
|
const lineId = doc.createElement('cbc:LineID');
|
||||||
|
lineId.textContent = itemMetadata.orderLineReferenceId || '1';
|
||||||
|
orderLineRef.appendChild(lineId);
|
||||||
|
|
||||||
|
if (itemMetadata.orderLineReference) {
|
||||||
|
const orderRef = doc.createElement('cac:OrderReference');
|
||||||
|
const orderId = doc.createElement('cbc:ID');
|
||||||
|
orderId.textContent = itemMetadata.orderLineReference;
|
||||||
|
orderRef.appendChild(orderId);
|
||||||
|
orderLineRef.appendChild(orderRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert after ID
|
||||||
|
const invoiceLineId = line.getElementsByTagName('cbc:ID')[0];
|
||||||
|
if (invoiceLineId && invoiceLineId.nextSibling) {
|
||||||
|
line.insertBefore(orderLineRef, invoiceLineId.nextSibling);
|
||||||
|
} else {
|
||||||
|
// Insert before InvoicedQuantity
|
||||||
|
const quantity = line.getElementsByTagName('cbc:InvoicedQuantity')[0];
|
||||||
|
if (quantity) {
|
||||||
|
line.insertBefore(orderLineRef, quantity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const itemElement = line.getElementsByTagName('cac:Item')[0];
|
const itemElement = line.getElementsByTagName('cac:Item')[0];
|
||||||
if (!itemElement) continue;
|
if (!itemElement) continue;
|
||||||
|
|
||||||
|
@@ -106,6 +106,10 @@ export class XRechnungDecoder extends UBLBaseDecoder {
|
|||||||
vatPercentage
|
vatPercentage
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Extract order line reference
|
||||||
|
const orderLineReference = this.getText('./cac:OrderLineReference/cac:OrderReference/cbc:ID', line) || '';
|
||||||
|
const orderLineReferenceId = this.getText('./cac:OrderLineReference/cbc:LineID', line) || '';
|
||||||
|
|
||||||
// Extract additional item properties
|
// Extract additional item properties
|
||||||
const additionalProps: Record<string, string> = {};
|
const additionalProps: Record<string, string> = {};
|
||||||
const propNodes = this.select('./cac:Item/cac:AdditionalItemProperty', line);
|
const propNodes = this.select('./cac:Item/cac:AdditionalItemProperty', line);
|
||||||
@@ -120,12 +124,14 @@ export class XRechnungDecoder extends UBLBaseDecoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Store additional item data in metadata
|
// Store additional item data in metadata
|
||||||
if (description || buyerItemID || standardItemID || commodityClassification || Object.keys(additionalProps).length > 0) {
|
if (description || buyerItemID || standardItemID || commodityClassification || orderLineReference || Object.keys(additionalProps).length > 0) {
|
||||||
item.metadata = {
|
item.metadata = {
|
||||||
description,
|
description,
|
||||||
buyerItemID,
|
buyerItemID,
|
||||||
standardItemID,
|
standardItemID,
|
||||||
commodityClassification,
|
commodityClassification,
|
||||||
|
orderLineReference,
|
||||||
|
orderLineReferenceId,
|
||||||
additionalProperties: additionalProps
|
additionalProperties: additionalProps
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -142,8 +148,10 @@ export class XRechnungDecoder extends UBLBaseDecoder {
|
|||||||
// Extract payment information
|
// Extract payment information
|
||||||
const paymentMeansCode = this.getText('//cac:PaymentMeans/cbc:PaymentMeansCode', this.doc);
|
const paymentMeansCode = this.getText('//cac:PaymentMeans/cbc:PaymentMeansCode', this.doc);
|
||||||
const paymentID = this.getText('//cac:PaymentMeans/cbc:PaymentID', this.doc);
|
const paymentID = this.getText('//cac:PaymentMeans/cbc:PaymentID', this.doc);
|
||||||
|
const paymentDueDate = this.getText('//cac:PaymentMeans/cbc:PaymentDueDate', this.doc);
|
||||||
const iban = this.getText('//cac:PaymentMeans/cac:PayeeFinancialAccount/cbc:ID', this.doc);
|
const iban = this.getText('//cac:PaymentMeans/cac:PayeeFinancialAccount/cbc:ID', this.doc);
|
||||||
const bic = this.getText('//cac:PaymentMeans/cac:PayeeFinancialAccount/cac:FinancialInstitutionBranch/cac:FinancialInstitution/cbc:ID', this.doc);
|
const bic = this.getText('//cac:PaymentMeans/cac:PayeeFinancialAccount/cac:FinancialInstitutionBranch/cbc:ID', this.doc);
|
||||||
|
const bankName = this.getText('//cac:PaymentMeans/cac:PayeeFinancialAccount/cac:FinancialInstitutionBranch/cbc:Name', this.doc);
|
||||||
const accountName = this.getText('//cac:PaymentMeans/cac:PayeeFinancialAccount/cbc:Name', this.doc);
|
const accountName = this.getText('//cac:PaymentMeans/cac:PayeeFinancialAccount/cbc:Name', this.doc);
|
||||||
|
|
||||||
// Extract payment terms with discount
|
// Extract payment terms with discount
|
||||||
@@ -206,8 +214,10 @@ export class XRechnungDecoder extends UBLBaseDecoder {
|
|||||||
paymentInformation: {
|
paymentInformation: {
|
||||||
paymentMeansCode,
|
paymentMeansCode,
|
||||||
paymentID,
|
paymentID,
|
||||||
|
paymentDueDate,
|
||||||
iban,
|
iban,
|
||||||
bic,
|
bic,
|
||||||
|
bankName,
|
||||||
accountName,
|
accountName,
|
||||||
paymentTermsNote,
|
paymentTermsNote,
|
||||||
discountPercent
|
discountPercent
|
||||||
@@ -272,6 +282,8 @@ export class XRechnungDecoder extends UBLBaseDecoder {
|
|||||||
let contactPhone = '';
|
let contactPhone = '';
|
||||||
let contactEmail = '';
|
let contactEmail = '';
|
||||||
let contactName = '';
|
let contactName = '';
|
||||||
|
let gln = '';
|
||||||
|
const additionalIdentifiers: any[] = [];
|
||||||
|
|
||||||
// Try to extract party information
|
// Try to extract party information
|
||||||
const partyNodes = this.select(partyPath, this.doc);
|
const partyNodes = this.select(partyPath, this.doc);
|
||||||
@@ -279,6 +291,28 @@ export class XRechnungDecoder extends UBLBaseDecoder {
|
|||||||
if (partyNodes && Array.isArray(partyNodes) && partyNodes.length > 0) {
|
if (partyNodes && Array.isArray(partyNodes) && partyNodes.length > 0) {
|
||||||
const party = partyNodes[0];
|
const party = partyNodes[0];
|
||||||
|
|
||||||
|
// Extract GLN from EndpointID
|
||||||
|
const endpointId = this.getText('./cbc:EndpointID[@schemeID="0088"]', party);
|
||||||
|
if (endpointId) {
|
||||||
|
gln = endpointId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract additional party identifications
|
||||||
|
const partyIdNodes = this.select('./cac:PartyIdentification', party);
|
||||||
|
if (partyIdNodes && Array.isArray(partyIdNodes)) {
|
||||||
|
for (const idNode of partyIdNodes) {
|
||||||
|
const idValue = this.getText('./cbc:ID', idNode);
|
||||||
|
const idElement = (idNode as Element).getElementsByTagName('cbc:ID')[0];
|
||||||
|
const schemeId = idElement?.getAttribute('schemeID');
|
||||||
|
if (idValue) {
|
||||||
|
additionalIdentifiers.push({
|
||||||
|
value: idValue,
|
||||||
|
scheme: schemeId || ''
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Extract name
|
// Extract name
|
||||||
name = this.getText('./cac:PartyName/cbc:Name', party) || '';
|
name = this.getText('./cac:PartyName/cbc:Name', party) || '';
|
||||||
|
|
||||||
@@ -349,16 +383,28 @@ export class XRechnungDecoder extends UBLBaseDecoder {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Store contact information in metadata if available
|
// Store contact information and additional identifiers in metadata if available
|
||||||
|
const metadata: any = {};
|
||||||
|
|
||||||
if (contactPhone || contactEmail || contactName) {
|
if (contactPhone || contactEmail || contactName) {
|
||||||
contact.metadata = {
|
metadata.contactInformation = {
|
||||||
contactInformation: {
|
phone: contactPhone,
|
||||||
phone: contactPhone,
|
email: contactEmail,
|
||||||
email: contactEmail,
|
name: contactName
|
||||||
name: contactName
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (gln) {
|
||||||
|
(contact as any).gln = gln;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (additionalIdentifiers.length > 0) {
|
||||||
|
(contact as any).additionalIdentifiers = additionalIdentifiers;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Object.keys(metadata).length > 0) {
|
||||||
|
contact.metadata = metadata;
|
||||||
|
}
|
||||||
|
|
||||||
return contact;
|
return contact;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@@ -143,6 +143,72 @@ export class XRechnungEncoder extends UBLEncoder {
|
|||||||
partyElement.appendChild(endpointNode);
|
partyElement.appendChild(endpointNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add GLN (Global Location Number) if available
|
||||||
|
if (party.gln && !existingEndpoint) {
|
||||||
|
const endpointNode = doc.createElement('cbc:EndpointID');
|
||||||
|
endpointNode.setAttribute('schemeID', '0088'); // GLN scheme ID
|
||||||
|
endpointNode.textContent = party.gln;
|
||||||
|
|
||||||
|
// Insert as first child of party element
|
||||||
|
if (partyElement.firstChild) {
|
||||||
|
partyElement.insertBefore(endpointNode, partyElement.firstChild);
|
||||||
|
} else {
|
||||||
|
partyElement.appendChild(endpointNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add PartyIdentification for additional identifiers
|
||||||
|
if (party.additionalIdentifiers) {
|
||||||
|
for (const identifier of party.additionalIdentifiers) {
|
||||||
|
const partyId = doc.createElement('cac:PartyIdentification');
|
||||||
|
const id = doc.createElement('cbc:ID');
|
||||||
|
if (identifier.scheme) {
|
||||||
|
id.setAttribute('schemeID', identifier.scheme);
|
||||||
|
}
|
||||||
|
id.textContent = identifier.value;
|
||||||
|
partyId.appendChild(id);
|
||||||
|
|
||||||
|
// Insert after EndpointID or at beginning
|
||||||
|
const endpoint = partyElement.getElementsByTagName('cbc:EndpointID')[0];
|
||||||
|
if (endpoint && endpoint.nextSibling) {
|
||||||
|
partyElement.insertBefore(partyId, endpoint.nextSibling);
|
||||||
|
} else if (partyElement.firstChild) {
|
||||||
|
partyElement.insertBefore(partyId, partyElement.firstChild);
|
||||||
|
} else {
|
||||||
|
partyElement.appendChild(partyId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add company registration number to PartyLegalEntity
|
||||||
|
if (party.registrationDetails?.registrationId) {
|
||||||
|
let legalEntity = partyElement.getElementsByTagName('cac:PartyLegalEntity')[0];
|
||||||
|
if (!legalEntity) {
|
||||||
|
legalEntity = doc.createElement('cac:PartyLegalEntity');
|
||||||
|
// Insert after PostalAddress
|
||||||
|
const postalAddress = partyElement.getElementsByTagName('cac:PostalAddress')[0];
|
||||||
|
if (postalAddress && postalAddress.nextSibling) {
|
||||||
|
partyElement.insertBefore(legalEntity, postalAddress.nextSibling);
|
||||||
|
} else {
|
||||||
|
partyElement.appendChild(legalEntity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add registration name if not present
|
||||||
|
if (!legalEntity.getElementsByTagName('cbc:RegistrationName')[0]) {
|
||||||
|
const regName = doc.createElement('cbc:RegistrationName');
|
||||||
|
regName.textContent = party.registrationDetails.registrationName || party.name;
|
||||||
|
legalEntity.appendChild(regName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add company ID if not present
|
||||||
|
if (!legalEntity.getElementsByTagName('cbc:CompanyID')[0]) {
|
||||||
|
const companyId = doc.createElement('cbc:CompanyID');
|
||||||
|
companyId.textContent = party.registrationDetails.registrationId;
|
||||||
|
legalEntity.appendChild(companyId);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -256,6 +322,13 @@ export class XRechnungEncoder extends UBLEncoder {
|
|||||||
paymentMeans.appendChild(paymentId);
|
paymentMeans.appendChild(paymentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add PaymentDueDate
|
||||||
|
if (paymentInfo.paymentDueDate && !paymentMeans.getElementsByTagName('cbc:PaymentDueDate')[0]) {
|
||||||
|
const dueDate = doc.createElement('cbc:PaymentDueDate');
|
||||||
|
dueDate.textContent = paymentInfo.paymentDueDate;
|
||||||
|
paymentMeans.appendChild(dueDate);
|
||||||
|
}
|
||||||
|
|
||||||
// Add IBAN and BIC
|
// Add IBAN and BIC
|
||||||
if (paymentInfo.iban || paymentInfo.bic) {
|
if (paymentInfo.iban || paymentInfo.bic) {
|
||||||
let payeeAccount = paymentMeans.getElementsByTagName('cac:PayeeFinancialAccount')[0];
|
let payeeAccount = paymentMeans.getElementsByTagName('cac:PayeeFinancialAccount')[0];
|
||||||
@@ -271,37 +344,42 @@ export class XRechnungEncoder extends UBLEncoder {
|
|||||||
payeeAccount.appendChild(iban);
|
payeeAccount.appendChild(iban);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add BIC
|
// Add account name (must come after ID but before FinancialInstitutionBranch)
|
||||||
if (paymentInfo.bic) {
|
if (paymentInfo.accountName && !payeeAccount.getElementsByTagName('cbc:Name')[0]) {
|
||||||
|
const accountName = doc.createElement('cbc:Name');
|
||||||
|
accountName.textContent = paymentInfo.accountName;
|
||||||
|
// Insert after ID but before FinancialInstitutionBranch
|
||||||
|
const id = payeeAccount.getElementsByTagName('cbc:ID')[0];
|
||||||
|
const finInstBranch = payeeAccount.getElementsByTagName('cac:FinancialInstitutionBranch')[0];
|
||||||
|
if (finInstBranch) {
|
||||||
|
payeeAccount.insertBefore(accountName, finInstBranch);
|
||||||
|
} else if (id && id.nextSibling) {
|
||||||
|
payeeAccount.insertBefore(accountName, id.nextSibling);
|
||||||
|
} else {
|
||||||
|
payeeAccount.appendChild(accountName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add BIC and bank name
|
||||||
|
if (paymentInfo.bic || paymentInfo.bankName) {
|
||||||
let finInstBranch = payeeAccount.getElementsByTagName('cac:FinancialInstitutionBranch')[0];
|
let finInstBranch = payeeAccount.getElementsByTagName('cac:FinancialInstitutionBranch')[0];
|
||||||
if (!finInstBranch) {
|
if (!finInstBranch) {
|
||||||
finInstBranch = doc.createElement('cac:FinancialInstitutionBranch');
|
finInstBranch = doc.createElement('cac:FinancialInstitutionBranch');
|
||||||
payeeAccount.appendChild(finInstBranch);
|
payeeAccount.appendChild(finInstBranch);
|
||||||
}
|
}
|
||||||
|
|
||||||
let finInst = finInstBranch.getElementsByTagName('cac:FinancialInstitution')[0];
|
// Add BIC as branch ID
|
||||||
if (!finInst) {
|
if (paymentInfo.bic && !finInstBranch.getElementsByTagName('cbc:ID')[0]) {
|
||||||
finInst = doc.createElement('cac:FinancialInstitution');
|
const bicElement = doc.createElement('cbc:ID');
|
||||||
finInstBranch.appendChild(finInst);
|
bicElement.textContent = paymentInfo.bic;
|
||||||
|
finInstBranch.appendChild(bicElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!finInst.getElementsByTagName('cbc:ID')[0]) {
|
// Add bank name
|
||||||
const bic = doc.createElement('cbc:ID');
|
if (paymentInfo.bankName && !finInstBranch.getElementsByTagName('cbc:Name')[0]) {
|
||||||
bic.textContent = paymentInfo.bic;
|
const bankNameElement = doc.createElement('cbc:Name');
|
||||||
finInst.appendChild(bic);
|
bankNameElement.textContent = paymentInfo.bankName;
|
||||||
}
|
finInstBranch.appendChild(bankNameElement);
|
||||||
}
|
|
||||||
|
|
||||||
// Add account name
|
|
||||||
if (paymentInfo.accountName && !payeeAccount.getElementsByTagName('cbc:Name')[0]) {
|
|
||||||
const accountName = doc.createElement('cbc:Name');
|
|
||||||
accountName.textContent = paymentInfo.accountName;
|
|
||||||
// Insert after ID
|
|
||||||
const id = payeeAccount.getElementsByTagName('cbc:ID')[0];
|
|
||||||
if (id && id.nextSibling) {
|
|
||||||
payeeAccount.insertBefore(accountName, id.nextSibling);
|
|
||||||
} else {
|
|
||||||
payeeAccount.appendChild(accountName);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user