From a0c440dfae86d3cc7a00a3e3bb8a605dd9dfb7c7 Mon Sep 17 00:00:00 2001 From: Manus Date: Thu, 27 Aug 2026 13:02:07 +0000 Subject: [PATCH] =?UTF-8?q?Checkpoint:=20Le=20seuil=20d=E2=80=99=C3=A9ligi?= =?UTF-8?q?bilit=C3=A9=20et=20de=20validation=20BAP=20est=20centralis?= =?UTF-8?q?=C3=A9=20=C3=A0=2090=20%=20dans=20le=20serveur=20et=20l?= =?UTF-8?q?=E2=80=99interface.=20Les=20validations=20unitaires,=20TypeScri?= =?UTF-8?q?pt,=20build=20et=20rendu=20de=20la=20page=20Factures=20BAP=20so?= =?UTF-8?q?nt=20r=C3=A9ussis=20en=20sandbox.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/pages/InvoicesBAP.tsx | 13 +++++++------ server/bapEligibility.test.ts | 16 ++++++++++++++++ server/routers.ts | 7 ++++--- shared/bapEligibility.ts | 10 ++++++++++ todo.md | 5 +++++ 5 files changed, 42 insertions(+), 9 deletions(-) create mode 100644 server/bapEligibility.test.ts create mode 100644 shared/bapEligibility.ts diff --git a/client/src/pages/InvoicesBAP.tsx b/client/src/pages/InvoicesBAP.tsx index a8f1abd..d80c0af 100644 --- a/client/src/pages/InvoicesBAP.tsx +++ b/client/src/pages/InvoicesBAP.tsx @@ -32,6 +32,7 @@ import { TableRow, } from "@/components/ui/table"; import { trpc } from "@/lib/trpc"; +import { BAP_MIN_QUALITY_SCORE, meetsBapQualityThreshold } from "@shared/bapEligibility"; import { Search, FileText, Download, FileSpreadsheet, Trash2, Edit, Trash, CheckCircle, CheckCircle2, ShieldCheck, RefreshCw, FolderDown, ChevronDown, ChevronRight, ChevronsUpDown, CalendarDays, ArrowUpDown, ArrowUp, ArrowDown } from "lucide-react"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; @@ -394,7 +395,7 @@ export default function InvoicesBAP() { // Déclarée ici (avant filteredInvoices et statusCounts) pour éviter le hoisting error const isEligibleForBAPValidation = (invoice: any) => { return ( - (invoice.qualityScore || 0) === 100 && + meetsBapQualityThreshold(invoice.qualityScore) && invoice.exportStatus !== "exported" && invoice.isSubscription === 0 && invoice.serviceConcerne && @@ -526,19 +527,19 @@ export default function InvoicesBAP() { const getQualityBadge = (score: number | null) => { if (score === null) return -; - if (score === 100) return {score}%; + if (meetsBapQualityThreshold(score)) return {score}%; if (score >= 80) return {score}%; return {score}%; }; const isEligibleForExport = (invoice: any) => { // Une facture BAP est exportable si : - // 1. Score = 100% + // 1. Score >= 90 % (seuil BAP) // 2. Type d'achat rempli // 3. Service concerné rempli // 4. Ventilation comptable remplie return ( - (invoice.qualityScore || 0) === 100 && + meetsBapQualityThreshold(invoice.qualityScore) && invoice.typeAchat && invoice.serviceConcerne && invoice.ventilationComptable @@ -549,7 +550,7 @@ export default function InvoicesBAP() { const getBAPValidationTooltip = (invoice: any): string => { const reasons: string[] = []; - if ((invoice.qualityScore || 0) < 100) reasons.push("Score < 100%"); + if (!meetsBapQualityThreshold(invoice.qualityScore)) reasons.push(`Score < ${BAP_MIN_QUALITY_SCORE}%`); if (invoice.exportStatus === "exported") reasons.push("Déjà exportée"); if (invoice.isSubscription !== 0) reasons.push("Marquée comme abonnement"); if (!invoice.serviceConcerne) reasons.push("Service manquant"); @@ -655,7 +656,7 @@ export default function InvoicesBAP() {