@@ -23,44 +23,321 @@ npm install @pixeldrive/peppol-toolkit
2323### ESM
2424
2525``` typescript
26- import { PeppolToolkit , createToolkit } from ' @pixeldrive/peppol-toolkit' ;
26+ import { PeppolToolkit } from ' @pixeldrive/peppol-toolkit' ;
2727
28- // Using the class directly
2928const toolkit = new PeppolToolkit ();
30-
31- // Or using the factory function
32- // const toolkit = createToolkit();
33-
34- // Generate PEPPOL UBL XML from invoice data
35- const invoiceData = {};
36- const peppolXML = toolkit .invoiceToPeppolUBL (invoiceData );
37- console .log (peppolXML );
3829```
3930
4031### CommonJS
4132
4233``` javascript
43- const { PeppolToolkit , createToolkit } = require (' @pixeldrive/peppol-toolkit' );
34+ const { PeppolToolkit } = require (' @pixeldrive/peppol-toolkit' );
35+
36+ const toolkit = new PeppolToolkit ();
37+ ```
38+
39+ ## Usage Examples
40+
41+ ### Generate a PEPPOL UBL Invoice
42+
43+ ``` typescript
44+ import { PeppolToolkit , Invoice } from ' @pixeldrive/peppol-toolkit' ;
45+
46+ const toolkit = new PeppolToolkit ();
47+
48+ const invoice: Invoice = {
49+ ID: ' INV-2024-001' ,
50+ issueDate: ' 2024-01-15' ,
51+ dueDate: ' 2024-02-15' ,
52+ invoiceTypeCode: 380 ,
53+ documentCurrencyCode: ' EUR' ,
54+ buyerReference: ' PO-12345' ,
55+ seller: {
56+ endPoint: { scheme: ' 9925' , id: ' 0123456789' },
57+ legalEntity: {
58+ registrationName: ' Acme Corp' ,
59+ companyId: ' 0123456789' ,
60+ },
61+ name: ' Acme Corp' ,
62+ address: {
63+ streetName: ' 123 Seller Street' ,
64+ cityName: ' Brussels' ,
65+ postalZone: ' 1000' ,
66+ country: ' BE' ,
67+ },
68+ taxSchemeCompanyID: ' BE0123456789' ,
69+ identification: [{ id: ' BE0123456789' }],
70+ },
71+ buyer: {
72+ endPoint: { scheme: ' 9925' , id: ' 9876543210' },
73+ legalEntity: {
74+ registrationName: ' Buyer Ltd' ,
75+ companyId: ' 9876543210' ,
76+ legalForm: ' SRL' ,
77+ },
78+ name: ' Buyer Ltd' ,
79+ address: {
80+ streetName: ' 456 Buyer Avenue' ,
81+ cityName: ' Amsterdam' ,
82+ postalZone: ' 1011' ,
83+ country: ' NL' ,
84+ },
85+ taxSchemeCompanyID: ' NL9876543210' ,
86+ identification: [{ id: ' NL9876543210' }],
87+ },
88+ paymentMeans: [
89+ {
90+ code: ' 30' ,
91+ paymentId: ' INV-2024-001' ,
92+ name: ' Bank Transfer' ,
93+ financialAccount: {
94+ id: ' BE71 0961 2345 6769' ,
95+ name: ' Acme Corp' ,
96+ financialInstitutionBranch: ' GEBABEBB' ,
97+ },
98+ },
99+ ],
100+ paymentTermsNote: ' Payment due within 30 days.' ,
101+ taxTotal: [
102+ {
103+ taxAmountCurrency: ' EUR' ,
104+ taxAmount: 210.0 ,
105+ subTotals: [
106+ {
107+ taxableAmount: 1000 ,
108+ taxAmount: 210 ,
109+ taxCategory: { categoryCode: ' S' , percent: 21 },
110+ },
111+ ],
112+ },
113+ ],
114+ legalMonetaryTotal: {
115+ currency: ' EUR' ,
116+ lineExtensionAmount: 1000 ,
117+ taxExclusiveAmount: 1000 ,
118+ taxInclusiveAmount: 1210 ,
119+ prepaidAmount: 0 ,
120+ payableAmount: 1210 ,
121+ },
122+ invoiceLines: [
123+ {
124+ id: ' 1' ,
125+ invoicedQuantity: 10 ,
126+ unitCode: ' EA' ,
127+ lineExtensionAmount: 1000 ,
128+ price: 100 ,
129+ name: ' Consulting Services' ,
130+ currency: ' EUR' ,
131+ taxCategory: { categoryCode: ' S' , percent: 21 },
132+ },
133+ ],
134+ };
135+
136+ const xml: string = toolkit .invoiceToPeppolUBL (invoice );
137+ console .log (xml );
138+ ```
139+
140+ ### Generate a PEPPOL UBL Credit Note
141+
142+ ``` typescript
143+ import { PeppolToolkit , CreditNote } from ' @pixeldrive/peppol-toolkit' ;
144+
145+ const toolkit = new PeppolToolkit ();
146+
147+ const creditNote: CreditNote = {
148+ ID: ' CN-2024-001' ,
149+ issueDate: ' 2024-01-20' ,
150+ creditNoteTypeCode: 381 ,
151+ documentCurrencyCode: ' EUR' ,
152+ buyerReference: ' PO-12345' ,
153+ billingReference: {
154+ invoiceDocReference: {
155+ id: ' INV-2024-001' ,
156+ issueDate: ' 2024-01-15' ,
157+ },
158+ },
159+ seller: {
160+ endPoint: { scheme: ' 9925' , id: ' 0123456789' },
161+ legalEntity: {
162+ registrationName: ' Acme Corp' ,
163+ companyId: ' 0123456789' ,
164+ },
165+ name: ' Acme Corp' ,
166+ address: {
167+ streetName: ' 123 Seller Street' ,
168+ cityName: ' Brussels' ,
169+ postalZone: ' 1000' ,
170+ country: ' BE' ,
171+ },
172+ taxSchemeCompanyID: ' BE0123456789' ,
173+ identification: [{ id: ' BE0123456789' }],
174+ },
175+ buyer: {
176+ endPoint: { scheme: ' 9925' , id: ' 9876543210' },
177+ legalEntity: {
178+ registrationName: ' Buyer Ltd' ,
179+ companyId: ' 9876543210' ,
180+ },
181+ name: ' Buyer Ltd' ,
182+ address: {
183+ streetName: ' 456 Buyer Avenue' ,
184+ cityName: ' Amsterdam' ,
185+ postalZone: ' 1011' ,
186+ country: ' NL' ,
187+ },
188+ taxSchemeCompanyID: ' NL9876543210' ,
189+ identification: [{ id: ' NL9876543210' }],
190+ },
191+ taxTotal: [
192+ {
193+ taxAmountCurrency: ' EUR' ,
194+ taxAmount: 21.0 ,
195+ subTotals: [
196+ {
197+ taxableAmount: 100 ,
198+ taxAmount: 21 ,
199+ taxCategory: { categoryCode: ' S' , percent: 21 },
200+ },
201+ ],
202+ },
203+ ],
204+ legalMonetaryTotal: {
205+ currency: ' EUR' ,
206+ lineExtensionAmount: 100 ,
207+ taxExclusiveAmount: 100 ,
208+ taxInclusiveAmount: 121 ,
209+ prepaidAmount: 0 ,
210+ payableAmount: 121 ,
211+ },
212+ creditNoteLines: [
213+ {
214+ id: ' 1' ,
215+ invoicedQuantity: 1 ,
216+ unitCode: ' EA' ,
217+ lineExtensionAmount: 100 ,
218+ price: 100 ,
219+ name: ' Consulting Services (correction)' ,
220+ currency: ' EUR' ,
221+ taxCategory: { categoryCode: ' S' , percent: 21 },
222+ },
223+ ],
224+ };
225+
226+ const xml: string = toolkit .creditNoteToPeppolUBL (creditNote );
227+ console .log (xml );
228+ ```
229+
230+ ### Parse a PEPPOL UBL XML back to an Invoice or CreditNote
231+
232+ ``` typescript
233+ import { PeppolToolkit , Invoice , CreditNote } from ' @pixeldrive/peppol-toolkit' ;
234+
235+ const toolkit = new PeppolToolkit ();
236+
237+ // Parse an invoice XML string back into a structured Invoice object
238+ const invoiceXml = ' <?xml version="1.0"?>...' ; // your UBL XML string
239+ const invoice: Invoice = toolkit .peppolUBLToInvoice (invoiceXml );
240+ console .log (invoice .ID ); // 'INV-2024-001'
241+ console .log (invoice .invoiceLines ); // array of line items
242+
243+ // Parse a credit note XML string back into a CreditNote object
244+ const creditNoteXml = ' <?xml version="1.0"?>...' ; // your UBL credit note XML
245+ const creditNote: CreditNote = toolkit .peppolUBLToCreditNote (creditNoteXml );
246+ console .log (creditNote .ID );
247+ ```
248+
249+ ### Compute Invoice Totals
250+
251+ 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.
252+
253+ ``` typescript
254+ import { PeppolToolkit } from ' @pixeldrive/peppol-toolkit' ;
255+
256+ const items = [
257+ { price: 100 , quantity: 10 , taxPercent: 21 }, // 1 000.00 + 210.00 VAT
258+ { price: 49.99 , quantity: 3 , taxPercent: 21 }, // 149.97 + 31.49 VAT
259+ { price: 200 , quantity: 2 , taxPercent: 0 }, // 400.00 + 0.00 VAT (exempt)
260+ ];
261+
262+ const totals = PeppolToolkit .computeTotals (items );
263+
264+ console .log (totals .baseAmount .toNumber ()); // 1549.97
265+ console .log (totals .taxAmount .toNumber ()); // 241.49
266+ console .log (totals .totalAmount .toNumber ()); // 1791.46
267+
268+ // Tax amounts grouped by rate
269+ for (const [rate, taxableAmount] of totals .taxableAmountPerRate ) {
270+ console .log (` ${rate }% → taxable: ${taxableAmount } ` );
271+ }
272+ ```
273+
274+ ### Look up an EAS Endpoint Scheme from a VAT Number
275+
276+ ` getEASFromTaxId ` resolves the correct EAS (Electronic Address Scheme) identifier for a given country-prefixed VAT number.
277+
278+ ``` typescript
279+ import { PeppolToolkit } from ' @pixeldrive/peppol-toolkit' ;
280+
281+ const scheme = PeppolToolkit .getEASFromTaxId (' BE0123456789' );
282+ console .log (scheme ); // '9925'
283+
284+ const scheme2 = PeppolToolkit .getEASFromTaxId (' NL9876543210' );
285+ console .log (scheme2 ); // '9944'
286+ ```
287+
288+ ### Use the Built-in Example Data
289+
290+ The toolkit ships ready-to-run example documents so you can test your integration without building a full document from scratch.
291+
292+ ``` typescript
293+ import {
294+ PeppolToolkit ,
295+ exampleInvoice ,
296+ exampleCreditNote ,
297+ } from ' @pixeldrive/peppol-toolkit' ;
44298
45299const toolkit = new PeppolToolkit ();
46- const peppolXML = toolkit .invoiceToPeppolUBL ({});
300+
301+ // Generate XML from the bundled example invoice
302+ const invoiceXml = toolkit .invoiceToPeppolUBL (exampleInvoice );
303+ console .log (invoiceXml );
304+
305+ // Generate XML from the bundled example credit note
306+ const creditNoteXml = toolkit .creditNoteToPeppolUBL (exampleCreditNote );
307+ console .log (creditNoteXml );
47308```
48309
49310## API Reference
50311
51- ### PeppolToolkit
312+ ### ` PeppolToolkit `
313+
314+ The main class that provides invoice and credit note conversion functionality.
315+
316+ #### Instance Methods
317+
318+ | Method | Description |
319+ | --------| -------------|
320+ | ` invoiceToPeppolUBL(invoice: Invoice): string ` | Converts an ` Invoice ` object to a PEPPOL-compliant UBL XML string |
321+ | ` creditNoteToPeppolUBL(creditNote: CreditNote): string ` | Converts a ` CreditNote ` object to a PEPPOL-compliant UBL XML string |
322+ | ` peppolUBLToInvoice(xml: string): Invoice ` | Parses a PEPPOL UBL XML string into an ` Invoice ` object |
323+ | ` peppolUBLToCreditNote(xml: string): CreditNote ` | Parses a PEPPOL UBL XML string into a ` CreditNote ` object |
52324
53- The main class that provides invoice conversion functionality.
325+ #### Static Helpers
54326
55- #### Methods
327+ | Helper | Description |
328+ | --------| -------------|
329+ | ` PeppolToolkit.computeTotals(items: UBLLineItem[]): Totals ` | Calculates line totals, tax amounts and grand total following EN 16931 rules |
330+ | ` PeppolToolkit.getEASFromTaxId(taxId: string): string ` | Returns the EAS scheme code for a country-prefixed VAT number |
56331
57- - ` invoiceToPeppolUBL(invoice: Invoice): string `
58- - Converts an invoice object to PEPPOL-compliant UBL XML
59- - Returns: XML string formatted for PEPPOL compliance
332+ ### ` createToolkit() `
60333
61- ### createToolkit()
334+ Factory function that creates a new instance of ` PeppolToolkit ` . Equivalent to ` new PeppolToolkit() ` .
62335
63- Factory function that creates a new instance of PeppolToolkit.
336+ ``` typescript
337+ import { createToolkit } from ' @pixeldrive/peppol-toolkit' ;
338+
339+ const toolkit = createToolkit ();
340+ ```
64341
65342## PEPPOL BIS UBL Invoice Elements Checklist
66343
@@ -173,19 +450,19 @@ Starting from version 1.0.0, this library will follow [Semantic Versioning (SemV
173450
174451## Roadmap
175452
176- - [ ] Initial invoice-to-UBL XML generation API
177- - [ ] Define and export robust Invoice TypeScript types
178- - [ ] Add input validation helpers
179- - [ ] Support CreditNote documents
453+ - [x ] Initial invoice-to-UBL XML generation API
454+ - [x ] Define and export robust Invoice TypeScript types
455+ - [x ] Add input validation helpers
456+ - [x ] Support CreditNote documents
180457- [ ] Implement UBL 2.1 schema validation (offline)
181458- [ ] Implement PEPPOL BIS profile validation (offline)
182459- [ ] Enable online validation against remote services
183460- [ ] Support attachments/binary objects embedding (e.g., PDF)
184461- [ ] CLI: Convert JSON invoices to UBL XML
185- - [ ] Documentation: Examples and recipe-style guides
462+ - [x ] Documentation: Examples and recipe-style guides
186463- [ ] QA: Expand unit tests
187464
188- Last updated: 2025-09-29
465+ Last updated: 2026-03-10
189466
190467## Development Scripts
191468
0 commit comments