@fin.cx/einvoice
Version:
A TypeScript module for creating, manipulating, and embedding XML data within PDF files specifically tailored for electronic invoice (einvoice) packages.
138 lines • 11.4 kB
JavaScript
import { CIIBaseValidator } from '../cii.validator.js';
import { ValidationLevel } from '../../../interfaces/common.js';
/**
* Validator for Factur-X invoice format
* Implements validation rules according to EN16931 and Factur-X specification
*/
export class FacturXValidator extends CIIBaseValidator {
/**
* Validates structure of the Factur-X XML document
* @returns True if structure validation passed
*/
validateStructure() {
if (!this.doc)
return false;
let valid = true;
// Check for required main sections
const sections = [
'rsm:ExchangedDocumentContext',
'rsm:ExchangedDocument',
'rsm:SupplyChainTradeTransaction'
];
for (const section of sections) {
if (!this.exists(section)) {
this.addError('FX-STRUCT-1', `Required section ${section} is missing`, '/rsm:CrossIndustryInvoice');
valid = false;
}
}
// Check for SupplyChainTradeTransaction sections
if (this.exists('rsm:SupplyChainTradeTransaction')) {
const tradeSubsections = [
'ram:ApplicableHeaderTradeAgreement',
'ram:ApplicableHeaderTradeDelivery',
'ram:ApplicableHeaderTradeSettlement'
];
for (const subsection of tradeSubsections) {
if (!this.exists(`rsm:SupplyChainTradeTransaction/${subsection}`)) {
this.addError('FX-STRUCT-2', `Required subsection ${subsection} is missing`, '/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction');
valid = false;
}
}
}
return valid;
}
/**
* Validates business rules
* @returns True if business rule validation passed
*/
validateBusinessRules() {
if (!this.doc)
return false;
let valid = true;
// BR-16: Amount due for payment (BT-115) = Invoice total amount with VAT (BT-112) - Paid amount (BT-113)
valid = this.validateAmounts() && valid;
// BR-CO-3: Value added tax point date (BT-7) and Value added tax point date code (BT-8) are mutually exclusive
valid = this.validateMutuallyExclusiveFields() && valid;
// BR-S-1: An Invoice that contains a line (BG-25) where the Invoiced item VAT category code (BT-151) is "Standard rated"
// shall contain the Seller VAT Identifier (BT-31), the Seller tax registration identifier (BT-32)
// and/or the Seller tax representative VAT identifier (BT-63).
valid = this.validateSellerVatIdentifier() && valid;
return valid;
}
/**
* Validates amount calculations in the invoice
* @returns True if amount validation passed
*/
validateAmounts() {
if (!this.doc)
return false;
try {
// Extract amounts
const totalAmount = this.getNumber('//ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementHeaderMonetarySummation/ram:GrandTotalAmount');
const paidAmount = this.getNumber('//ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementHeaderMonetarySummation/ram:TotalPrepaidAmount') || 0;
const dueAmount = this.getNumber('//ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementHeaderMonetarySummation/ram:DuePayableAmount');
// Calculate expected due amount
const expectedDueAmount = totalAmount - paidAmount;
// Compare with a small tolerance for rounding errors
if (Math.abs(dueAmount - expectedDueAmount) > 0.01) {
this.addError('BR-16', `Amount due for payment (${dueAmount}) must equal Invoice total amount with VAT (${totalAmount}) - Paid amount (${paidAmount})`, '//ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementHeaderMonetarySummation');
return false;
}
return true;
}
catch (error) {
this.addError('FX-AMOUNT', `Error validating amounts: ${error}`, '/');
return false;
}
}
/**
* Validates mutually exclusive fields
* @returns True if validation passed
*/
validateMutuallyExclusiveFields() {
if (!this.doc)
return false;
try {
// Check for VAT point date and code (BR-CO-3)
const vatPointDate = this.exists('//ram:ApplicableHeaderTradeSettlement/ram:ApplicableTradeTax/ram:TaxPointDate');
const vatPointDateCode = this.exists('//ram:ApplicableHeaderTradeSettlement/ram:ApplicableTradeTax/ram:DueDateTypeCode');
if (vatPointDate && vatPointDateCode) {
this.addError('BR-CO-3', 'Value added tax point date and Value added tax point date code are mutually exclusive', '//ram:ApplicableHeaderTradeSettlement/ram:ApplicableTradeTax');
return false;
}
return true;
}
catch (error) {
this.addError('FX-MUTUAL', `Error validating mutually exclusive fields: ${error}`, '/');
return false;
}
}
/**
* Validates seller VAT identifier requirements
* @returns True if validation passed
*/
validateSellerVatIdentifier() {
if (!this.doc)
return false;
try {
// Check if there are any standard rated line items
const standardRatedItems = this.exists('//ram:SpecifiedLineTradeSettlement/ram:ApplicableTradeTax/ram:CategoryCode[text()="S"]');
if (standardRatedItems) {
// Check for seller VAT identifier
const sellerVatId = this.exists('//ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:SpecifiedTaxRegistration/ram:ID[@schemeID="VA"]');
const sellerTaxId = this.exists('//ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:SpecifiedTaxRegistration/ram:ID[@schemeID="FC"]');
const sellerTaxRepId = this.exists('//ram:ApplicableHeaderTradeAgreement/ram:SellerTaxRepresentativeTradeParty/ram:SpecifiedTaxRegistration/ram:ID[@schemeID="VA"]');
if (!sellerVatId && !sellerTaxId && !sellerTaxRepId) {
this.addError('BR-S-1', 'An Invoice with standard rated items must contain the Seller VAT Identifier, Tax registration identifier or Tax representative VAT identifier', '//ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty');
return false;
}
}
return true;
}
catch (error) {
this.addError('FX-VAT', `Error validating seller VAT identifier: ${error}`, '/');
return false;
}
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFjdHVyeC52YWxpZGF0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90cy9mb3JtYXRzL2NpaS9mYWN0dXJ4L2ZhY3R1cngudmFsaWRhdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUdoRTs7O0dBR0c7QUFDSCxNQUFNLE9BQU8sZ0JBQWlCLFNBQVEsZ0JBQWdCO0lBQ3BEOzs7T0FHRztJQUNPLGlCQUFpQjtRQUN6QixJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUc7WUFBRSxPQUFPLEtBQUssQ0FBQztRQUU1QixJQUFJLEtBQUssR0FBRyxJQUFJLENBQUM7UUFFakIsbUNBQW1DO1FBQ25DLE1BQU0sUUFBUSxHQUFHO1lBQ2YsOEJBQThCO1lBQzlCLHVCQUF1QjtZQUN2QixpQ0FBaUM7U0FDbEMsQ0FBQztRQUVGLEtBQUssTUFBTSxPQUFPLElBQUksUUFBUSxFQUFFLENBQUM7WUFDL0IsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztnQkFDMUIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxhQUFhLEVBQUUsb0JBQW9CLE9BQU8sYUFBYSxFQUFFLDJCQUEyQixDQUFDLENBQUM7Z0JBQ3BHLEtBQUssR0FBRyxLQUFLLENBQUM7WUFDaEIsQ0FBQztRQUNILENBQUM7UUFFRCxpREFBaUQ7UUFDakQsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLGlDQUFpQyxDQUFDLEVBQUUsQ0FBQztZQUNuRCxNQUFNLGdCQUFnQixHQUFHO2dCQUN2QixvQ0FBb0M7Z0JBQ3BDLG1DQUFtQztnQkFDbkMscUNBQXFDO2FBQ3RDLENBQUM7WUFFRixLQUFLLE1BQU0sVUFBVSxJQUFJLGdCQUFnQixFQUFFLENBQUM7Z0JBQzFDLElBQUksQ0FBQyxJQUFJ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