Checkpoint: Ajout colonne "Source import" (Email / Dossier / Fichier) dans l'historique des imports : schéma DB migré, backend mis à jour (routers.ts, emailImportService.ts, folderImportService.ts), frontend History.tsx avec badges colorés dans le tableau et le dialog de détails.

This commit is contained in:
Manus
2026-06-17 06:11:46 -04:00
parent b97efb5c57
commit f7d3f6d5b3
9 changed files with 2210 additions and 0 deletions

View File

@@ -23,6 +23,9 @@ import {
RotateCcw,
Package,
X,
Upload,
FolderOpen,
Mail,
} from "lucide-react";
import { Button } from "@/components/ui/button";
import { toast } from "sonner";
@@ -307,6 +310,7 @@ export default function History() {
<TableRow className="bg-gray-50">
<TableHead className="font-semibold">Fichier importé</TableHead>
<TableHead className="font-semibold">Date d'import</TableHead>
<TableHead className="font-semibold text-center">Source</TableHead>
<TableHead className="font-semibold text-center">Détectées</TableHead>
<TableHead className="font-semibold text-center">Importées</TableHead>
<TableHead className="font-semibold text-center">Doublons</TableHead>
@@ -326,6 +330,24 @@ export default function History() {
<TableCell className="text-sm text-gray-600">
{new Date(log.importedAt).toLocaleString("fr-FR")}
</TableCell>
<TableCell className="text-center">
{log.importSource === "email" ? (
<span className="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium bg-blue-100 text-blue-700 border border-blue-200">
<Mail className="h-3 w-3" />
Email
</span>
) : log.importSource === "folder" ? (
<span className="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium bg-purple-100 text-purple-700 border border-purple-200">
<FolderOpen className="h-3 w-3" />
Dossier
</span>
) : (
<span className="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium bg-gray-100 text-gray-700 border border-gray-200">
<Upload className="h-3 w-3" />
Fichier
</span>
)}
</TableCell>
<TableCell className="text-center">
<Badge variant="outline" className="font-mono">
{log.totalInvoicesDetected}
@@ -408,6 +430,18 @@ export default function History() {
<p className="text-xs text-gray-500 font-medium mb-1">Date d'import</p>
<p className="text-sm font-semibold">{new Date(selectedLog.importedAt).toLocaleString("fr-FR")}</p>
</div>
<div className="bg-gray-50 rounded-lg p-3">
<p className="text-xs text-gray-500 font-medium mb-1">Source import</p>
<p className="text-sm font-semibold">
{selectedLog.importSource === "email" ? (
<span className="inline-flex items-center gap-1 text-blue-700"><Mail className="h-4 w-4" /> Email</span>
) : selectedLog.importSource === "folder" ? (
<span className="inline-flex items-center gap-1 text-purple-700"><FolderOpen className="h-4 w-4" /> Dossier</span>
) : (
<span className="inline-flex items-center gap-1 text-gray-700"><Upload className="h-4 w-4" /> Fichier</span>
)}
</p>
</div>
</div>
{/* Statistiques */}

View File

@@ -0,0 +1 @@
ALTER TABLE `importLogs` ADD `importSource` enum('file','folder','email') DEFAULT 'file' NOT NULL;

File diff suppressed because it is too large Load Diff

View File

@@ -225,6 +225,13 @@
"when": 1781021650065,
"tag": "0031_mean_squadron_supreme",
"breakpoints": true
},
{
"idx": 32,
"version": "5",
"when": 1781690960721,
"tag": "0032_volatile_jocasta",
"breakpoints": true
}
]
}

View File

@@ -223,6 +223,8 @@ export const importLogs = mysqlTable("importLogs", {
duplicateDetails: text("duplicateDetails"), // JSON array of duplicate invoice info
errorDetails: text("errorDetails"), // JSON array of error messages
warningMessage: text("warningMessage"), // Warning message (e.g. quota exhausted)
/** Source du mode d'import : 'file' = upload manuel, 'folder' = dossier automatique, 'email' = import par email */
importSource: mysqlEnum("importSource", ["file", "folder", "email"]).default("file").notNull(),
importedAt: timestamp("importedAt").defaultNow().notNull(),
});

View File

@@ -232,6 +232,7 @@ async function processEmailAttachment(
duplicateDetails: duplicateDetails.length > 0 ? JSON.stringify(duplicateDetails) : null,
errorDetails: errorDetails.length > 0 ? JSON.stringify(errorDetails) : null,
warningMessage,
importSource: "email",
});
console.log(`[EmailImport] Successfully processed attachment: ${fileName}`);

View File

@@ -191,6 +191,7 @@ async function processFolderFile(
errors: errorsCount,
duplicateDetails: duplicateDetails.length > 0 ? JSON.stringify(duplicateDetails) : null,
errorDetails: errorDetails.length > 0 ? JSON.stringify(errorDetails) : null,
importSource: "folder",
});
// Move file to processed folder

View File

@@ -370,6 +370,7 @@ export const appRouter = router({
errors: errorsCount,
duplicateDetails: JSON.stringify(duplicateDetails),
errorDetails: JSON.stringify(errorDetails),
importSource: "file",
});
} catch (error: any) {

View File

@@ -667,3 +667,11 @@
- [x] Job cron WebDev : vérification périodique selon fréquence configurée (setInterval en mémoire)
- [x] Frontend VentilationFreePro.tsx : wrapper Tabs (onglet 1 = import manuel, onglet 2 = paramétrage)
- [x] Onglet Paramétrage : formulaire credentials FreePro web, fréquence, date antériorité, bouton "Forcer récupération", statut dernière récupération
## Colonne Source import dans l'historique des imports
- [x] Ajouter colonne importSource (file/folder/email) dans la table importLogs (schéma + migration)
- [x] Enregistrer importSource="file" lors d'un import manuel (routers.ts)
- [x] Enregistrer importSource="email" lors d'un import par email (emailImportService.ts)
- [x] Enregistrer importSource="folder" lors d'un import par dossier (folderImportService.ts)
- [x] Afficher la colonne "Source" avec badge coloré dans le tableau History.tsx (Email=bleu, Dossier=violet, Fichier=gris)
- [x] Afficher la source dans le dialog de détails de l'import