import { tap, expect } from '@git.zone/tstest/tapbundle'; import { XRechnungValidator } from '../ts/formats/validation/xrechnung.validator.js'; import type { EInvoice } from '../ts/einvoice.js'; tap.test('XRechnungValidator - Leitweg-ID validation', async () => { const validator = XRechnungValidator.create(); // Create test invoice with XRechnung profile const invoice: Partial = { invoiceNumber: 'INV-2025-001', metadata: { profileId: 'urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0', buyerReference: '04-123456789012-01' } }; const results = validator.validateXRechnung(invoice as EInvoice); // Valid Leitweg-ID should pass const leitwegErrors = results.filter(r => r.ruleId === 'XR-DE-01'); expect(leitwegErrors).toHaveLength(0); }); tap.test('XRechnungValidator - Invalid Leitweg-ID', async () => { const validator = XRechnungValidator.create(); const invoice: Partial = { invoiceNumber: 'INV-2025-002', metadata: { profileId: 'urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0', buyerReference: '4-12345-1' // Invalid format } }; const results = validator.validateXRechnung(invoice as EInvoice); // Should have Leitweg-ID format error const leitwegErrors = results.filter(r => r.ruleId === 'XR-DE-01'); expect(leitwegErrors).toHaveLength(1); expect(leitwegErrors[0].severity).toEqual('error'); }); tap.test('XRechnungValidator - IBAN validation', async () => { const validator = XRechnungValidator.create(); const invoice: Partial = { invoiceNumber: 'INV-2025-003', metadata: { profileId: 'urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0', buyerReference: 'REF-123', extensions: { paymentMeans: [ { type: 'SEPA', iban: 'DE89370400440532013000', // Valid German IBAN bic: 'COBADEFFXXX' } ] } } }; const results = validator.validateXRechnung(invoice as EInvoice); // Valid IBAN should pass const ibanErrors = results.filter(r => r.ruleId === 'XR-DE-19'); expect(ibanErrors).toHaveLength(0); }); tap.test('XRechnungValidator - Invalid IBAN checksum', async () => { const validator = XRechnungValidator.create(); const invoice: Partial = { invoiceNumber: 'INV-2025-004', metadata: { profileId: 'urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0', buyerReference: 'REF-124', extensions: { paymentMeans: [ { type: 'SEPA', iban: 'DE89370400440532013001' // Invalid checksum } ] } } }; const results = validator.validateXRechnung(invoice as EInvoice); // Should have IBAN checksum error const ibanErrors = results.filter(r => r.ruleId === 'XR-DE-19'); expect(ibanErrors).toHaveLength(1); expect(ibanErrors[0].message).toInclude('Invalid IBAN checksum'); }); tap.test('XRechnungValidator - BIC validation', async () => { const validator = XRechnungValidator.create(); const invoice: Partial = { invoiceNumber: 'INV-2025-005', metadata: { profileId: 'urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0', buyerReference: 'REF-125', extensions: { paymentMeans: [ { type: 'SEPA', iban: 'DE89370400440532013000', bic: 'COBADEFF' // Valid 8-character BIC } ] } } }; const results = validator.validateXRechnung(invoice as EInvoice); // Valid BIC should pass const bicErrors = results.filter(r => r.ruleId === 'XR-DE-20'); expect(bicErrors).toHaveLength(0); }); tap.test('XRechnungValidator - Invalid BIC format', async () => { const validator = XRechnungValidator.create(); const invoice: Partial = { invoiceNumber: 'INV-2025-006', metadata: { profileId: 'urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0', buyerReference: 'REF-126', extensions: { paymentMeans: [ { type: 'SEPA', iban: 'DE89370400440532013000', bic: 'INVALID' // Invalid BIC format } ] } } }; const results = validator.validateXRechnung(invoice as EInvoice); // Should have BIC format error const bicErrors = results.filter(r => r.ruleId === 'XR-DE-20'); expect(bicErrors).toHaveLength(1); expect(bicErrors[0].message).toInclude('Invalid BIC format'); }); tap.test('XRechnungValidator - Mandatory buyer reference', async () => { const validator = XRechnungValidator.create(); const invoice: Partial = { invoiceNumber: 'INV-2025-007', metadata: { profileId: 'urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0' // Missing buyerReference } }; const results = validator.validateXRechnung(invoice as EInvoice); // Should have mandatory buyer reference error const refErrors = results.filter(r => r.ruleId === 'XR-DE-15'); expect(refErrors).toHaveLength(1); expect(refErrors[0].severity).toEqual('error'); }); tap.test('XRechnungValidator - Seller contact validation', async () => { const validator = XRechnungValidator.create(); const invoice: Partial = { invoiceNumber: 'INV-2025-008', metadata: { profileId: 'urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0', buyerReference: 'REF-127', extensions: { sellerContact: { name: 'John Doe', email: 'john.doe@example.com', phone: '+49 30 12345678' } } } }; const results = validator.validateXRechnung(invoice as EInvoice); // Valid seller contact should pass const contactErrors = results.filter(r => r.ruleId === 'XR-DE-02'); expect(contactErrors).toHaveLength(0); }); tap.test('XRechnungValidator - Missing seller contact', async () => { const validator = XRechnungValidator.create(); const invoice: Partial = { invoiceNumber: 'INV-2025-009', metadata: { profileId: 'urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0', buyerReference: 'REF-128' // Missing sellerContact } }; const results = validator.validateXRechnung(invoice as EInvoice); // Should have missing seller contact error const contactErrors = results.filter(r => r.ruleId === 'XR-DE-02'); expect(contactErrors).toHaveLength(1); expect(contactErrors[0].severity).toEqual('error'); }); tap.test('XRechnungValidator - German VAT ID validation', async () => { const validator = XRechnungValidator.create(); const invoice: Partial = { invoiceNumber: 'INV-2025-010', from: { type: 'company' as const, name: 'Test Company', registrationDetails: { vatId: 'DE123456789' // Valid German VAT ID format } }, metadata: { profileId: 'urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0', buyerReference: 'REF-129', sellerTaxId: 'DE123456789' } }; const results = validator.validateXRechnung(invoice as EInvoice); // Valid German VAT ID should pass const vatErrors = results.filter(r => r.ruleId === 'XR-DE-04'); expect(vatErrors).toHaveLength(0); }); tap.test('XRechnungValidator - Invalid German VAT ID', async () => { const validator = XRechnungValidator.create(); const invoice: Partial = { invoiceNumber: 'INV-2025-011', metadata: { profileId: 'urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0', buyerReference: 'REF-130', sellerTaxId: 'DE12345' // Invalid - too short } }; const results = validator.validateXRechnung(invoice as EInvoice); // Should have invalid VAT ID error const vatErrors = results.filter(r => r.ruleId === 'XR-DE-04'); expect(vatErrors).toHaveLength(1); expect(vatErrors[0].message).toInclude('Invalid German VAT ID format'); }); tap.test('XRechnungValidator - Non-XRechnung invoice', async () => { const validator = XRechnungValidator.create(); const invoice: Partial = { invoiceNumber: 'INV-2025-012', metadata: { profileId: 'urn:cen.eu:en16931:2017' // Not XRechnung } }; const results = validator.validateXRechnung(invoice as EInvoice); // Should not validate non-XRechnung invoices expect(results).toHaveLength(0); }); tap.test('XRechnungValidator - SEPA country validation', async () => { const validator = XRechnungValidator.create(); const invoice: Partial = { invoiceNumber: 'INV-2025-013', metadata: { profileId: 'urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0', buyerReference: 'REF-131', extensions: { paymentMeans: [ { type: 'SEPA', iban: 'US12345678901234567890123456789' // Non-SEPA country } ] } } }; const results = validator.validateXRechnung(invoice as EInvoice); // Should have warning for non-SEPA country const sepaWarnings = results.filter(r => r.ruleId === 'XR-DE-19' && r.severity === 'warning'); expect(sepaWarnings.length).toBeGreaterThan(0); expect(sepaWarnings[0].message).toInclude('not in SEPA zone'); }); tap.test('XRechnungValidator - B2G Leitweg-ID requirement', async () => { const validator = XRechnungValidator.create(); const invoice: Partial = { invoiceNumber: 'INV-2025-014', to: { name: 'Bundesamt für Migration' // Public entity }, metadata: { profileId: 'urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0', // Missing buyerReference for B2G } }; const results = validator.validateXRechnung(invoice as EInvoice); // Should require Leitweg-ID for B2G const b2gErrors = results.filter(r => r.ruleId === 'XR-DE-15'); expect(b2gErrors).toHaveLength(1); expect(b2gErrors[0].message).toInclude('mandatory for B2G invoices'); }); tap.test('XRechnungValidator - Complete valid XRechnung invoice', async () => { const validator = XRechnungValidator.create(); const invoice: Partial = { invoiceNumber: 'INV-2025-015', from: { type: 'company' as const, name: 'Example GmbH', registrationDetails: { vatId: 'DE123456789' } }, metadata: { profileId: 'urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0', buyerReference: '991-12345678901-23', sellerTaxId: 'DE123456789', extensions: { sellerContact: { name: 'Sales Department', email: 'sales@example.de', phone: '+49 30 98765432' }, paymentMeans: [ { type: 'SEPA', iban: 'DE89370400440532013000', bic: 'COBADEFFXXX', accountName: 'Example GmbH' } ] } } }; const results = validator.validateXRechnung(invoice as EInvoice); // Complete valid invoice should have no errors const errors = results.filter(r => r.severity === 'error'); expect(errors).toHaveLength(0); }); export default tap.start();