einvoice/test/suite/einvoice_standards-compliance/test.std-10.country-extensions.ts

317 lines
10 KiB
TypeScript
Raw Normal View History

import { tap, expect } from '@git.zone/tstest/tapbundle';
import { EInvoice } from '../../../ts/index.js';
import { InvoiceFormat } from '../../../ts/interfaces/common.js';
import { CorpusLoader } from '../../helpers/corpus.loader.js';
import { PerformanceTracker } from '../../helpers/performance.tracker.instance.js';
import * as path from 'path';
/**
* Test ID: STD-10
* Test Description: Country-Specific Extensions
* Priority: Medium
*
* This test validates handling of country-specific extensions to EN16931,
* including XRechnung (Germany), FatturaPA (Italy), and PEPPOL BIS variations.
*/
// Test 1: German XRechnung Extensions
tap.test('STD-10: German XRechnung specific requirements', async () => {
const invoice = new EInvoice();
// XRechnung specific fields
invoice.id = 'XRECHNUNG-001';
invoice.issueDate = new Date();
invoice.metadata = {
format: InvoiceFormat.XRECHNUNG,
extensions: {
'BT-DE-1': 'Payment conditions text', // German specific
'BT-DE-2': 'Buyer reference', // Leitweg-ID
'BT-DE-3': 'Project reference',
'BT-DE-4': 'Contract reference',
'BT-DE-5': 'Order reference'
}
};
// Leitweg-ID validation (German routing ID)
const leitwegId = '04011000-12345-67';
const leitwegPattern = /^\d{8,12}-\d{1,30}-\d{1,2}$/;
expect(leitwegPattern.test(leitwegId)).toBeTrue();
console.log('✓ Valid Leitweg-ID format');
// Bank transfer requirements
invoice.paymentTerms = {
method: 'SEPA',
iban: 'DE89370400440532013000',
bic: 'DEUTDEFF',
reference: 'RF18539007547034'
};
// IBAN validation for Germany
const germanIbanPattern = /^DE\d{20}$/;
expect(germanIbanPattern.test(invoice.paymentTerms.iban)).toBeTrue();
console.log('✓ Valid German IBAN format');
// XRechnung profile requirements
const xrechnungProfiles = [
'urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.0',
'urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.1',
'urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.2'
];
expect(xrechnungProfiles.length).toBeGreaterThan(0);
console.log('✓ XRechnung profile identifiers defined');
});
// Test 2: Italian FatturaPA Extensions
tap.test('STD-10: Italian FatturaPA specific requirements', async () => {
// FatturaPA specific structure
const fatturapaRequirements = {
transmissionFormat: {
FormatoTrasmissione: 'FPR12', // Private B2B
CodiceDestinatario: '0000000', // 7 digits
PECDestinatario: 'pec@example.it'
},
cedentePrestatore: {
DatiAnagrafici: {
IdFiscaleIVA: {
IdPaese: 'IT',
IdCodice: '12345678901' // 11 digits
},
CodiceFiscale: 'RSSMRA80A01H501U' // 16 chars
}
},
documentType: '1.2.1' // Version
};
// Validate Italian VAT number
const italianVATPattern = /^IT\d{11}$/;
const testVAT = 'IT' + fatturapaRequirements.cedentePrestatore.DatiAnagrafici.IdFiscaleIVA.IdCodice;
expect(italianVATPattern.test(testVAT)).toBeTrue();
console.log('✓ Valid Italian VAT number format');
// Validate Codice Fiscale
const codiceFiscalePattern = /^[A-Z]{6}\d{2}[A-Z]\d{2}[A-Z]\d{3}[A-Z]$/;
expect(codiceFiscalePattern.test(fatturapaRequirements.cedentePrestatore.DatiAnagrafici.CodiceFiscale)).toBeTrue();
console.log('✓ Valid Italian Codice Fiscale format');
// Validate Codice Destinatario
expect(fatturapaRequirements.transmissionFormat.CodiceDestinatario).toMatch(/^\d{7}$/);
console.log('✓ Valid Codice Destinatario format');
// Document numbering requirements
const italianInvoiceNumber = '2024/001';
expect(italianInvoiceNumber).toMatch(/^\d{4}\/\d+$/);
console.log('✓ Valid Italian invoice number format');
});
// Test 3: French Factur-X Extensions
tap.test('STD-10: French Factur-X specific requirements', async () => {
const invoice = new EInvoice();
invoice.id = 'FX-FR-001';
invoice.issueDate = new Date();
// French specific requirements
const frenchExtensions = {
siret: '12345678901234', // 14 digits
naf: '6201Z', // NAF/APE code
tvaIntracommunautaire: 'FR12345678901',
mentionsLegales: 'SARL au capital de 10000 EUR',
chorus: {
serviceCode: 'SERVICE123',
engagementNumber: 'ENG123456'
}
};
// Validate SIRET (14 digits)
expect(frenchExtensions.siret).toMatch(/^\d{14}$/);
console.log('✓ Valid French SIRET format');
// Validate French VAT number
const frenchVATPattern = /^FR[0-9A-Z]{2}\d{9}$/;
expect(frenchVATPattern.test(frenchExtensions.tvaIntracommunautaire)).toBeTrue();
console.log('✓ Valid French VAT number format');
// Validate NAF/APE code
expect(frenchExtensions.naf).toMatch(/^\d{4}[A-Z]$/);
console.log('✓ Valid French NAF/APE code format');
// Chorus Pro integration (French public sector)
if (frenchExtensions.chorus.serviceCode) {
console.log('✓ Chorus Pro service code present');
}
});
// Test 4: Belgian Extensions
tap.test('STD-10: Belgian e-invoicing extensions', async () => {
const belgianExtensions = {
merchantAgreementReference: 'BE-MERCH-001',
vatNumber: 'BE0123456789',
bancontact: {
enabled: true,
reference: 'BC123456'
},
languages: ['nl', 'fr', 'de'], // Belgium has 3 official languages
regionalCodes: {
flanders: 'VL',
wallonia: 'WA',
brussels: 'BR'
}
};
// Validate Belgian VAT number (BE followed by 10 digits)
expect(belgianExtensions.vatNumber).toMatch(/^BE\d{10}$/);
console.log('✓ Valid Belgian VAT number format');
// Language requirements
expect(belgianExtensions.languages).toContain('nl');
expect(belgianExtensions.languages).toContain('fr');
console.log('✓ Supports required Belgian languages');
});
// Test 5: Nordic Countries Extensions
tap.test('STD-10: Nordic countries specific requirements', async () => {
// Swedish requirements
const swedishExtensions = {
organisationNumber: '1234567890', // 10 digits
vatNumber: 'SE123456789001',
bankgiro: '123-4567',
plusgiro: '12 34 56-7',
referenceType: 'OCR', // Swedish payment reference
ocrReference: '12345678901234567890'
};
// Norwegian requirements
const norwegianExtensions = {
organisationNumber: '123456789', // 9 digits
vatNumber: 'NO123456789MVA',
kidNumber: '1234567890123', // Payment reference
iban: 'NO9386011117947'
};
// Danish requirements
const danishExtensions = {
cvrNumber: '12345678', // 8 digits
eanLocation: '5790000123456', // 13 digits
vatNumber: 'DK12345678',
nemKonto: true // Danish public payment system
};
// Validate formats
expect(swedishExtensions.vatNumber).toMatch(/^SE\d{12}$/);
console.log('✓ Valid Swedish VAT format');
expect(norwegianExtensions.vatNumber).toMatch(/^NO\d{9}MVA$/);
console.log('✓ Valid Norwegian VAT format');
expect(danishExtensions.cvrNumber).toMatch(/^\d{8}$/);
console.log('✓ Valid Danish CVR format');
});
// Test 6: PEPPOL BIS Country Variations
tap.test('STD-10: PEPPOL BIS country-specific profiles', async () => {
const peppolProfiles = {
'PEPPOL-BIS-3.0': 'Base profile',
'PEPPOL-BIS-3.0-AU': 'Australian extension',
'PEPPOL-BIS-3.0-NZ': 'New Zealand extension',
'PEPPOL-BIS-3.0-SG': 'Singapore extension',
'PEPPOL-BIS-3.0-MY': 'Malaysian extension'
};
// Country-specific identifiers
const countryIdentifiers = {
AU: { scheme: '0151', name: 'ABN' }, // Australian Business Number
NZ: { scheme: '0088', name: 'NZBN' }, // NZ Business Number
SG: { scheme: '0195', name: 'UEN' }, // Unique Entity Number
MY: { scheme: '0199', name: 'MyBRN' } // Malaysian Business Registration
};
// Test identifier schemes
for (const [country, identifier] of Object.entries(countryIdentifiers)) {
expect(identifier.scheme).toMatch(/^\d{4}$/);
console.log(`${country}: Valid PEPPOL identifier scheme ${identifier.scheme} (${identifier.name})`);
}
});
// Test 7: Tax Regime Variations
tap.test('STD-10: Country-specific tax requirements', async () => {
const countryTaxRequirements = {
DE: {
standardRate: 19,
reducedRate: 7,
reverseCharge: 'Steuerschuldnerschaft des Leistungsempfängers'
},
FR: {
standardRate: 20,
reducedRates: [10, 5.5, 2.1],
autoliquidation: 'Autoliquidation de la TVA'
},
IT: {
standardRate: 22,
reducedRates: [10, 5, 4],
splitPayment: true // Italian split payment mechanism
},
ES: {
standardRate: 21,
reducedRates: [10, 4],
canaryIslands: 'IGIC', // Different tax system
recargo: true // Equivalence surcharge
}
};
// Validate tax rates
for (const [country, tax] of Object.entries(countryTaxRequirements)) {
expect(tax.standardRate).toBeGreaterThan(0);
expect(tax.standardRate).toBeLessThan(30);
console.log(`${country}: Valid tax rates defined`);
}
});
// Test 8: Country-Specific Validation Rules
tap.test('STD-10: Country-specific validation rules', async () => {
// Test with real corpus files
const countryFiles = {
DE: await CorpusLoader.getFiles('CII_XMLRECHNUNG'),
IT: await CorpusLoader.getFiles('FATTURAPA_OFFICIAL')
};
// German validation rules
if (countryFiles.DE.length > 0) {
const germanFile = countryFiles.DE[0];
const xmlBuffer = await CorpusLoader.loadFile(germanFile);
const xmlString = xmlBuffer.toString('utf-8');
// Check for German-specific elements
const hasLeitwegId = xmlString.includes('BuyerReference') ||
xmlString.includes('BT-10');
if (hasLeitwegId) {
console.log('✓ German invoice contains buyer reference (Leitweg-ID)');
}
}
// Italian validation rules
if (countryFiles.IT.length > 0) {
const italianFile = countryFiles.IT[0];
const xmlBuffer = await CorpusLoader.loadFile(italianFile);
const xmlString = xmlBuffer.toString('utf-8');
// Check for Italian-specific structure
const hasFatturaPA = xmlString.includes('FatturaElettronica') ||
xmlString.includes('FormatoTrasmissione');
if (hasFatturaPA) {
console.log('✓ Italian invoice follows FatturaPA structure');
}
}
// Performance summary
const tracker = new PerformanceTracker('country-extensions');
const perfSummary = await tracker.getSummary();
if (perfSummary) {
console.log('\nCountry Extensions Test Performance:');
console.log(` Average: ${perfSummary.average}ms`);
}
});
tap.start();