feat(core): improve in-memory validation, FatturaPA detection coverage, and published type compatibility

This commit is contained in:
2026-04-16 20:30:56 +00:00
parent 55bee02a2e
commit 3f37f6538c
60 changed files with 5723 additions and 6678 deletions
+28 -24
View File
@@ -73,7 +73,7 @@ ${invoiceMatch[0]}`;
console.log(` Errors: ${validation.errors.map(e => `${e.code}: ${e.message}`).join('; ')}`);
}
}
} catch (error) {
} catch (error: any) {
results.failed++;
results.errors.push(`${fileName}: ${error.message}`);
console.log(`${fileName}: Error - ${error.message}`);
@@ -128,7 +128,7 @@ ${invoiceMatch[0]}`;
} else {
console.log(`${fileName}: Validation passed (may need stricter codelist checking)`);
}
} catch (error) {
} catch (error: any) {
console.log(`${fileName}: Error - ${error.message}`);
}
}
@@ -162,7 +162,7 @@ tap.test('Validation Suite - Syntax validation levels', async () => {
console.log(` - ${err.code}: ${err.message}`);
});
}
} catch (error) {
} catch (error: any) {
if (error instanceof EInvoiceValidationError) {
console.log('✓ Validation error caught correctly');
console.log(error.getValidationReport());
@@ -174,23 +174,30 @@ tap.test('Validation Suite - Syntax validation levels', async () => {
tap.test('Validation Suite - Error reporting and recovery', async () => {
const testInvoice = new EInvoice();
// Try to validate without loading XML
try {
await testInvoice.validate();
} catch (error) {
expect(error).toBeInstanceOf(EInvoiceValidationError);
if (error instanceof EInvoiceValidationError) {
// The error might be "Cannot validate: format unknown" since no XML is loaded
console.log('✓ Empty invoice validation error handled correctly');
console.log(` Error: ${error.message}`);
}
}
const emptyValidation = await testInvoice.validate();
expect(emptyValidation.valid).toBeFalse();
expect(emptyValidation.errors.some(error => error.code === 'BR-01')).toBeTrue();
console.log('✓ Empty invoice validation returns structured errors');
// Test with minimal valid invoice
testInvoice.id = 'TEST-001';
testInvoice.invoiceId = 'INV-001';
testInvoice.from.name = 'Test Seller';
testInvoice.from.address = {
streetName: 'Seller Street',
houseNumber: '1',
city: 'Berlin',
postalCode: '10115',
country: 'DE'
};
testInvoice.to.name = 'Test Buyer';
testInvoice.to.address = {
streetName: 'Buyer Street',
houseNumber: '2',
city: 'Paris',
postalCode: '75001',
country: 'FR'
};
testInvoice.items = [{
position: 1,
name: 'Test Item',
@@ -200,13 +207,10 @@ tap.test('Validation Suite - Error reporting and recovery', async () => {
vatPercentage: 19
}];
// This should fail because we don't have XML loaded
try {
await testInvoice.validate();
} catch (error) {
expect(error).toBeInstanceOf(EInvoiceValidationError);
console.log('✓ Validation requires loaded XML');
}
const programmaticValidation = await testInvoice.validate();
expect(programmaticValidation.valid).toBeTrue();
expect(programmaticValidation.errors).toHaveLength(0);
console.log('✓ Programmatic invoice validation works without loaded XML');
});
// Test format-specific validation
@@ -252,7 +256,7 @@ tap.test('Validation Suite - Format-specific validation rules', async () => {
// Validate according to profile
const validation = await einvoice.validate(ValidationLevel.SEMANTIC);
console.log(` Validation: ${validation.valid ? 'VALID' : 'INVALID'}`);
} catch (error) {
} catch (error: any) {
console.log(`${plugins.path.basename(file)}: Skipped - ${error.message}`);
}
}
@@ -369,7 +373,7 @@ tap.test('Validation Suite - Calculation and sum validations', async () => {
} else {
console.log('✓ Invoice calculations validated successfully');
}
} catch (error) {
} catch (error: any) {
console.log(`Calculation validation test skipped: ${error.message}`);
}
});
@@ -418,4 +422,4 @@ tap.test('Validation Suite - Summary Report', async () => {
}
});
tap.start();
tap.start();