einvoice/ts/formats/factories/validator.factory.ts

134 lines
3.9 KiB
TypeScript
Raw Normal View History

2025-04-03 15:53:08 +00:00
import { BaseValidator } from '../base/base.validator.js';
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
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';
import { ZUGFeRDValidator } from '../cii/zugferd/zugferd.validator.js';
2025-04-03 15:53:08 +00:00
// The EN16931UBLValidator handles all UBL-based formats with proper business rules
// No need for legacy validator implementations here
/**
* 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 {
try {
const format = FormatDetector.detectFormat(xml);
2025-04-03 15:53:08 +00:00
switch (format) {
case InvoiceFormat.UBL:
return new EN16931UBLValidator(xml);
2025-04-03 15:53:08 +00:00
case InvoiceFormat.XRECHNUNG:
return new XRechnungValidator(xml);
2025-04-03 15:53:08 +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
case InvoiceFormat.ZUGFERD:
return new ZUGFeRDValidator(xml);
2025-04-03 15:53:08 +00:00
case InvoiceFormat.FACTURX:
return new FacturXValidator(xml);
2025-04-03 15:53:08 +00:00
case InvoiceFormat.FATTURAPA:
return new FatturaPAValidator(xml);
2025-04-03 15:53:08 +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
}
}
}
/**
* 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;
}
}