From 01eea9d228bcbffd36e9cd74445ce87381c20aeb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 10 Mar 2026 23:26:17 +0000 Subject: [PATCH 1/2] Initial plan From 2ab8f771782f7d5301017c47ee272c59aea29008 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 10 Mar 2026 23:37:25 +0000 Subject: [PATCH 2/2] docs: add comprehensive usage examples to README and bump version to 0.5.1 Co-authored-by: SimonLoir <17649337+SimonLoir@users.noreply.github.com> --- README.md | 329 +++++++++++++++++++++++++++++++++++++++++++++++---- package.json | 2 +- 2 files changed, 304 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 1cff8fd..7f7f1b9 100644 --- a/README.md +++ b/README.md @@ -23,44 +23,321 @@ npm install @pixeldrive/peppol-toolkit ### ESM ```typescript -import { PeppolToolkit, createToolkit } from '@pixeldrive/peppol-toolkit'; +import { PeppolToolkit } from '@pixeldrive/peppol-toolkit'; -// Using the class directly const toolkit = new PeppolToolkit(); - -// Or using the factory function -// const toolkit = createToolkit(); - -// Generate PEPPOL UBL XML from invoice data -const invoiceData = {}; -const peppolXML = toolkit.invoiceToPeppolUBL(invoiceData); -console.log(peppolXML); ``` ### CommonJS ```javascript -const { PeppolToolkit, createToolkit } = require('@pixeldrive/peppol-toolkit'); +const { PeppolToolkit } = require('@pixeldrive/peppol-toolkit'); + +const toolkit = new PeppolToolkit(); +``` + +## Usage Examples + +### Generate a PEPPOL UBL Invoice + +```typescript +import { PeppolToolkit, Invoice } from '@pixeldrive/peppol-toolkit'; + +const toolkit = new PeppolToolkit(); + +const invoice: Invoice = { + ID: 'INV-2024-001', + issueDate: '2024-01-15', + dueDate: '2024-02-15', + invoiceTypeCode: 380, + documentCurrencyCode: 'EUR', + buyerReference: 'PO-12345', + seller: { + endPoint: { scheme: '9925', id: '0123456789' }, + legalEntity: { + registrationName: 'Acme Corp', + companyId: '0123456789', + }, + name: 'Acme Corp', + address: { + streetName: '123 Seller Street', + cityName: 'Brussels', + postalZone: '1000', + country: 'BE', + }, + taxSchemeCompanyID: 'BE0123456789', + identification: [{ id: 'BE0123456789' }], + }, + buyer: { + endPoint: { scheme: '9925', id: '9876543210' }, + legalEntity: { + registrationName: 'Buyer Ltd', + companyId: '9876543210', + legalForm: 'SRL', + }, + name: 'Buyer Ltd', + address: { + streetName: '456 Buyer Avenue', + cityName: 'Amsterdam', + postalZone: '1011', + country: 'NL', + }, + taxSchemeCompanyID: 'NL9876543210', + identification: [{ id: 'NL9876543210' }], + }, + paymentMeans: [ + { + code: '30', + paymentId: 'INV-2024-001', + name: 'Bank Transfer', + financialAccount: { + id: 'BE71 0961 2345 6769', + name: 'Acme Corp', + financialInstitutionBranch: 'GEBABEBB', + }, + }, + ], + paymentTermsNote: 'Payment due within 30 days.', + taxTotal: [ + { + taxAmountCurrency: 'EUR', + taxAmount: 210.0, + subTotals: [ + { + taxableAmount: 1000, + taxAmount: 210, + taxCategory: { categoryCode: 'S', percent: 21 }, + }, + ], + }, + ], + legalMonetaryTotal: { + currency: 'EUR', + lineExtensionAmount: 1000, + taxExclusiveAmount: 1000, + taxInclusiveAmount: 1210, + prepaidAmount: 0, + payableAmount: 1210, + }, + invoiceLines: [ + { + id: '1', + invoicedQuantity: 10, + unitCode: 'EA', + lineExtensionAmount: 1000, + price: 100, + name: 'Consulting Services', + currency: 'EUR', + taxCategory: { categoryCode: 'S', percent: 21 }, + }, + ], +}; + +const xml: string = toolkit.invoiceToPeppolUBL(invoice); +console.log(xml); +``` + +### Generate a PEPPOL UBL Credit Note + +```typescript +import { PeppolToolkit, CreditNote } from '@pixeldrive/peppol-toolkit'; + +const toolkit = new PeppolToolkit(); + +const creditNote: CreditNote = { + ID: 'CN-2024-001', + issueDate: '2024-01-20', + creditNoteTypeCode: 381, + documentCurrencyCode: 'EUR', + buyerReference: 'PO-12345', + billingReference: { + invoiceDocReference: { + id: 'INV-2024-001', + issueDate: '2024-01-15', + }, + }, + seller: { + endPoint: { scheme: '9925', id: '0123456789' }, + legalEntity: { + registrationName: 'Acme Corp', + companyId: '0123456789', + }, + name: 'Acme Corp', + address: { + streetName: '123 Seller Street', + cityName: 'Brussels', + postalZone: '1000', + country: 'BE', + }, + taxSchemeCompanyID: 'BE0123456789', + identification: [{ id: 'BE0123456789' }], + }, + buyer: { + endPoint: { scheme: '9925', id: '9876543210' }, + legalEntity: { + registrationName: 'Buyer Ltd', + companyId: '9876543210', + }, + name: 'Buyer Ltd', + address: { + streetName: '456 Buyer Avenue', + cityName: 'Amsterdam', + postalZone: '1011', + country: 'NL', + }, + taxSchemeCompanyID: 'NL9876543210', + identification: [{ id: 'NL9876543210' }], + }, + taxTotal: [ + { + taxAmountCurrency: 'EUR', + taxAmount: 21.0, + subTotals: [ + { + taxableAmount: 100, + taxAmount: 21, + taxCategory: { categoryCode: 'S', percent: 21 }, + }, + ], + }, + ], + legalMonetaryTotal: { + currency: 'EUR', + lineExtensionAmount: 100, + taxExclusiveAmount: 100, + taxInclusiveAmount: 121, + prepaidAmount: 0, + payableAmount: 121, + }, + creditNoteLines: [ + { + id: '1', + invoicedQuantity: 1, + unitCode: 'EA', + lineExtensionAmount: 100, + price: 100, + name: 'Consulting Services (correction)', + currency: 'EUR', + taxCategory: { categoryCode: 'S', percent: 21 }, + }, + ], +}; + +const xml: string = toolkit.creditNoteToPeppolUBL(creditNote); +console.log(xml); +``` + +### Parse a PEPPOL UBL XML back to an Invoice or CreditNote + +```typescript +import { PeppolToolkit, Invoice, CreditNote } from '@pixeldrive/peppol-toolkit'; + +const toolkit = new PeppolToolkit(); + +// Parse an invoice XML string back into a structured Invoice object +const invoiceXml = '...'; // your UBL XML string +const invoice: Invoice = toolkit.peppolUBLToInvoice(invoiceXml); +console.log(invoice.ID); // 'INV-2024-001' +console.log(invoice.invoiceLines); // array of line items + +// Parse a credit note XML string back into a CreditNote object +const creditNoteXml = '...'; // your UBL credit note XML +const creditNote: CreditNote = toolkit.peppolUBLToCreditNote(creditNoteXml); +console.log(creditNote.ID); +``` + +### Compute Invoice Totals + +Use the static `computeTotals` helper to calculate line totals, tax amounts, and the grand total from a list of line items — following EN 16931 rounding rules. + +```typescript +import { PeppolToolkit } from '@pixeldrive/peppol-toolkit'; + +const items = [ + { price: 100, quantity: 10, taxPercent: 21 }, // 1 000.00 + 210.00 VAT + { price: 49.99, quantity: 3, taxPercent: 21 }, // 149.97 + 31.49 VAT + { price: 200, quantity: 2, taxPercent: 0 }, // 400.00 + 0.00 VAT (exempt) +]; + +const totals = PeppolToolkit.computeTotals(items); + +console.log(totals.baseAmount.toNumber()); // 1549.97 +console.log(totals.taxAmount.toNumber()); // 241.49 +console.log(totals.totalAmount.toNumber()); // 1791.46 + +// Tax amounts grouped by rate +for (const [rate, taxableAmount] of totals.taxableAmountPerRate) { + console.log(`${rate}% → taxable: ${taxableAmount}`); +} +``` + +### Look up an EAS Endpoint Scheme from a VAT Number + +`getEASFromTaxId` resolves the correct EAS (Electronic Address Scheme) identifier for a given country-prefixed VAT number. + +```typescript +import { PeppolToolkit } from '@pixeldrive/peppol-toolkit'; + +const scheme = PeppolToolkit.getEASFromTaxId('BE0123456789'); +console.log(scheme); // '9925' + +const scheme2 = PeppolToolkit.getEASFromTaxId('NL9876543210'); +console.log(scheme2); // '9944' +``` + +### Use the Built-in Example Data + +The toolkit ships ready-to-run example documents so you can test your integration without building a full document from scratch. + +```typescript +import { + PeppolToolkit, + exampleInvoice, + exampleCreditNote, +} from '@pixeldrive/peppol-toolkit'; const toolkit = new PeppolToolkit(); -const peppolXML = toolkit.invoiceToPeppolUBL({}); + +// Generate XML from the bundled example invoice +const invoiceXml = toolkit.invoiceToPeppolUBL(exampleInvoice); +console.log(invoiceXml); + +// Generate XML from the bundled example credit note +const creditNoteXml = toolkit.creditNoteToPeppolUBL(exampleCreditNote); +console.log(creditNoteXml); ``` ## API Reference -### PeppolToolkit +### `PeppolToolkit` + +The main class that provides invoice and credit note conversion functionality. + +#### Instance Methods + +| Method | Description | +|--------|-------------| +| `invoiceToPeppolUBL(invoice: Invoice): string` | Converts an `Invoice` object to a PEPPOL-compliant UBL XML string | +| `creditNoteToPeppolUBL(creditNote: CreditNote): string` | Converts a `CreditNote` object to a PEPPOL-compliant UBL XML string | +| `peppolUBLToInvoice(xml: string): Invoice` | Parses a PEPPOL UBL XML string into an `Invoice` object | +| `peppolUBLToCreditNote(xml: string): CreditNote` | Parses a PEPPOL UBL XML string into a `CreditNote` object | -The main class that provides invoice conversion functionality. +#### Static Helpers -#### Methods +| Helper | Description | +|--------|-------------| +| `PeppolToolkit.computeTotals(items: UBLLineItem[]): Totals` | Calculates line totals, tax amounts and grand total following EN 16931 rules | +| `PeppolToolkit.getEASFromTaxId(taxId: string): string` | Returns the EAS scheme code for a country-prefixed VAT number | -- `invoiceToPeppolUBL(invoice: Invoice): string` - - Converts an invoice object to PEPPOL-compliant UBL XML - - Returns: XML string formatted for PEPPOL compliance +### `createToolkit()` -### createToolkit() +Factory function that creates a new instance of `PeppolToolkit`. Equivalent to `new PeppolToolkit()`. -Factory function that creates a new instance of PeppolToolkit. +```typescript +import { createToolkit } from '@pixeldrive/peppol-toolkit'; + +const toolkit = createToolkit(); +``` ## PEPPOL BIS UBL Invoice Elements Checklist @@ -173,19 +450,19 @@ Starting from version 1.0.0, this library will follow [Semantic Versioning (SemV ## Roadmap -- [ ] Initial invoice-to-UBL XML generation API -- [ ] Define and export robust Invoice TypeScript types -- [ ] Add input validation helpers -- [ ] Support CreditNote documents +- [x] Initial invoice-to-UBL XML generation API +- [x] Define and export robust Invoice TypeScript types +- [x] Add input validation helpers +- [x] Support CreditNote documents - [ ] Implement UBL 2.1 schema validation (offline) - [ ] Implement PEPPOL BIS profile validation (offline) - [ ] Enable online validation against remote services - [ ] Support attachments/binary objects embedding (e.g., PDF) - [ ] CLI: Convert JSON invoices to UBL XML -- [ ] Documentation: Examples and recipe-style guides +- [x] Documentation: Examples and recipe-style guides - [ ] QA: Expand unit tests -Last updated: 2025-09-29 +Last updated: 2026-03-10 ## Development Scripts diff --git a/package.json b/package.json index 3621e4b..a8564bf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@pixeldrive/peppol-toolkit", - "version": "0.5.0", + "version": "0.5.1", "description": "A TypeScript toolkit for building and reading peppol UBL documents", "keywords": [ "typescript",