Files
demat-facturation/shared/invoiceQuality.ts

60 lines
2.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/** Champ requis configuré pour le calcul du score de qualité d’une facture. */
export type QualityFieldConfig = {
fieldName: string;
isRequired: number;
};
/** Référentiel utilisé tant qu’un compte ne possède pas encore sa configuration en base. */
export const DEFAULT_REQUIRED_INVOICE_FIELDS = [
"supplierName",
"invoiceNumber",
"invoiceDate",
"totalAmount",
] as const;
function hasValue(value: unknown): boolean {
if (value === null || value === undefined) return false;
if (typeof value === "string") return value.trim().length > 0;
if (value instanceof Date) return Number.isFinite(value.getTime());
return true;
}
/**
* Recalcule le score selon les champs obligatoires configurés pour le compte.
* Les champs optionnels n'affectent jamais le résultat. Le calcul est purement
* déterministe afin d'être identique après import et après une correction manuelle.
*/
export function calculateInvoiceQualityScore(
invoice: Record<string, unknown>,
fieldsConfiguration: readonly QualityFieldConfig[],
): number {
const configuredRequiredFields = fieldsConfiguration
.filter((field) => field.isRequired === 1)
.map((field) => field.fieldName);
const requiredFields = fieldsConfiguration.length > 0
? configuredRequiredFields
: DEFAULT_REQUIRED_INVOICE_FIELDS;
if (requiredFields.length === 0) return 100;
const completedFields = requiredFields.filter((fieldName) => hasValue(invoice[fieldName])).length;
return Math.round((completedFields / requiredFields.length) * 100);
}
/**
* Prépare une extraction IA pour la persistance. Le score brut du modèle est
* volontairement remplacé par le calcul déterministe commun à tous les flux.
*/
export function withCalculatedInvoiceQuality<T extends object>(
invoice: T,
fieldsConfiguration: readonly QualityFieldConfig[],
): T & { qualityScore: number } {
return {
...invoice,
qualityScore: calculateInvoiceQualityScore(
invoice as Record<string, unknown>,
fieldsConfiguration,
),
};
}