diff --git a/client/src/pages/InvoicesBAP.tsx b/client/src/pages/InvoicesBAP.tsx
index 6a3cc6b..d11e6d9 100644
--- a/client/src/pages/InvoicesBAP.tsx
+++ b/client/src/pages/InvoicesBAP.tsx
@@ -97,6 +97,14 @@ export default function InvoicesBAP() {
const { data: allInvoices, isLoading } = trpc.invoices.list.useQuery();
// Filter for BAP invoices only (Abonnement = NON, isSubscription = 0)
const invoices = allInvoices?.filter(inv => inv.isSubscription === 0);
+ // IDs des factures déjà validées BAP (pour charger leurs pdfUrl depuis bapHistory)
+ const validatedInvoiceIds = (invoices || []).filter(inv => inv.bapValidated === 1).map(inv => inv.id);
+ const { data: persistedBapPdfUrls } = trpc.invoices.getBapPdfUrls.useQuery(
+ { invoiceIds: validatedInvoiceIds },
+ { enabled: validatedInvoiceIds.length > 0 }
+ );
+ // Fusionner les pdfUrl persistés (depuis bapHistory) avec ceux en mémoire (validation en cours)
+ const allBapPdfUrls = { ...(persistedBapPdfUrls || {}), ...bapPdfUrls };
const { data: departments } = trpc.departments.getByUser.useQuery();
const { data: allocations } = trpc.accountingAllocations.getByUser.useQuery();
const utils = trpc.useUtils();
@@ -779,13 +787,23 @@ export default function InvoicesBAP() {
Validé
- {bapPdfUrls[invoice.id] && (
+ {allBapPdfUrls[invoice.id] ? (
+ ) : (
+
diff --git a/server/db.ts b/server/db.ts
index 6e91aa5..303434f 100644
--- a/server/db.ts
+++ b/server/db.ts
@@ -1,4 +1,4 @@
-import { eq, and, desc, sql } from "drizzle-orm";
+import { eq, and, desc, sql, inArray } from "drizzle-orm";
import { drizzle } from "drizzle-orm/mysql2";
import {
InsertUser,
@@ -891,3 +891,31 @@ export async function deleteAllLearnings(userId: number): Promise {
if (!db) return;
await db.delete(invoiceLearnings).where(eq(invoiceLearnings.userId, userId));
}
+
+export async function getBapPdfUrlByInvoiceId(invoiceId: number): Promise {
+ const db = await getDb();
+ if (!db) return undefined;
+ const results = await db.select({ pdfUrl: bapHistory.pdfUrl })
+ .from(bapHistory)
+ .where(eq(bapHistory.invoiceId, invoiceId))
+ .orderBy(desc(bapHistory.validatedAt))
+ .limit(1);
+ return results[0]?.pdfUrl ?? undefined;
+}
+
+export async function getBapPdfUrlsByInvoiceIds(invoiceIds: number[]): Promise> {
+ const db = await getDb();
+ if (!db || invoiceIds.length === 0) return {};
+ const results = await db.select({ invoiceId: bapHistory.invoiceId, pdfUrl: bapHistory.pdfUrl, validatedAt: bapHistory.validatedAt })
+ .from(bapHistory)
+ .where(inArray(bapHistory.invoiceId, invoiceIds))
+ .orderBy(desc(bapHistory.validatedAt));
+ // Keep only the most recent pdfUrl per invoiceId
+ const map: Record = {};
+ for (const row of results) {
+ if (row.invoiceId && row.pdfUrl && !map[row.invoiceId]) {
+ map[row.invoiceId] = row.pdfUrl;
+ }
+ }
+ return map;
+}
diff --git a/server/routers.ts b/server/routers.ts
index 9457e47..31bfe3e 100644
--- a/server/routers.ts
+++ b/server/routers.ts
@@ -71,6 +71,7 @@ import {
upsertLearning,
deleteLearning,
deleteAllLearnings,
+ getBapPdfUrlsByInvoiceIds,
} from "./db";
import { loginLocal, hashPassword, getAzureAuthUrl, isAzureAdConfigured, generateToken } from "./auth";
import { extractInvoicesWithMistral, generateMetadataJSON } from "./invoiceExtractor";
@@ -896,6 +897,13 @@ export const appRouter = router({
}
return { success: true, processed, errors, results };
}),
+ // ── Récupérer les pdfUrl BAP pour une liste de factures validées ─────────────────
+ getBapPdfUrls: protectedProcedure
+ .input(z.object({ invoiceIds: z.array(z.number()) }))
+ .query(async ({ input }) => {
+ if (input.invoiceIds.length === 0) return {};
+ return getBapPdfUrlsByInvoiceIds(input.invoiceIds);
+ }),
// ── Relancer les automatismes sur une sélection ─────────────────
reprocessSelected: protectedProcedure
.input(z.object({