2025-04-03 15:53:08 +00:00
|
|
|
import { BaseValidator } from '../base/base.validator.js';
|
2025-04-04 12:14:41 +00:00
|
|
|
import { InvoiceFormat, ValidationLevel } from '../../interfaces/common.js';
|
|
|
|
import type { ValidationResult } from '../../interfaces/common.js';
|
2025-04-03 15:53:08 +00:00
|
|
|
import { FormatDetector } from '../utils/format.detector.js';
|
|
|
|
|
|
|
|
// Import specific validators
|
2025-05-30 18:18:42 +00:00
|
|
|
import { EN16931UBLValidator } from '../ubl/en16931.ubl.validator.js';
|
|
|
|
import { XRechnungValidator } from '../ubl/xrechnung.validator.js';
|
2025-04-03 15:53:08 +00:00
|
|
|
import { FacturXValidator } from '../cii/facturx/facturx.validator.js';
|
2025-04-03 20:08:02 +00:00
|
|
|
import { ZUGFeRDValidator } from '../cii/zugferd/zugferd.validator.js';
|
2025-04-03 15:53:08 +00:00
|
|
|
|
2025-05-30 18:18:42 +00:00
|
|
|
// The EN16931UBLValidator handles all UBL-based formats with proper business rules
|
|
|
|
// No need for legacy validator implementations here
|
2025-04-04 12:14:41 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* FatturaPA validator implementation
|
|
|
|
* Basic implementation for Italian electronic invoices
|
|
|
|
*/
|
|
|
|
class FatturaPAValidator extends BaseValidator {
|
|
|
|
validate(level: ValidationLevel = ValidationLevel.SYNTAX): ValidationResult {
|
|
|
|
// Reset errors
|
|
|
|
this.errors = [];
|
|
|
|
|
|
|
|
let valid = true;
|
|
|
|
|
|
|
|
if (level === ValidationLevel.SYNTAX) {
|
|
|
|
valid = this.validateSchema();
|
|
|
|
} else if (level === ValidationLevel.SEMANTIC || level === ValidationLevel.BUSINESS) {
|
|
|
|
valid = this.validateSchema() && this.validateBusinessRules();
|
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
valid,
|
|
|
|
errors: this.errors,
|
|
|
|
level
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
protected validateSchema(): boolean {
|
|
|
|
// Basic schema validation for FatturaPA
|
|
|
|
if (!this.xml.includes('<FatturaElettronica')) {
|
|
|
|
this.addError('FATT-SCHEMA-1', 'Root element must be FatturaElettronica', '/');
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected validateBusinessRules(): boolean {
|
|
|
|
// Basic placeholder implementation - would need more detailed rules
|
|
|
|
// for a real implementation
|
|
|
|
return this.validateSchema();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-04-03 15:53:08 +00:00
|
|
|
/**
|
|
|
|
* Factory to create the appropriate validator based on the XML format
|
|
|
|
*/
|
|
|
|
export class ValidatorFactory {
|
|
|
|
/**
|
|
|
|
* Creates a validator for the specified XML content
|
|
|
|
* @param xml XML content to validate
|
|
|
|
* @returns Appropriate validator instance
|
|
|
|
*/
|
|
|
|
public static createValidator(xml: string): BaseValidator {
|
2025-04-04 12:14:41 +00:00
|
|
|
try {
|
|
|
|
const format = FormatDetector.detectFormat(xml);
|
2025-04-03 15:53:08 +00:00
|
|
|
|
2025-04-04 12:14:41 +00:00
|
|
|
switch (format) {
|
|
|
|
case InvoiceFormat.UBL:
|
2025-05-30 18:18:42 +00:00
|
|
|
return new EN16931UBLValidator(xml);
|
2025-04-03 15:53:08 +00:00
|
|
|
|
2025-04-04 12:14:41 +00:00
|
|
|
case InvoiceFormat.XRECHNUNG:
|
|
|
|
return new XRechnungValidator(xml);
|
2025-04-03 15:53:08 +00:00
|
|
|
|
2025-04-04 12:14:41 +00:00
|
|
|
case InvoiceFormat.CII:
|
|
|
|
// For now, use Factur-X validator for generic CII
|
|
|
|
return new FacturXValidator(xml);
|
2025-04-03 15:53:08 +00:00
|
|
|
|
2025-04-04 12:14:41 +00:00
|
|
|
case InvoiceFormat.ZUGFERD:
|
|
|
|
return new ZUGFeRDValidator(xml);
|
2025-04-03 15:53:08 +00:00
|
|
|
|
2025-04-04 12:14:41 +00:00
|
|
|
case InvoiceFormat.FACTURX:
|
|
|
|
return new FacturXValidator(xml);
|
2025-04-03 15:53:08 +00:00
|
|
|
|
2025-04-04 12:14:41 +00:00
|
|
|
case InvoiceFormat.FATTURAPA:
|
|
|
|
return new FatturaPAValidator(xml);
|
2025-04-03 15:53:08 +00:00
|
|
|
|
2025-04-04 12:14:41 +00:00
|
|
|
default:
|
|
|
|
// For unknown formats, provide a generic validator that will
|
|
|
|
// mark the document as invalid but won't throw an exception
|
|
|
|
return new GenericValidator(xml, format);
|
|
|
|
}
|
|
|
|
} catch (error) {
|
|
|
|
// If an error occurs during validator creation, return a generic validator
|
|
|
|
// that will provide meaningful error information instead of throwing
|
|
|
|
console.error(`Error creating validator: ${error}`);
|
|
|
|
return new GenericValidator(xml, 'unknown');
|
2025-04-03 15:53:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2025-04-04 12:14:41 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Generic validator for unknown or unsupported formats
|
|
|
|
* Provides meaningful validation errors instead of throwing exceptions
|
|
|
|
*/
|
|
|
|
class GenericValidator extends BaseValidator {
|
|
|
|
private format: string;
|
|
|
|
|
|
|
|
constructor(xml: string, format: string) {
|
|
|
|
super(xml);
|
|
|
|
this.format = format;
|
|
|
|
this.addError(
|
|
|
|
'GEN-1',
|
|
|
|
`Unsupported invoice format: ${format}`,
|
|
|
|
'/'
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
validate(level: ValidationLevel = ValidationLevel.SYNTAX): ValidationResult {
|
|
|
|
return {
|
|
|
|
valid: false,
|
|
|
|
errors: this.errors,
|
|
|
|
level
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
protected validateSchema(): boolean {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected validateBusinessRules(): boolean {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|