Skip to content

fix: correct XSD element ordering for allowances and charges#107

Merged
jslno merged 1 commit intojslno:mainfrom
smnbbrv:main
Dec 11, 2025
Merged

fix: correct XSD element ordering for allowances and charges#107
jslno merged 1 commit intojslno:mainfrom
smnbbrv:main

Conversation

@smnbbrv
Copy link
Copy Markdown
Contributor

@smnbbrv smnbbrv commented Dec 10, 2025

Hi and thank you for your work on this project!

I have faced an issue today that the extended profile generates the TypeCode after other parameters in the allowances and charges and fails XSD validation. See below

<ram:ApplicableHeaderTradeSettlement>
      <ram:InvoiceCurrencyCode>EUR</ram:InvoiceCurrencyCode>
      <ram:SpecifiedTradeSettlementPaymentMeans>
        <ram:TypeCode>58</ram:TypeCode>
        <ram:PayeePartyCreditorFinancialAccount>
          <ram:IBANID>...</ram:IBANID>
        </ram:PayeePartyCreditorFinancialAccount>
      </ram:SpecifiedTradeSettlementPaymentMeans>
      <ram:ApplicableTradeTax>
        <ram:CalculatedAmount>1657.56</ram:CalculatedAmount>
        <ram:TypeCode>VAT</ram:TypeCode>
        <ram:BasisAmount>8724</ram:BasisAmount>
        <ram:CategoryCode>S</ram:CategoryCode>
        <ram:RateApplicablePercent>19</ram:RateApplicablePercent>
      </ram:ApplicableTradeTax>
      <ram:SpecifiedTradeAllowanceCharge>
        <ram:ChargeIndicator>
          <udt:Indicator>true</udt:Indicator>
        </ram:ChargeIndicator>
        <ram:ActualAmount>49.9</ram:ActualAmount>
        <ram:Reason>Speditionsversand</ram:Reason>
        <ram:CategoryTradeTax>
          <ram:CategoryCode>S</ram:CategoryCode>
          <ram:RateApplicablePercent>19</ram:RateApplicablePercent>
          <ram:TypeCode>VAT</ram:TypeCode>
        </ram:CategoryTradeTax>
      </ram:SpecifiedTradeAllowanceCharge>
      <ram:SpecifiedTradePaymentTerms>
        <ram:DueDateDateTime>
          <udt:DateTimeString format="102">20241226</udt:DateTimeString>
        </ram:DueDateDateTime>
      </ram:SpecifiedTradePaymentTerms>
      <ram:SpecifiedTradeSettlementHeaderMonetarySummation>
        <ram:LineTotalAmount>8724</ram:LineTotalAmount>
        <ram:ChargeTotalAmount>49.9</ram:ChargeTotalAmount>
        <ram:AllowanceTotalAmount>436.2</ram:AllowanceTotalAmount>
        <ram:TaxBasisTotalAmount>8337.699999999999</ram:TaxBasisTotalAmount>
        <ram:TaxTotalAmount currencyID="EUR">1657.56</ram:TaxTotalAmount>
        <ram:GrandTotalAmount>9995.26</ram:GrandTotalAmount>
        <ram:DuePayableAmount>9995.26</ram:DuePayableAmount>
      </ram:SpecifiedTradeSettlementHeaderMonetarySummation>
    </ram:ApplicableHeaderTradeSettlement>

Minimal repro:

// minimal-repro.ts - ZUGFeRD XML element ordering bug

import { zugferd } from 'node-zugferd';
import { EXTENDED } from 'node-zugferd/profile/extended';

const invoicer = zugferd({ profile: EXTENDED, strict: true });

const data = {
  issueDate: '2024-11-26',
  number: 'INV-2024-001',
  typeCode: '380',
  transaction: {
    line: [
      {
        identifier: 'ITEM-001',
        tradeProduct: { name: 'Test Product' },
        tradeAgreement: {
          grossTradePrice: { chargeAmount: 100 },
          netTradePrice: { chargeAmount: 100 },
        },
        tradeDelivery: {
          billedQuantity: { amount: 1, unitMeasureCode: 'C62' },
        },
        tradeSettlement: {
          tradeTax: {
            typeCode: 'VAT',
            categoryCode: 'S',
            rateApplicablePercent: 19,
          },
          monetarySummation: { lineTotalAmount: 100 },
        },
      },
    ],
    tradeAgreement: {
      seller: {
        name: 'Test Seller GmbH',
        postalAddress: {
          line1: 'Test Street 1',
          city: 'Berlin',
          postCode: '10115',
          countryCode: 'DE',
        },
        taxRegistration: { vatIdentifier: 'DE123456789' },
      },
      buyer: {
        name: 'Test Buyer',
        postalAddress: {
          line1: 'Buyer Street 1',
          city: 'Munich',
          postCode: '80331',
          countryCode: 'DE',
        },
      },
    },
    tradeDelivery: {
      information: { deliveryDate: '2024-11-25' },
    },
    tradeSettlement: {
      currencyCode: 'EUR',
      vatBreakdown: [
        {
          calculatedAmount: 19,
          typeCode: 'VAT',
          basisAmount: 100,
          categoryCode: 'S',
          rateApplicablePercent: 19,
        },
      ],
      // THIS CAUSES THE BUG - charges with categoryTradeTax
      charges: [
        {
          actualAmount: 9.9,
          reason: 'Shipping',
          categoryTradeTax: {
            categoryCode: 'S',
            vatRate: 19,
          },
        },
      ],
      monetarySummation: {
        lineTotalAmount: 100,
        chargeTotalAmount: 9.9,
        allowanceTotalAmount: 0,
        taxBasisTotalAmount: 109.9,
        taxTotal: { amount: 20.88, currencyCode: 'EUR' },
        grandTotalAmount: 130.78,
        duePayableAmount: 130.78,
      },
    },
  },
} satisfies typeof invoicer.$Infer.Schema;

async function main() {
  const invoice = invoicer.create(data);
  const xml = await invoice.toXML();
  console.log(xml);
}

main().catch(console.error);

The fix I found works well, not sure however how does it fit into the whole project architecture and idea.

@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented Dec 10, 2025

@smnbbrv is attempting to deploy a commit to the better-auth-extended Team on Vercel.

A member of the Team first needs to authorize it.

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Dec 10, 2025

Open in StackBlitz

npm i https://pkg.pr.new/jslno/node-zugferd/@node-zugferd/api@107
npm i https://pkg.pr.new/jslno/node-zugferd@107

commit: 7ec76ca

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 1 file

@smnbbrv smnbbrv changed the title fix: process additionalXml before shape fields for correct XSD element ordering correct XSD element ordering for allowances and charges Dec 10, 2025
@smnbbrv
Copy link
Copy Markdown
Contributor Author

smnbbrv commented Dec 10, 2025

@jslno hope it goes well. I'm happy to have a feedback

@jslno jslno changed the title correct XSD element ordering for allowances and charges fix: correct XSD element ordering for allowances and charges Dec 11, 2025
Copy link
Copy Markdown
Owner

@jslno jslno left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Im currently quite busy, so not sure when I'll find time to publish

@jslno jslno merged commit d311303 into jslno:main Dec 11, 2025
3 of 4 checks passed
@smnbbrv
Copy link
Copy Markdown
Contributor Author

smnbbrv commented Dec 11, 2025

@jslno thanks! I have hardcoded it ATM in the project, so no hurry

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants