diff --git a/client/src/pages/AutomationRules.tsx b/client/src/pages/AutomationRules.tsx
index d923483..4b5d986 100644
--- a/client/src/pages/AutomationRules.tsx
+++ b/client/src/pages/AutomationRules.tsx
@@ -237,6 +237,7 @@ export default function AutomationRules() {
const fieldOptions = [
{ value: "supplierName", label: "Fournisseur" },
+ { value: "recipientName", label: "Destinataire" },
{ value: "invoiceNumber", label: "N° Facture" },
{ value: "totalAmount", label: "Montant" },
{ value: "invoiceDate", label: "Date facture" },
diff --git a/client/src/pages/InvoiceDetail.tsx b/client/src/pages/InvoiceDetail.tsx
index 38fa57c..b858f5c 100644
--- a/client/src/pages/InvoiceDetail.tsx
+++ b/client/src/pages/InvoiceDetail.tsx
@@ -28,6 +28,7 @@ export default function InvoiceDetail() {
deliveryNoteNumber: "",
orderNumber: "",
totalAmount: "",
+ recipientName: "",
serviceConcerne: "",
typeAchat: "",
ventilationComptable: "",
@@ -45,6 +46,7 @@ export default function InvoiceDetail() {
deliveryNoteNumber: invoice.deliveryNoteNumber || "",
orderNumber: invoice.orderNumber || "",
totalAmount: invoice.totalAmount ? invoice.totalAmount.toString() : "",
+ recipientName: (invoice as any).recipientName || "",
serviceConcerne: invoice.serviceConcerne || "",
typeAchat: invoice.typeAchat || "",
ventilationComptable: invoice.ventilationComptable || "",
@@ -87,6 +89,7 @@ export default function InvoiceDetail() {
deliveryNoteNumber: formData.deliveryNoteNumber || undefined,
orderNumber: formData.orderNumber || undefined,
totalAmount: formData.totalAmount ? formData.totalAmount : undefined,
+ recipientName: formData.recipientName || undefined,
serviceConcerne: formData.serviceConcerne || undefined,
typeAchat: (formData.typeAchat as "CAPEX" | "OPEX" | "") || undefined,
ventilationComptable: formData.ventilationComptable || undefined,
@@ -330,6 +333,20 @@ export default function InvoiceDetail() {
)}
+
+
+
+ {isEditing ? (
+
setFormData({ ...formData, recipientName: e.target.value })}
+ placeholder="Nom du destinataire"
+ />
+ ) : (
+
{(invoice as any).recipientName || "-"}
+ )}
+
diff --git a/client/src/pages/Invoices.tsx b/client/src/pages/Invoices.tsx
index bf125f4..df2c169 100644
--- a/client/src/pages/Invoices.tsx
+++ b/client/src/pages/Invoices.tsx
@@ -60,15 +60,16 @@ export default function Invoices() {
// Generate Excel file
const worksheet = XLSX.utils.json_to_sheet(data.invoices.map(inv => ({
'Fournisseur': inv.supplierName,
- 'N\u00b0 Facture': inv.invoiceNumber,
+ 'Destinataire': (inv as any).recipientName,
+ 'N° Facture': inv.invoiceNumber,
'Date': inv.invoiceDate,
- 'N\u00b0 Bon de livraison': inv.deliveryNoteNumber,
- 'N\u00b0 Commande': inv.orderNumber,
+ 'N° Bon de livraison': inv.deliveryNoteNumber,
+ 'N° Commande': inv.orderNumber,
'Montant': inv.totalAmount,
'Score': inv.qualityScore,
'Statut export': inv.exportStatus,
- 'Export\u00e9 le': inv.exportedAt,
- 'Cr\u00e9\u00e9 le': inv.createdAt,
+ 'Exporté le': inv.exportedAt,
+ 'Créé le': inv.createdAt,
})));
const workbook = XLSX.utils.book_new();
@@ -398,6 +399,7 @@ export default function Invoices() {
/>
Fournisseur
+ Destinataire
N° Facture
Date
Montant
@@ -426,6 +428,7 @@ export default function Invoices() {
{invoice.supplierName || "Inconnu"}
+ {(invoice as any).recipientName || "-"}
{invoice.invoiceNumber || "-"}
{invoice.invoiceDate
diff --git a/client/src/pages/Settings.tsx b/client/src/pages/Settings.tsx
index 36c1e10..fc06bcb 100644
--- a/client/src/pages/Settings.tsx
+++ b/client/src/pages/Settings.tsx
@@ -664,6 +664,7 @@ export default function Settings() {
const [supplierKeywords, setSupplierKeywords] = useState("");
const [totalAmountKeywords, setTotalAmountKeywords] = useState("");
const [subscriptionKeywords, setSubscriptionKeywords] = useState("");
+ const [recipientKeywords, setRecipientKeywords] = useState("");
const [sftpHost, setSftpHost] = useState("");
const [sftpPort, setSftpPort] = useState(22);
const [sftpUsername, setSftpUsername] = useState("");
@@ -681,6 +682,7 @@ export default function Settings() {
setSupplierKeywords(settings.supplierKeywords || "");
setTotalAmountKeywords(settings.totalAmountKeywords || "");
setSubscriptionKeywords(settings.subscriptionKeywords || "");
+ setRecipientKeywords((settings as any).recipientKeywords || "");
setSftpHost(settings.sftpHost || "");
setSftpPort(settings.sftpPort || 22);
setSftpUsername(settings.sftpUsername || "");
@@ -723,6 +725,7 @@ export default function Settings() {
supplierKeywords,
totalAmountKeywords,
subscriptionKeywords,
+ recipientKeywords,
sftpHost,
sftpPort,
sftpUsername,
@@ -986,6 +989,24 @@ export default function Settings() {
Les factures contenant ces mots-clés seront automatiquement marquées comme abonnement
+
+
diff --git a/drizzle/0015_cool_redwing.sql b/drizzle/0015_cool_redwing.sql
new file mode 100644
index 0000000..5bd73bf
--- /dev/null
+++ b/drizzle/0015_cool_redwing.sql
@@ -0,0 +1,2 @@
+ALTER TABLE `invoices` ADD `recipientName` varchar(255);--> statement-breakpoint
+ALTER TABLE `userSettings` ADD `recipientKeywords` text;
\ No newline at end of file
diff --git a/drizzle/meta/0015_snapshot.json b/drizzle/meta/0015_snapshot.json
new file mode 100644
index 0000000..8fdc84f
--- /dev/null
+++ b/drizzle/meta/0015_snapshot.json
@@ -0,0 +1,1464 @@
+{
+ "version": "5",
+ "dialect": "mysql",
+ "id": "7f04b025-6023-4f79-a041-5d796b12d894",
+ "prevId": "879f5656-bb98-4ea3-ae6f-d3d82b4d420c",
+ "tables": {
+ "accountingAllocationList": {
+ "name": "accountingAllocationList",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "userId": {
+ "name": "userId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(100)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ }
+ },
+ "indexes": {
+ "user_allocation_unique": {
+ "name": "user_allocation_unique",
+ "columns": [
+ "userId",
+ "name"
+ ],
+ "isUnique": true
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "accountingAllocationList_id": {
+ "name": "accountingAllocationList_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "automationRules": {
+ "name": "automationRules",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "userId": {
+ "name": "userId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "isActive": {
+ "name": "isActive",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": 1
+ },
+ "priority": {
+ "name": "priority",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": 0
+ },
+ "conditions": {
+ "name": "conditions",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "conditionsLogic": {
+ "name": "conditionsLogic",
+ "type": "enum('AND','OR')",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'AND'"
+ },
+ "actions": {
+ "name": "actions",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ },
+ "updatedAt": {
+ "name": "updatedAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "onUpdate": true,
+ "default": "(now())"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "automationRules_id": {
+ "name": "automationRules_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "departmentList": {
+ "name": "departmentList",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "userId": {
+ "name": "userId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(100)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ }
+ },
+ "indexes": {
+ "user_department_unique": {
+ "name": "user_department_unique",
+ "columns": [
+ "userId",
+ "name"
+ ],
+ "isUnique": true
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "departmentList_id": {
+ "name": "departmentList_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "importLogs": {
+ "name": "importLogs",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "userId": {
+ "name": "userId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "sourceFileId": {
+ "name": "sourceFileId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "fileName": {
+ "name": "fileName",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "totalInvoicesDetected": {
+ "name": "totalInvoicesDetected",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": 0
+ },
+ "invoicesImported": {
+ "name": "invoicesImported",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": 0
+ },
+ "duplicatesIgnored": {
+ "name": "duplicatesIgnored",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": 0
+ },
+ "errors": {
+ "name": "errors",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": 0
+ },
+ "duplicateDetails": {
+ "name": "duplicateDetails",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "errorDetails": {
+ "name": "errorDetails",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "importedAt": {
+ "name": "importedAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "importLogs_id": {
+ "name": "importLogs_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "importSettings": {
+ "name": "importSettings",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "userId": {
+ "name": "userId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "manualImportEnabled": {
+ "name": "manualImportEnabled",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": 1
+ },
+ "autoImportEnabled": {
+ "name": "autoImportEnabled",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": 0
+ },
+ "autoImportSourcePath": {
+ "name": "autoImportSourcePath",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "autoImportFrequency": {
+ "name": "autoImportFrequency",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": 60
+ },
+ "emailImportEnabled": {
+ "name": "emailImportEnabled",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": 0
+ },
+ "emailImportAddress": {
+ "name": "emailImportAddress",
+ "type": "varchar(320)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "emailImportPassword": {
+ "name": "emailImportPassword",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "emailImportHost": {
+ "name": "emailImportHost",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "emailImportPort": {
+ "name": "emailImportPort",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false,
+ "default": 993
+ },
+ "emailImportFrequency": {
+ "name": "emailImportFrequency",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": 30
+ },
+ "exportFolder": {
+ "name": "exportFolder",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ },
+ "updatedAt": {
+ "name": "updatedAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "onUpdate": true,
+ "default": "(now())"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "importSettings_id": {
+ "name": "importSettings_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {
+ "importSettings_userId_unique": {
+ "name": "importSettings_userId_unique",
+ "columns": [
+ "userId"
+ ]
+ }
+ },
+ "checkConstraint": {}
+ },
+ "invoices": {
+ "name": "invoices",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "userId": {
+ "name": "userId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "sourceFileId": {
+ "name": "sourceFileId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "invoiceIndexInFile": {
+ "name": "invoiceIndexInFile",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": 1
+ },
+ "fileName": {
+ "name": "fileName",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "fileKey": {
+ "name": "fileKey",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "fileUrl": {
+ "name": "fileUrl",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "supplierName": {
+ "name": "supplierName",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "invoiceNumber": {
+ "name": "invoiceNumber",
+ "type": "varchar(100)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "invoiceDate": {
+ "name": "invoiceDate",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "deliveryNoteNumber": {
+ "name": "deliveryNoteNumber",
+ "type": "varchar(100)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "orderNumber": {
+ "name": "orderNumber",
+ "type": "varchar(100)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "totalAmount": {
+ "name": "totalAmount",
+ "type": "decimal(10,2)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "recipientName": {
+ "name": "recipientName",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "pageRange": {
+ "name": "pageRange",
+ "type": "varchar(20)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "qualityScore": {
+ "name": "qualityScore",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "metadataFileKey": {
+ "name": "metadataFileKey",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "metadataFileUrl": {
+ "name": "metadataFileUrl",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "status": {
+ "name": "status",
+ "type": "enum('processing','completed','error')",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'processing'"
+ },
+ "errorMessage": {
+ "name": "errorMessage",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "exportStatus": {
+ "name": "exportStatus",
+ "type": "enum('not_exported','exported','export_error')",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'not_exported'"
+ },
+ "manuallyEdited": {
+ "name": "manuallyEdited",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": 0
+ },
+ "serviceConcerne": {
+ "name": "serviceConcerne",
+ "type": "varchar(100)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "typeAchat": {
+ "name": "typeAchat",
+ "type": "enum('CAPEX','OPEX')",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "ventilationComptable": {
+ "name": "ventilationComptable",
+ "type": "varchar(100)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "autoFilledFields": {
+ "name": "autoFilledFields",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "extractedText": {
+ "name": "extractedText",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "isSubscription": {
+ "name": "isSubscription",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": 0
+ },
+ "bapValidated": {
+ "name": "bapValidated",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": 0
+ },
+ "bapValidatedAt": {
+ "name": "bapValidatedAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "exportedAt": {
+ "name": "exportedAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "exportMode": {
+ "name": "exportMode",
+ "type": "enum('manual','automatic')",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ },
+ "updatedAt": {
+ "name": "updatedAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "onUpdate": true,
+ "default": "(now())"
+ }
+ },
+ "indexes": {
+ "supplier_invoice_date_unique": {
+ "name": "supplier_invoice_date_unique",
+ "columns": [
+ "supplierName",
+ "invoiceNumber",
+ "invoiceDate"
+ ],
+ "isUnique": true
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "invoices_id": {
+ "name": "invoices_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "llmFieldsConfig": {
+ "name": "llmFieldsConfig",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "userId": {
+ "name": "userId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "fieldName": {
+ "name": "fieldName",
+ "type": "varchar(100)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "displayName": {
+ "name": "displayName",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "isRequired": {
+ "name": "isRequired",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": 1
+ },
+ "displayOrder": {
+ "name": "displayOrder",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": 0
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ },
+ "updatedAt": {
+ "name": "updatedAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "onUpdate": true,
+ "default": "(now())"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "llmFieldsConfig_id": {
+ "name": "llmFieldsConfig_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "llmLogs": {
+ "name": "llmLogs",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "userId": {
+ "name": "userId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "sourceFileId": {
+ "name": "sourceFileId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "invoiceId": {
+ "name": "invoiceId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "operation": {
+ "name": "operation",
+ "type": "varchar(50)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "model": {
+ "name": "model",
+ "type": "varchar(50)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "promptSent": {
+ "name": "promptSent",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "rawResponse": {
+ "name": "rawResponse",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "cleanedResponse": {
+ "name": "cleanedResponse",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "success": {
+ "name": "success",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": 1
+ },
+ "errorMessage": {
+ "name": "errorMessage",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "processingTimeMs": {
+ "name": "processingTimeMs",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "pageRange": {
+ "name": "pageRange",
+ "type": "varchar(50)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "llmLogs_id": {
+ "name": "llmLogs_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "serviceSignatures": {
+ "name": "serviceSignatures",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "userId": {
+ "name": "userId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "serviceName": {
+ "name": "serviceName",
+ "type": "varchar(100)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "signatureId": {
+ "name": "signatureId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ },
+ "updatedAt": {
+ "name": "updatedAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "onUpdate": true,
+ "default": "(now())"
+ }
+ },
+ "indexes": {
+ "user_service_unique": {
+ "name": "user_service_unique",
+ "columns": [
+ "userId",
+ "serviceName"
+ ],
+ "isUnique": true
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "serviceSignatures_id": {
+ "name": "serviceSignatures_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "signatures": {
+ "name": "signatures",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "userId": {
+ "name": "userId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "firstName": {
+ "name": "firstName",
+ "type": "varchar(100)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "lastName": {
+ "name": "lastName",
+ "type": "varchar(100)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "imageKey": {
+ "name": "imageKey",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "imageUrl": {
+ "name": "imageUrl",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ },
+ "updatedAt": {
+ "name": "updatedAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "onUpdate": true,
+ "default": "(now())"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "signatures_id": {
+ "name": "signatures_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "sourceFiles": {
+ "name": "sourceFiles",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "userId": {
+ "name": "userId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "fileName": {
+ "name": "fileName",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "fileKey": {
+ "name": "fileKey",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "fileUrl": {
+ "name": "fileUrl",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "totalInvoicesDetected": {
+ "name": "totalInvoicesDetected",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": 0
+ },
+ "processingStatus": {
+ "name": "processingStatus",
+ "type": "enum('processing','completed','error')",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'processing'"
+ },
+ "processingProgress": {
+ "name": "processingProgress",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ },
+ "updatedAt": {
+ "name": "updatedAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "onUpdate": true,
+ "default": "(now())"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "sourceFiles_id": {
+ "name": "sourceFiles_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "userSettings": {
+ "name": "userSettings",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "userId": {
+ "name": "userId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "llmModel": {
+ "name": "llmModel",
+ "type": "varchar(50)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'mistral-large-latest'"
+ },
+ "orderNumberFormat": {
+ "name": "orderNumberFormat",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "invoiceNumberKeywords": {
+ "name": "invoiceNumberKeywords",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "deliveryNoteKeywords": {
+ "name": "deliveryNoteKeywords",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "orderNumberKeywords": {
+ "name": "orderNumberKeywords",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "supplierKeywords": {
+ "name": "supplierKeywords",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "totalAmountKeywords": {
+ "name": "totalAmountKeywords",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "subscriptionKeywords": {
+ "name": "subscriptionKeywords",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "recipientKeywords": {
+ "name": "recipientKeywords",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "sftpHost": {
+ "name": "sftpHost",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "sftpPort": {
+ "name": "sftpPort",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false,
+ "default": 22
+ },
+ "sftpUsername": {
+ "name": "sftpUsername",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "sftpPassword": {
+ "name": "sftpPassword",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "sftpRemotePath": {
+ "name": "sftpRemotePath",
+ "type": "varchar(500)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false,
+ "default": "'/'"
+ },
+ "sftpAutoExport": {
+ "name": "sftpAutoExport",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": 0
+ },
+ "llmLogsRetentionMonths": {
+ "name": "llmLogsRetentionMonths",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": 3
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ },
+ "updatedAt": {
+ "name": "updatedAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "onUpdate": true,
+ "default": "(now())"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "userSettings_id": {
+ "name": "userSettings_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {
+ "userSettings_userId_unique": {
+ "name": "userSettings_userId_unique",
+ "columns": [
+ "userId"
+ ]
+ }
+ },
+ "checkConstraint": {}
+ },
+ "users": {
+ "name": "users",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "openId": {
+ "name": "openId",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "azureAdId": {
+ "name": "azureAdId",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "email": {
+ "name": "email",
+ "type": "varchar(320)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "passwordHash": {
+ "name": "passwordHash",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "loginMethod": {
+ "name": "loginMethod",
+ "type": "enum('manus','local','azure-ad')",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "role": {
+ "name": "role",
+ "type": "enum('user','admin')",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'user'"
+ },
+ "isActive": {
+ "name": "isActive",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": 1
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ },
+ "updatedAt": {
+ "name": "updatedAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "onUpdate": true,
+ "default": "(now())"
+ },
+ "lastSignedIn": {
+ "name": "lastSignedIn",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "users_id": {
+ "name": "users_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {
+ "users_openId_unique": {
+ "name": "users_openId_unique",
+ "columns": [
+ "openId"
+ ]
+ },
+ "users_azureAdId_unique": {
+ "name": "users_azureAdId_unique",
+ "columns": [
+ "azureAdId"
+ ]
+ },
+ "users_email_unique": {
+ "name": "users_email_unique",
+ "columns": [
+ "email"
+ ]
+ }
+ },
+ "checkConstraint": {}
+ }
+ },
+ "views": {},
+ "_meta": {
+ "schemas": {},
+ "tables": {},
+ "columns": {}
+ },
+ "internal": {
+ "tables": {},
+ "indexes": {}
+ }
+}
\ No newline at end of file
diff --git a/drizzle/meta/_journal.json b/drizzle/meta/_journal.json
index c0ffae9..801b71a 100644
--- a/drizzle/meta/_journal.json
+++ b/drizzle/meta/_journal.json
@@ -106,6 +106,13 @@
"when": 1773530695041,
"tag": "0014_watery_talos",
"breakpoints": true
+ },
+ {
+ "idx": 15,
+ "version": "5",
+ "when": 1775984357982,
+ "tag": "0015_cool_redwing",
+ "breakpoints": true
}
]
}
\ No newline at end of file
diff --git a/drizzle/schema.ts b/drizzle/schema.ts
index cdeee7e..e659272 100644
--- a/drizzle/schema.ts
+++ b/drizzle/schema.ts
@@ -67,6 +67,7 @@ export const invoices = mysqlTable("invoices", {
deliveryNoteNumber: varchar("deliveryNoteNumber", { length: 100 }),
orderNumber: varchar("orderNumber", { length: 100 }),
totalAmount: decimal("totalAmount", { precision: 10, scale: 2 }),
+ recipientName: varchar("recipientName", { length: 255 }), // Destinataire de la facture
pageRange: varchar("pageRange", { length: 20 }), // ex: "1-2" ou "5"
qualityScore: int("qualityScore"), // Score de qualité de l'extraction (0-100)
@@ -134,6 +135,7 @@ export const userSettings = mysqlTable("userSettings", {
supplierKeywords: text("supplierKeywords"), // Ex: "Vendeur, Société, Émetteur"
totalAmountKeywords: text("totalAmountKeywords"), // Ex: "Net à payer, Total à régler, Amount due"
subscriptionKeywords: text("subscriptionKeywords"), // Ex: "Abonnement, Subscription, Mensuel, Annuel"
+ recipientKeywords: text("recipientKeywords"), // Ex: "Destinataire, À l'attention de, Client"
// SFTP Configuration
sftpHost: varchar("sftpHost", { length: 255 }),
sftpPort: int("sftpPort").default(22),
diff --git a/server/db.ts b/server/db.ts
index 0f3d0e9..92fad0d 100644
--- a/server/db.ts
+++ b/server/db.ts
@@ -658,6 +658,7 @@ export async function initializeDefaultLlmFields(userId: number): Promise
{ 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 },
+ { fieldName: "recipientName", displayName: "Destinataire", isRequired: 0, displayOrder: 7 },
];
const existingFields = await db.select().from(llmFieldsConfig).where(eq(llmFieldsConfig.userId, userId));
diff --git a/server/emailImportService.ts b/server/emailImportService.ts
index 66c37d3..8cda8ce 100644
--- a/server/emailImportService.ts
+++ b/server/emailImportService.ts
@@ -75,6 +75,7 @@ async function processEmailAttachment(
supplier: settings.supplierKeywords,
totalAmount: settings.totalAmountKeywords,
subscription: settings.subscriptionKeywords,
+ recipient: settings.recipientKeywords,
} : undefined;
const model = settings?.llmModel || "mistral-large-latest";
@@ -153,6 +154,7 @@ async function processEmailAttachment(
deliveryNoteNumber: invoiceData.deliveryNoteNumber,
orderNumber: invoiceData.orderNumber,
totalAmount: invoiceData.totalAmount?.toString(),
+ recipientName: invoiceData.recipientName,
pageRange: invoiceData.pageRange,
qualityScore: invoiceData.qualityScore,
extractedText: invoiceData.extractedText,
diff --git a/server/folderImportService.ts b/server/folderImportService.ts
index 61ac275..66b6998 100644
--- a/server/folderImportService.ts
+++ b/server/folderImportService.ts
@@ -76,6 +76,7 @@ async function processFolderFile(
supplier: settings.supplierKeywords,
totalAmount: settings.totalAmountKeywords,
subscription: settings.subscriptionKeywords,
+ recipient: settings.recipientKeywords,
} : undefined;
const model = settings?.llmModel || "mistral-large-latest";
@@ -154,6 +155,7 @@ async function processFolderFile(
deliveryNoteNumber: invoiceData.deliveryNoteNumber,
orderNumber: invoiceData.orderNumber,
totalAmount: invoiceData.totalAmount?.toString(),
+ recipientName: invoiceData.recipientName,
pageRange: invoiceData.pageRange,
qualityScore: invoiceData.qualityScore,
extractedText: invoiceData.extractedText,
diff --git a/server/invoiceExtractor.ts b/server/invoiceExtractor.ts
index 157fdbf..bfdf2e1 100644
--- a/server/invoiceExtractor.ts
+++ b/server/invoiceExtractor.ts
@@ -10,6 +10,7 @@ export interface ExtractedInvoiceData {
deliveryNoteNumber: string | null;
orderNumber: string | null;
totalAmount: number | null;
+ recipientName: string | null; // Destinataire de la facture
pageRange: string;
qualityScore: number; // 0-100
extractedText: string | null; // Full text extracted from the invoice PDF
@@ -141,6 +142,7 @@ export async function extractInvoicesWithMistral(
supplier?: string | null;
totalAmount?: string | null;
subscription?: string | null;
+ recipient?: string | null;
}
): Promise {
// Load user's field configuration
@@ -184,6 +186,7 @@ export async function extractInvoicesWithMistral(
if (customKeywords.supplier) hints.push(`Fournisseur: ${customKeywords.supplier}`);
if (customKeywords.totalAmount) hints.push(`Montant total: ${customKeywords.totalAmount}`);
if (customKeywords.subscription) hints.push(`Abonnement: ${customKeywords.subscription}`);
+ if (customKeywords.recipient) hints.push(`Destinataire: ${customKeywords.recipient}`);
if (hints.length > 0) {
keywordsHint = `\n\nMots-clés personnalisés à rechercher:\n${hints.join("\n")}`;
@@ -200,12 +203,13 @@ export async function extractInvoicesWithMistral(
const prompt = `Tu es un expert en extraction de données de factures. Analyse ce document PDF et extrais toutes les factures qu'il contient.
Pour chaque facture trouvée, extrais les informations suivantes:
-- supplierName: Nom du fournisseur/vendeur
+- supplierName: Nom du fournisseur/vendeur (émetteur de la facture)
- invoiceNumber: Numéro de la facture
- invoiceDate: Date de la facture (format ISO 8601: YYYY-MM-DD)
- deliveryNoteNumber: Numéro du bon de livraison (si présent)
- orderNumber: Numéro de commande client (si présent)
- totalAmount: Montant total TTC (nombre décimal)
+- recipientName: Nom du destinataire/client (société ou personne à qui la facture est adressée)
- pageRange: Plage de pages de cette facture (ex: "1-2" ou "5")
${qualityScoreInstruction}
- extractedText: Texte complet extrait de la facture (tout le texte visible sur les pages de cette facture)
@@ -223,6 +227,7 @@ Réponds UNIQUEMENT avec un objet JSON valide au format suivant:
"deliveryNoteNumber": "...",
"orderNumber": "...",
"totalAmount": 123.45,
+ "recipientName": "...",
"pageRange": "1-2",
"qualityScore": 85,
"extractedText": "Texte complet de la facture...",
@@ -318,6 +323,7 @@ export function generateMetadataJSON(invoice: ExtractedInvoiceData): string {
deliveryNoteNumber: invoice.deliveryNoteNumber,
orderNumber: invoice.orderNumber,
totalAmount: invoice.totalAmount,
+ recipientName: invoice.recipientName,
pageRange: invoice.pageRange,
qualityScore: invoice.qualityScore,
extractedAt: new Date().toISOString(),
diff --git a/server/routers.ts b/server/routers.ts
index 429414a..a52acef 100644
--- a/server/routers.ts
+++ b/server/routers.ts
@@ -185,6 +185,7 @@ export const appRouter = router({
supplier: settings.supplierKeywords,
totalAmount: settings.totalAmountKeywords,
subscription: settings.subscriptionKeywords,
+ recipient: settings.recipientKeywords,
} : undefined;
const model = settings?.llmModel || "mistral-large-latest";
@@ -260,6 +261,7 @@ export const appRouter = router({
deliveryNoteNumber: invoiceData.deliveryNoteNumber,
orderNumber: invoiceData.orderNumber,
totalAmount: invoiceData.totalAmount?.toString(),
+ recipientName: invoiceData.recipientName,
pageRange: invoiceData.pageRange,
qualityScore: invoiceData.qualityScore,
extractedText: invoiceData.extractedText,
@@ -350,6 +352,7 @@ export const appRouter = router({
deliveryNoteNumber: z.string().optional(),
orderNumber: z.string().optional(),
totalAmount: z.string().optional(),
+ recipientName: z.string().optional(),
serviceConcerne: z.string().optional(),
typeAchat: z.enum(["CAPEX", "OPEX"]).optional(),
ventilationComptable: z.string().optional(),
@@ -459,6 +462,7 @@ export const appRouter = router({
supplierKeywords: z.string().optional(),
totalAmountKeywords: z.string().optional(),
subscriptionKeywords: z.string().optional(),
+ recipientKeywords: z.string().optional(),
sftpHost: z.string().optional(),
sftpPort: z.number().optional(),
sftpUsername: z.string().optional(),
diff --git a/todo.md b/todo.md
index 80f4b7e..3d2ecfd 100644
--- a/todo.md
+++ b/todo.md
@@ -555,5 +555,26 @@
- [x] Modifier la route tRPC `auth.loginLocal` pour accepter un username libre
- [x] Modifier la page Login.tsx pour remplacer le champ email par un champ "Identifiant"
- [x] Créer le compte admin `adminItinova` avec mot de passe `Itinova69!` en base de données locale
-- [ ] Créer le compte admin `adminItinova` sur le VPS
+- [x] Créer le compte admin `adminItinova` sur le VPS
+- [x] Déployer sur le VPS
+
+## Correction connexion adminItinova VPS
+- [x] Diagnostiquer le problème d'authentification (hash bcrypt Python vs Node.js)
+- [x] Corriger le hash du mot de passe sur le VPS (généré avec Node.js bcrypt)
+- [x] Vérifier que la connexion fonctionne (API tRPC répond 200 avec user)
+
+## Ajout du champ Destinataire
+- [x] Ajouter colonne `recipientName` dans la table `invoices` (schéma DB + migration)
+- [x] Ajouter colonne `recipientKeywords` dans la table `userSettings` (schéma DB + migration)
+- [x] Mettre à jour le prompt LLM pour extraire le destinataire
+- [x] Mettre à jour l'interface `ExtractedInvoiceData` dans invoiceExtractor.ts
+- [x] Mettre à jour les mots-clés personnalisés dans invoiceExtractor.ts
+- [x] Mettre à jour la route `settings.upsert` dans routers.ts
+- [x] Mettre à jour la route `invoices.update` dans routers.ts
+- [x] Ajouter le champ destinataire dans InvoiceDetail.tsx
+- [x] Ajouter le champ mots-clés destinataire dans Settings.tsx (onglet Mots-clés)
+- [x] Ajouter destinataire dans AutomationRules.tsx (conditions)
+- [x] Ajouter recipientName dans les champs LLM par défaut (db.ts)
+- [x] Ajouter colonne Destinataire dans la liste des factures (Invoices.tsx)
+- [x] Ajouter Destinataire dans l'export Excel
- [ ] Déployer sur le VPS