fix(compliance): improve compliance

This commit is contained in:
2025-05-30 04:29:13 +00:00
parent 960bbc2208
commit 0ba55dcb60
14 changed files with 1270 additions and 1095 deletions

View File

@ -1,13 +1,13 @@
import { tap } from '@git.zone/tstest/tapbundle';
import { tap, expect } from '@git.zone/tstest/tapbundle';
import * as path from 'path';
import { EInvoice } from '../../../ts/index.js';
import { PerformanceTracker } from '../../helpers/performance.tracker.js';
import { PerformanceTracker } from '../../helpers/performance.tracker.instance.js';
import { CorpusLoader } from '../../helpers/corpus.loader.js';
tap.test('STD-04: ZUGFeRD 2.1 Compliance - should validate ZUGFeRD 2.1 standard compliance', async (t) => {
tap.test('STD-04: ZUGFeRD 2.1 Compliance - should validate ZUGFeRD 2.1 standard compliance', async () => {
const einvoice = new EInvoice();
const corpusLoader = new CorpusLoader();
const performanceTracker = new PerformanceTracker('STD-04', 'ZUGFeRD 2.1 Compliance');
const performanceTracker = new PerformanceTracker('STD-04: ZUGFeRD 2.1 Compliance');
// Test 1: ZUGFeRD 2.1 profile validation
const profileValidation = await performanceTracker.measureAsync(
@ -34,8 +34,8 @@ tap.test('STD-04: ZUGFeRD 2.1 Compliance - should validate ZUGFeRD 2.1 standard
}
);
t.ok(profileValidation.result.length === 5, 'Should validate all ZUGFeRD 2.1 profiles');
t.ok(profileValidation.result.find(p => p.profile === 'EN16931'), 'Should include EN16931 profile');
expect(profileValidation.length).toEqual(5);
expect(profileValidation.find(p => p.profile === 'EN16931')).toBeTruthy();
// Test 2: ZUGFeRD 2.1 field mapping
const fieldMapping = await performanceTracker.measureAsync(
@ -85,8 +85,8 @@ tap.test('STD-04: ZUGFeRD 2.1 Compliance - should validate ZUGFeRD 2.1 standard
}
);
t.ok(fieldMapping.result.totalMappings > 15, 'Should have comprehensive field mappings');
t.ok(fieldMapping.result.categories.document > 0, 'Should map document level fields');
expect(fieldMapping.totalMappings).toBeGreaterThan(15);
expect(fieldMapping.categories.document).toBeGreaterThan(0);
// Test 3: ZUGFeRD 2.1 namespace validation
const namespaceValidation = await performanceTracker.measureAsync(
@ -118,8 +118,8 @@ tap.test('STD-04: ZUGFeRD 2.1 Compliance - should validate ZUGFeRD 2.1 standard
}
);
t.ok(namespaceValidation.result.namespaceCount >= 5, 'Should define required namespaces');
t.ok(namespaceValidation.result.rootElement === 'rsm:CrossIndustryInvoice', 'Should use correct root element');
expect(namespaceValidation.namespaceCount).toBeGreaterThan(4);
expect(namespaceValidation.rootElement).toEqual('rsm:CrossIndustryInvoice');
// Test 4: ZUGFeRD 2.1 code list validation
const codeListValidation = await performanceTracker.measureAsync(
@ -161,8 +161,8 @@ tap.test('STD-04: ZUGFeRD 2.1 Compliance - should validate ZUGFeRD 2.1 standard
}
);
t.ok(codeListValidation.result.codeListCount >= 8, 'Should validate multiple code lists');
t.ok(codeListValidation.result.totalCodes > 50, 'Should have comprehensive code coverage');
expect(codeListValidation.codeListCount).toBeGreaterThan(7);
expect(codeListValidation.totalCodes).toBeGreaterThan(50);
// Test 5: ZUGFeRD 2.1 calculation rules
const calculationRules = await performanceTracker.measureAsync(
@ -209,8 +209,8 @@ tap.test('STD-04: ZUGFeRD 2.1 Compliance - should validate ZUGFeRD 2.1 standard
}
);
t.ok(calculationRules.result.ruleCount >= 6, 'Should include calculation rules');
t.ok(calculationRules.result.validationTypes.includes('arithmetic'), 'Should validate arithmetic calculations');
expect(calculationRules.ruleCount).toBeGreaterThan(5);
expect(calculationRules.validationTypes).toContain('arithmetic');
// Test 6: ZUGFeRD 2.1 business rules
const businessRules = await performanceTracker.measureAsync(
@ -261,8 +261,8 @@ tap.test('STD-04: ZUGFeRD 2.1 Compliance - should validate ZUGFeRD 2.1 standard
}
);
t.ok(businessRules.result.totalRules > 15, 'Should have comprehensive business rules');
t.ok(businessRules.result.categories.length >= 5, 'Should cover all major categories');
expect(businessRules.totalRules).toBeGreaterThan(15);
expect(businessRules.categories.length).toBeGreaterThan(4);
// Test 7: ZUGFeRD 2.1 attachment handling
const attachmentHandling = await performanceTracker.measureAsync(
@ -301,8 +301,8 @@ tap.test('STD-04: ZUGFeRD 2.1 Compliance - should validate ZUGFeRD 2.1 standard
}
);
t.ok(attachmentHandling.result.xmlFilename === 'factur-x.xml', 'Should use standard XML filename');
t.ok(attachmentHandling.result.pdfVersion === 'PDF/A-3', 'Should require PDF/A-3');
expect(attachmentHandling.xmlFilename).toEqual('factur-x.xml');
expect(attachmentHandling.pdfVersion).toEqual('PDF/A-3');
// Test 8: Profile-specific validation
const profileSpecificValidation = await performanceTracker.measureAsync(
@ -348,8 +348,8 @@ tap.test('STD-04: ZUGFeRD 2.1 Compliance - should validate ZUGFeRD 2.1 standard
}
);
t.ok(profileSpecificValidation.result.profileCount === 5, 'Should validate all profiles');
t.ok(profileSpecificValidation.result.profiles.find(p => p.profile === 'EXTENDED')?.forbiddenCount === 0, 'EXTENDED profile should allow all fields');
expect(profileSpecificValidation.profileCount).toEqual(5);
expect(profileSpecificValidation.profiles.find(p => p.profile === 'EXTENDED')?.forbiddenCount).toEqual(0);
// Test 9: Corpus validation - ZUGFeRD 2.1 files
const corpusValidation = await performanceTracker.measureAsync(
@ -368,13 +368,13 @@ tap.test('STD-04: ZUGFeRD 2.1 Compliance - should validate ZUGFeRD 2.1 standard
// Process ZUGFeRD 2.1 corpus files
const zugferd21Pattern = '**/zugferd_2p1_*.pdf';
const zugferd21Files = await corpusLoader.findFiles('ZUGFeRDv2', zugferd21Pattern);
const zugferd21Files = await CorpusLoader.loadPattern(zugferd21Pattern, 'ZUGFERD_V2_CORRECT');
results.total = zugferd21Files.length;
// Count by profile
for (const file of zugferd21Files) {
const filename = path.basename(file);
const filename = path.basename(file.path);
results.byType.pdf++;
if (filename.includes('MINIMUM')) results.byProfile['MINIMUM'] = (results.byProfile['MINIMUM'] || 0) + 1;
@ -384,20 +384,20 @@ tap.test('STD-04: ZUGFeRD 2.1 Compliance - should validate ZUGFeRD 2.1 standard
else if (filename.includes('EXTENDED')) results.byProfile['EXTENDED'] = (results.byProfile['EXTENDED'] || 0) + 1;
// Check if in correct/fail directory
if (file.includes('/correct/')) results.byType.valid++;
else if (file.includes('/fail/')) results.byType.invalid++;
if (file.path.includes('/correct/')) results.byType.valid++;
else if (file.path.includes('/fail/')) results.byType.invalid++;
}
// Also check for XML files
const xmlFiles = await corpusLoader.findFiles('ZUGFeRDv2', '**/*.xml');
const xmlFiles = await CorpusLoader.loadPattern('**/*.xml', 'ZUGFERD_V2_CORRECT');
results.byType.xml = xmlFiles.length;
return results;
}
);
t.ok(corpusValidation.result.total > 0, 'Should find ZUGFeRD 2.1 corpus files');
t.ok(Object.keys(corpusValidation.result.byProfile).length > 0, 'Should categorize files by profile');
expect(corpusValidation.total).toBeGreaterThan(0);
expect(Object.keys(corpusValidation.byProfile).length).toBeGreaterThan(0);
// Test 10: XRechnung compatibility
const xrechnungCompatibility = await performanceTracker.measureAsync(
@ -432,30 +432,24 @@ tap.test('STD-04: ZUGFeRD 2.1 Compliance - should validate ZUGFeRD 2.1 standard
}
);
t.ok(xrechnungCompatibility.result.compatible, 'Should be XRechnung compatible');
t.ok(xrechnungCompatibility.result.profile === 'EN16931', 'Should use EN16931 profile for XRechnung');
expect(xrechnungCompatibility.compatible).toBeTrue();
expect(xrechnungCompatibility.profile).toEqual('EN16931');
// Generate performance summary
const summary = performanceTracker.getSummary();
console.log('\n📊 ZUGFeRD 2.1 Compliance Test Summary:');
console.log(`✅ Total operations: ${summary.totalOperations}`);
console.log(` Total duration: ${summary.totalDuration}ms`);
console.log(`🏁 Profile validation: ${profileValidation.result.length} profiles validated`);
console.log(`🗺️ Field mappings: ${fieldMapping.result.totalMappings} fields mapped`);
console.log(`📋 Code lists: ${codeListValidation.result.codeListCount} lists, ${codeListValidation.result.totalCodes} codes`);
console.log(`📐 Business rules: ${businessRules.result.totalRules} rules across ${businessRules.result.categories.length} categories`);
console.log(`📎 Attachment handling: PDF/${attachmentHandling.result.pdfVersion} with ${attachmentHandling.result.xmlFilename}`);
console.log(`📁 Corpus files: ${corpusValidation.result.total} ZUGFeRD 2.1 files found`);
console.log(`🔄 XRechnung compatible: ${xrechnungCompatibility.result.compatible ? 'Yes' : 'No'}`);
console.log('\n🔍 Performance breakdown:');
summary.operations.forEach(op => {
console.log(` - ${op.name}: ${op.duration}ms`);
});
console.log(`🏁 Profile validation: ${profileValidation.length} profiles validated`);
console.log(`🗺 Field mappings: ${fieldMapping.totalMappings} fields mapped`);
console.log(`📋 Code lists: ${codeListValidation.codeListCount} lists, ${codeListValidation.totalCodes} codes`);
console.log(`📐 Business rules: ${businessRules.totalRules} rules across ${businessRules.categories.length} categories`);
console.log(`📎 Attachment handling: PDF/${attachmentHandling.pdfVersion} with ${attachmentHandling.xmlFilename}`);
console.log(`📁 Corpus files: ${corpusValidation.total} ZUGFeRD 2.1 files found`);
console.log(`🔄 XRechnung compatible: ${xrechnungCompatibility.compatible ? 'Yes' : 'No'}`);
t.end();
// Test completed
});
// Start the tests
tap.start();
// Export for test runner compatibility
export default tap;