Checkpoint: Bouton Télécharger toujours visible pour les factures en état Validé dans InvoicesBAP, même après rechargement. Le pdfUrl est récupéré depuis bapHistory via une nouvelle route tRPC getBapPdfUrls. Nommage uniforme Date - Fournisseur - N°Facture.pdf sur tous les points d'export.
This commit is contained in:
30
server/db.ts
30
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<void> {
|
||||
if (!db) return;
|
||||
await db.delete(invoiceLearnings).where(eq(invoiceLearnings.userId, userId));
|
||||
}
|
||||
|
||||
export async function getBapPdfUrlByInvoiceId(invoiceId: number): Promise<string | undefined> {
|
||||
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<Record<number, string>> {
|
||||
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<number, string> = {};
|
||||
for (const row of results) {
|
||||
if (row.invoiceId && row.pdfUrl && !map[row.invoiceId]) {
|
||||
map[row.invoiceId] = row.pdfUrl;
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@@ -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({
|
||||
|
||||
Reference in New Issue
Block a user