Skip to content

Commit d4fea1d

Browse files
committed
Fix facturX gen, now using BASIC profile
1 parent 3f88ce1 commit d4fea1d

File tree

3 files changed

+19
-19
lines changed

3 files changed

+19
-19
lines changed

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.3.1
1+
1.3.2

backend/src/utils/facturx.ts

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export function generateFacturX22XML(
5757
const issue = fmtDateYYYYMMDD(invoice.issueDate) || fmtDateYYYYMMDD(new Date()) || "";
5858

5959
// BASIC profile - minimal yet compliant
60-
const profileUrn = "urn:factur-x.eu:1p0:basic";
60+
const profileUrn = "urn:cen.eu:en16931:2017#compliant#urn:factur-x.eu:1p0:basic";
6161

6262
// Tax summary
6363
const taxes = (invoice.taxes && invoice.taxes.length > 0)
@@ -83,7 +83,7 @@ export function generateFacturX22XML(
8383
${invoice.notes ? `<ram:IncludedNote><ram:Content>${xmlEscape(invoice.notes)}</ram:Content></ram:IncludedNote>` : ""}
8484
</rsm:ExchangedDocument>`;
8585

86-
// BASIC WL: Simplified seller party - only essential elements
86+
// BASIC: Simplified seller party - only essential elements
8787
const sellerParty = `
8888
<ram:SellerTradeParty>
8989
<ram:Name>${xmlEscape(business.companyName)}</ram:Name>
@@ -92,11 +92,11 @@ export function generateFacturX22XML(
9292
</ram:PostalTradeAddress>
9393
${isLikelyVatId(business.companyTaxId) ? `
9494
<ram:SpecifiedTaxRegistration>
95-
<ram:ID schemeID="VA">${xmlEscape(business.companyTaxId!)}</ram:ID>
95+
<ram:ID schemeID="VA">${xmlEscape((business.companyCountryCode || opts.sellerCountryCode || "DE") + business.companyTaxId!)}</ram:ID>
9696
</ram:SpecifiedTaxRegistration>` : ""}
9797
</ram:SellerTradeParty>`;
9898

99-
// BASIC WL: Simplified buyer party - only essential elements
99+
// BASIC: Simplified buyer party - only essential elements
100100
const buyer = invoice.customer;
101101
const buyerParty = `
102102
<ram:BuyerTradeParty>
@@ -106,7 +106,7 @@ export function generateFacturX22XML(
106106
</ram:PostalTradeAddress>
107107
${isLikelyVatId(buyer.taxId) ? `
108108
<ram:SpecifiedTaxRegistration>
109-
<ram:ID schemeID="VA">${xmlEscape(buyer.taxId!)}</ram:ID>
109+
<ram:ID schemeID="VA">${xmlEscape((buyer.countryCode || opts.buyerCountryCode || "DE") + buyer.taxId!)}</ram:ID>
110110
</ram:SpecifiedTaxRegistration>` : ""}
111111
</ram:BuyerTradeParty>`;
112112

@@ -121,7 +121,7 @@ export function generateFacturX22XML(
121121
const paymentTerms = business.paymentTerms || invoice.paymentTerms;
122122
const headerTaxes = (taxes.length > 0 ? taxes : [{ percent: 0, taxable: Math.max(0, (invoice.subtotal || 0) - (invoice.discountAmount || 0)), amount: 0 }]);
123123

124-
// BASIC WL: Simplified settlement with correct element order
124+
// BASIC: Simplified settlement with correct element order
125125
const headerSettlement = `
126126
<ram:ApplicableHeaderTradeSettlement>
127127
<ram:InvoiceCurrencyCode>${xmlEscape(currency)}</ram:InvoiceCurrencyCode>
@@ -134,23 +134,23 @@ export function generateFacturX22XML(
134134
</ram:SpecifiedTradeSettlementPaymentMeans>` : ""}
135135
${headerTaxes.map((t) => `
136136
<ram:ApplicableTradeTax>
137-
<ram:CalculatedAmount currencyID="${xmlEscape(currency)}">${decimals(t.amount)}</ram:CalculatedAmount>
137+
<ram:CalculatedAmount>${decimals(t.amount)}</ram:CalculatedAmount>
138138
<ram:TypeCode>VAT</ram:TypeCode>
139-
<ram:BasisAmount currencyID="${xmlEscape(currency)}">${decimals(t.taxable)}</ram:BasisAmount>
139+
<ram:BasisAmount>${decimals(t.taxable)}</ram:BasisAmount>
140140
<ram:CategoryCode>${taxCategoryId(t.percent)}</ram:CategoryCode>
141141
<ram:RateApplicablePercent>${decimals(t.percent)}</ram:RateApplicablePercent>
142142
</ram:ApplicableTradeTax>`).join("")}
143143
${paymentTerms ? `<ram:SpecifiedTradePaymentTerms><ram:Description>${xmlEscape(paymentTerms)}</ram:Description></ram:SpecifiedTradePaymentTerms>` : ""}
144144
<ram:SpecifiedTradeSettlementHeaderMonetarySummation>
145-
<ram:LineTotalAmount currencyID="${xmlEscape(currency)}">${decimals(invoice.subtotal)}</ram:LineTotalAmount>
146-
<ram:TaxBasisTotalAmount currencyID="${xmlEscape(currency)}">${decimals(Math.max(0, invoice.subtotal - invoice.discountAmount))}</ram:TaxBasisTotalAmount>
145+
<ram:LineTotalAmount>${decimals(invoice.subtotal)}</ram:LineTotalAmount>
146+
<ram:TaxBasisTotalAmount>${decimals(Math.max(0, invoice.subtotal - invoice.discountAmount))}</ram:TaxBasisTotalAmount>
147147
<ram:TaxTotalAmount currencyID="${xmlEscape(currency)}">${decimals(invoice.taxAmount)}</ram:TaxTotalAmount>
148-
<ram:GrandTotalAmount currencyID="${xmlEscape(currency)}">${decimals(invoice.total)}</ram:GrandTotalAmount>
149-
<ram:DuePayableAmount currencyID="${xmlEscape(currency)}">${decimals(invoice.total)}</ram:DuePayableAmount>
148+
<ram:GrandTotalAmount>${decimals(invoice.total)}</ram:GrandTotalAmount>
149+
<ram:DuePayableAmount>${decimals(invoice.total)}</ram:DuePayableAmount>
150150
</ram:SpecifiedTradeSettlementHeaderMonetarySummation>
151151
</ram:ApplicableHeaderTradeSettlement>`;
152152

153-
// BASIC WL: Essential line items only
153+
// BASIC: Essential line items only
154154
const linesXml = invoice.items.map((it, idx) => {
155155
const qty = Number(it.quantity) || 0;
156156
const unit = Number(it.unitPrice) || 0;
@@ -167,7 +167,7 @@ export function generateFacturX22XML(
167167
</ram:SpecifiedTradeProduct>
168168
<ram:SpecifiedLineTradeAgreement>
169169
<ram:NetPriceProductTradePrice>
170-
<ram:ChargeAmount currencyID="${xmlEscape(currency)}">${decimals(unit)}</ram:ChargeAmount>
170+
<ram:ChargeAmount>${decimals(unit)}</ram:ChargeAmount>
171171
</ram:NetPriceProductTradePrice>
172172
</ram:SpecifiedLineTradeAgreement>
173173
<ram:SpecifiedLineTradeDelivery>
@@ -180,19 +180,19 @@ export function generateFacturX22XML(
180180
<ram:RateApplicablePercent>${decimals(lineRate)}</ram:RateApplicablePercent>
181181
</ram:ApplicableTradeTax>
182182
<ram:SpecifiedTradeSettlementLineMonetarySummation>
183-
<ram:LineTotalAmount currencyID="${xmlEscape(currency)}">${decimals(lineTotal)}</ram:LineTotalAmount>
183+
<ram:LineTotalAmount>${decimals(lineTotal)}</ram:LineTotalAmount>
184184
</ram:SpecifiedTradeSettlementLineMonetarySummation>
185185
</ram:SpecifiedLineTradeSettlement>
186186
</ram:IncludedSupplyChainTradeLineItem>`;
187187
}).join("");
188188

189-
// Correct element order for BASIC WL
189+
// Correct element order for BASIC
190190
const trx = `
191191
<rsm:SupplyChainTradeTransaction>
192+
${linesXml}
192193
${headerAgreement}
193194
<ram:ApplicableHeaderTradeDelivery />
194195
${headerSettlement}
195-
${linesXml}
196196
</rsm:SupplyChainTradeTransaction>`;
197197

198198
const xml = `<?xml version="1.0" encoding="UTF-8"?>

frontend/routes/settings.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,7 @@ export default function SettingsPage(props: PageProps<Data & { demoMode: boolean
531531
<div class="label"><span class="label-text">Default XML Profile</span></div>
532532
<select name="xmlProfileId" class="select select-bordered w-full" value={xmlProfileId}>
533533
<option value="ubl21">UBL 2.1 (PEPPOL BIS)</option>
534-
<option value="facturx22">Factur‑X / ZUGFeRD 2.2 (BASIC WL)</option>
534+
<option value="facturx22">Factur‑X / ZUGFeRD 2.2 (BASIC)</option>
535535
<option value="fatturapa">FatturaPA 1.9</option>
536536
</select>
537537
</label>

0 commit comments

Comments
 (0)