Checkpoint: Ajout de la configuration des champs obligatoires pour le score LLM

Nouvelle fonctionnalité permettant de configurer quels champs sont obligatoires ou optionnels pour atteindre un score de reconnaissance de 100%.

Modifications:
- Nouvelle table llmFieldsConfig dans la base de données
- Routes tRPC pour gérer la configuration (getAll, updateField)
- Interface utilisateur dans la page Paramètres avec tableau et cases à cocher
- Modification du code d'extraction pour générer dynamiquement l'instruction de score
- Initialisation automatique des champs par défaut (supplierName, invoiceNumber, invoiceDate, totalAmount obligatoires)
- Tests unitaires pour valider la fonctionnalité

L'utilisateur peut maintenant personnaliser quels champs doivent être détectés pour qu'une facture atteigne 100% de score.
This commit is contained in:
Manus
2026-02-13 03:39:41 -05:00
parent 96f6367094
commit d32359fc10
14 changed files with 1903 additions and 30 deletions

View File

@@ -29,7 +29,10 @@ import {
AccountingAllocation,
automationRules,
InsertAutomationRule,
AutomationRule
AutomationRule,
llmFieldsConfig,
InsertLlmFieldConfig,
LlmFieldConfig
} from "../drizzle/schema";
import { ENV } from './_core/env';
@@ -606,3 +609,61 @@ export async function initializeDefaultLists(userId: number): Promise<void> {
}
}
}
// ============= LLM FIELDS CONFIG OPERATIONS =============
export async function getLlmFieldsConfigByUser(userId: number): Promise<LlmFieldConfig[]> {
const db = await getDb();
if (!db) return [];
return db.select().from(llmFieldsConfig).where(eq(llmFieldsConfig.userId, userId)).orderBy(llmFieldsConfig.displayOrder);
}
export async function upsertLlmFieldConfig(data: InsertLlmFieldConfig): Promise<LlmFieldConfig> {
const db = await getDb();
if (!db) throw new Error("Database not available");
const existing = await db.select().from(llmFieldsConfig)
.where(and(
eq(llmFieldsConfig.userId, data.userId),
eq(llmFieldsConfig.fieldName, data.fieldName)
))
.limit(1);
if (existing.length > 0) {
await db.update(llmFieldsConfig)
.set({ ...data, updatedAt: new Date() })
.where(eq(llmFieldsConfig.id, existing[0].id));
return (await db.select().from(llmFieldsConfig).where(eq(llmFieldsConfig.id, existing[0].id)))[0];
} else {
const result = await db.insert(llmFieldsConfig).values(data);
const insertedId = (result as any).insertId;
return (await db.select().from(llmFieldsConfig).where(eq(llmFieldsConfig.id, Number(insertedId))))[0];
}
}
export async function initializeDefaultLlmFields(userId: number): Promise<void> {
const db = await getDb();
if (!db) return;
const defaultFields = [
{ fieldName: "supplierName", displayName: "Nom du fournisseur", isRequired: 1, displayOrder: 1 },
{ fieldName: "invoiceNumber", displayName: "Numéro de facture", isRequired: 1, displayOrder: 2 },
{ fieldName: "invoiceDate", displayName: "Date de facture", isRequired: 1, displayOrder: 3 },
{ fieldName: "totalAmount", displayName: "Montant total TTC", isRequired: 1, displayOrder: 4 },
{ fieldName: "deliveryNoteNumber", displayName: "Numéro de bon de livraison", isRequired: 0, displayOrder: 5 },
{ fieldName: "orderNumber", displayName: "Numéro de commande", isRequired: 0, displayOrder: 6 },
];
const existingFields = await db.select().from(llmFieldsConfig).where(eq(llmFieldsConfig.userId, userId));
const existingFieldNames = new Set(existingFields.map(f => f.fieldName));
for (const field of defaultFields) {
if (!existingFieldNames.has(field.fieldName)) {
try {
await db.insert(llmFieldsConfig).values({ userId, ...field });
} catch (error) {
// Ignore errors
}
}
}
}