einvoice/test/suite/einvoice_standards-compliance/test.std-02.xrechnung-cius.ts
Philipp Kunz 1fae7db72c fix(tests): update test patterns and fix assertion syntax
- Change tap test signatures from async (t) => to async () =>
- Replace t.ok(), t.notOk(), t.equal() with expect() assertions
- Fix import paths for helpers to use correct ../../helpers/ path
- Update PerformanceTracker to use instance version
- Add missing expect imports from tapbundle
- Remove t.end() calls that are no longer needed
- Ensure all tests have tap.start() for proper execution
2025-05-30 06:31:02 +00:00

320 lines
11 KiB
TypeScript

import { tap, expect } from '@git.zone/tstest/tapbundle';
import { EInvoice } from '../../../ts/index.js';
import { CorpusLoader } from '../../helpers/corpus.loader.js';
import { ValidationLevel } from '../../../ts/index.js';
tap.test('STD-02: XRechnung CIUS Compliance - should validate XRechnung Core Invoice Usage Specification', async () => {
console.log('Testing XRechnung CIUS compliance...\n');
// Test 1: XRechnung specific mandatory fields
console.log('Test 1 - XRechnung specific mandatory fields:');
const testXRechnungMandatoryFields = () => {
// Test complete XRechnung invoice
const completeInvoice = new EInvoice();
// Set required EN16931 fields
completeInvoice.id = 'XRECHNUNG-001';
completeInvoice.issueDate = new Date(2024, 0, 15);
completeInvoice.dueDate = new Date(2024, 1, 15);
// XRechnung requires buyerReference (BT-10)
completeInvoice.buyerReference = '04011000-12345-67'; // Leitweg-ID
// Set supplier (from) with electronic address (BT-34)
completeInvoice.from = {
type: 'company',
name: 'Verkäufer GmbH',
description: 'XRechnung test supplier',
email: 'seller@example.de',
address: {
streetName: 'Musterstraße',
houseNumber: '1',
postalCode: '10115',
city: 'Berlin',
country: 'DE'
},
status: 'active',
foundedDate: { year: 2020, month: 1, day: 1 },
registrationDetails: {
vatId: 'DE123456789',
registrationId: 'HRB 12345',
registrationName: 'Commercial Register'
}
};
// Set customer (to) with electronic address (BT-49)
completeInvoice.to = {
type: 'company',
name: 'Käufer AG',
description: 'XRechnung test customer',
email: 'buyer@example.de',
address: {
streetName: 'Beispielweg',
houseNumber: '2',
postalCode: '20095',
city: 'Hamburg',
country: 'DE'
},
status: 'active',
foundedDate: { year: 2018, month: 1, day: 1 },
registrationDetails: {
vatId: 'DE987654321',
registrationId: 'HRB 54321',
registrationName: 'Commercial Register'
}
};
// Add invoice items
completeInvoice.items = [{
name: 'Produkt A',
description: 'Test product for XRechnung',
unitQuantity: 10,
unitPrice: { amount: 100, currency: 'EUR' as const },
totalPrice: { amount: 1000, currency: 'EUR' as const },
vatRate: 0.19
}];
// Test missing buyer reference
const missingBuyerRef = new EInvoice();
missingBuyerRef.id = 'XRECHNUNG-002';
missingBuyerRef.issueDate = new Date(2024, 0, 15);
missingBuyerRef.from = completeInvoice.from;
missingBuyerRef.to = completeInvoice.to;
missingBuyerRef.items = completeInvoice.items;
// Missing buyerReference - XRechnung specific requirement
console.log(' ✓ Created complete XRechnung invoice with all mandatory fields');
console.log(' ✓ Created invoice missing buyer reference for validation test');
// Check that complete invoice has all required fields
expect(completeInvoice.buyerReference).toBeDefined();
expect(completeInvoice.from?.email).toBeDefined();
expect(completeInvoice.to?.email).toBeDefined();
// Check that incomplete invoice is missing buyer reference
expect(missingBuyerRef.buyerReference).toBeUndefined();
return {
completeInvoice,
missingBuyerRef
};
};
const xrechnungInvoices = testXRechnungMandatoryFields();
// Test 2: Leitweg-ID format validation
console.log('\nTest 2 - Leitweg-ID validation:');
const testLeitwegId = () => {
const validLeitwegIds = [
'04011000-12345-67',
'04011000-12345-67-001',
'991-01234-56'
];
const invalidLeitwegIds = [
'12345',
'ABC-12345-67',
'04011000-12345',
null,
undefined,
''
];
console.log(' Testing valid Leitweg-IDs:');
validLeitwegIds.forEach(id => {
// Basic format check (digits and hyphens)
const isValid = /^\d{2,8}-\d{2,5}-\d{2}(-\d{3})?$/.test(id || '');
console.log(` ${id}: ${isValid ? '✓' : '✗'}`);
expect(isValid).toEqual(true);
});
console.log(' Testing invalid Leitweg-IDs:');
invalidLeitwegIds.forEach(id => {
const isValid = /^\d{2,8}-\d{2,5}-\d{2}(-\d{3})?$/.test(id || '');
console.log(` ${id}: ${isValid ? '✓' : '✗'}`);
expect(isValid).toEqual(false);
});
};
testLeitwegId();
// Test 3: XRechnung validation concepts
console.log('\nTest 3 - XRechnung validation concepts:');
const testXRechnungValidationConcepts = async () => {
const invoice = xrechnungInvoices.completeInvoice;
// Test that invoice can be validated
try {
const validationResult = await invoice.validate(ValidationLevel.BASIC);
console.log(` ✓ Basic validation: ${validationResult.isValid ? 'passed' : 'failed'}`);
// XRechnung specific checks
const hasLeitwegId = invoice.buyerReference && /^\d{2,8}-\d{2,5}-\d{2}(-\d{3})?$/.test(invoice.buyerReference);
const hasSupplierEmail = !!invoice.from?.email;
const hasCustomerEmail = !!invoice.to?.email;
console.log(` ${hasLeitwegId ? '✓' : '✗'} Has valid Leitweg-ID format`);
console.log(` ${hasSupplierEmail ? '✓' : '✗'} Has supplier electronic address`);
console.log(` ${hasCustomerEmail ? '✓' : '✗'} Has customer electronic address`);
expect(hasLeitwegId).toEqual(true);
expect(hasSupplierEmail).toEqual(true);
expect(hasCustomerEmail).toEqual(true);
} catch (error) {
console.log(` ! Validation error: ${error.message}`);
}
};
await testXRechnungValidationConcepts();
// Test 4: Corpus XRechnung file validation
console.log('\nTest 4 - Corpus XRechnung file validation:');
const testCorpusXRechnungFiles = async () => {
const xrechnungFiles = await CorpusLoader.loadPattern('**/XRECHNUNG*.xml');
console.log(` Found ${xrechnungFiles.length} XRechnung files in corpus`);
let validCount = 0;
let errorCount = 0;
let hasBuyerRefCount = 0;
// Test first 5 files
const testFiles = xrechnungFiles.slice(0, 5);
for (const file of testFiles) {
try {
const content = await CorpusLoader.loadFile(file.path);
const invoice = new EInvoice();
await invoice.fromXmlString(content.toString());
validCount++;
// Check for XRechnung specific fields
if (invoice.buyerReference) {
hasBuyerRefCount++;
console.log(`${file.path}: Valid with buyer reference: ${invoice.buyerReference}`);
} else {
console.log(`${file.path}: Valid but missing buyer reference`);
}
} catch (error) {
errorCount++;
console.log(`${file.path}: Parse error`);
}
}
console.log(`\n Summary: ${validCount} parsed successfully, ${errorCount} errors, ${hasBuyerRefCount} with buyer reference`);
expect(validCount).toBeGreaterThan(0);
};
await testCorpusXRechnungFiles();
// Test 5: XRechnung specific code lists
console.log('\nTest 5 - XRechnung code list restrictions:');
const testXRechnungCodeLists = () => {
// XRechnung restricts certain code values
const allowedPaymentMeans = ['58', '59', '30', '42', '48', '49', '57'];
const restrictedPaymentMeans = ['1', '2', '3', '4', '5'];
console.log(' Payment means code restrictions:');
console.log(' Allowed codes:', allowedPaymentMeans.join(', '));
console.log(' Restricted codes:', restrictedPaymentMeans.join(', '));
// Test that we can create invoices with allowed codes
const invoice = new EInvoice();
invoice.paymentMeansCode = '58'; // SEPA credit transfer
expect(invoice.paymentMeansCode).toEqual('58');
console.log(' ✓ Can set allowed payment means code');
};
testXRechnungCodeLists();
// Test 6: XRechnung version and specification
console.log('\nTest 6 - XRechnung version and specification:');
const testXRechnungVersions = () => {
const supportedVersions = [
{ version: '2.0', specId: 'urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.0' },
{ version: '2.3', specId: 'urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.3' },
{ version: '3.0', specId: 'urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_3.0' }
];
console.log(' XRechnung specification identifiers:');
supportedVersions.forEach(ver => {
console.log(` Version ${ver.version}: ${ver.specId}`);
});
// Test that specification IDs follow the correct pattern
supportedVersions.forEach(ver => {
expect(ver.specId).toContain('urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung');
expect(ver.specId).toContain(ver.version);
});
console.log(' ✓ All specification identifiers follow correct pattern');
};
testXRechnungVersions();
// Test 7: German administrative requirements
console.log('\nTest 7 - German administrative requirements:');
const testGermanAdminRequirements = () => {
const requirements = {
vatIdPattern: /^DE\d{9}$/,
postalCodePattern: /^\d{5}$/,
ibanPattern: /^DE\d{2}\d{8}\d{10}$/
};
// Test valid values
const validTests = [
{ type: 'VAT ID', value: 'DE123456789', pattern: requirements.vatIdPattern },
{ type: 'Postal Code', value: '10115', pattern: requirements.postalCodePattern },
{ type: 'IBAN', value: 'DE89370400440532013000', pattern: requirements.ibanPattern }
];
console.log(' Testing German format requirements:');
validTests.forEach(test => {
const isValid = test.pattern.test(test.value);
console.log(` ${test.type}: ${test.value} - ${isValid ? '✓' : '✗'}`);
expect(isValid).toEqual(true);
});
};
testGermanAdminRequirements();
// Test 8: XRechnung business rules
console.log('\nTest 8 - XRechnung business rules:');
const testXRechnungBusinessRules = () => {
const rules = [
'BR-DE-1: Payment account must be provided for credit transfer',
'BR-DE-2: Buyer reference (Leitweg-ID) is mandatory',
'BR-DE-3: Specification identifier must reference XRechnung',
'BR-DE-15: Buyer electronic address must be provided',
'BR-DE-21: VAT identifier must follow German format'
];
console.log(' Key XRechnung business rules:');
rules.forEach(rule => {
console.log(`${rule}`);
});
// Verify our test invoice follows these rules
const invoice = xrechnungInvoices.completeInvoice;
const ruleChecks = [
{ rule: 'BR-DE-2', check: !!invoice.buyerReference, desc: 'Has buyer reference' },
{ rule: 'BR-DE-15', check: !!invoice.to?.email, desc: 'Has buyer email' },
{ rule: 'BR-DE-21', check: /^DE\d{9}$/.test(invoice.from?.registrationDetails?.vatId || ''), desc: 'VAT ID format' }
];
console.log('\n Checking compliance with test invoice:');
ruleChecks.forEach(check => {
console.log(` ${check.rule}: ${check.desc} - ${check.check ? '✓' : '✗'}`);
expect(check.check).toEqual(true);
});
};
testXRechnungBusinessRules();
console.log('\nAll XRechnung CIUS compliance tests completed successfully! ✓');
});
// Run the test
tap.start();