Checkpoint: Les admins voient désormais toutes les factures (tous userId) : getById, update, delete, validateBAP, devalidateBAP, validateBAPBulk, reprocessSelected, regenerateBapPdf, search, exportToExcel, exportToPdf, exportSFTP, bapHistory.delete/regenerate — tous corrigés pour les admins.
This commit is contained in:
@@ -268,11 +268,17 @@ export async function deleteInvoice(id: number) {
|
||||
await db.delete(invoices).where(eq(invoices.id, id));
|
||||
}
|
||||
|
||||
export async function searchInvoices(userId: number, query: string): Promise<Invoice[]> {
|
||||
export async function searchInvoices(userId: number | null, query: string): Promise<Invoice[]> {
|
||||
const db = await getDb();
|
||||
if (!db) return [];
|
||||
|
||||
const searchPattern = `%${query}%`;
|
||||
if (userId === null) {
|
||||
// Admin : recherche globale sans filtre userId
|
||||
return db.select().from(invoices)
|
||||
.where(sql`(${invoices.supplierName} LIKE ${searchPattern} OR ${invoices.invoiceNumber} LIKE ${searchPattern})`)
|
||||
.orderBy(desc(invoices.createdAt));
|
||||
}
|
||||
return db.select().from(invoices)
|
||||
.where(
|
||||
and(
|
||||
|
||||
@@ -399,7 +399,7 @@ export const appRouter = router({
|
||||
.input(z.object({ id: z.number() }))
|
||||
.query(async ({ input, ctx }) => {
|
||||
const invoice = await getInvoiceById(input.id);
|
||||
if (!invoice || invoice.userId !== ctx.user.id) {
|
||||
if (!invoice || (ctx.user.role !== 'admin' && invoice.userId !== ctx.user.id)) {
|
||||
throw new TRPCError({ code: "NOT_FOUND" });
|
||||
}
|
||||
return invoice;
|
||||
@@ -425,7 +425,7 @@ export const appRouter = router({
|
||||
}))
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const invoice = await getInvoiceById(input.id);
|
||||
if (!invoice || invoice.userId !== ctx.user.id) {
|
||||
if (!invoice || (ctx.user.role !== 'admin' && invoice.userId !== ctx.user.id)) {
|
||||
throw new TRPCError({ code: "NOT_FOUND" });
|
||||
}
|
||||
|
||||
@@ -441,7 +441,7 @@ export const appRouter = router({
|
||||
.input(z.object({ id: z.number() }))
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const invoice = await getInvoiceById(input.id);
|
||||
if (!invoice || invoice.userId !== ctx.user.id) {
|
||||
if (!invoice || (ctx.user.role !== 'admin' && invoice.userId !== ctx.user.id)) {
|
||||
throw new TRPCError({ code: "NOT_FOUND" });
|
||||
}
|
||||
|
||||
@@ -453,7 +453,7 @@ export const appRouter = router({
|
||||
.input(z.object({ id: z.number() }))
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const invoice = await getInvoiceById(input.id);
|
||||
if (!invoice || invoice.userId !== ctx.user.id) {
|
||||
if (!invoice || (ctx.user.role !== 'admin' && invoice.userId !== ctx.user.id)) {
|
||||
throw new TRPCError({ code: "NOT_FOUND" });
|
||||
}
|
||||
// Vérifier les critères de validation BAP
|
||||
@@ -666,7 +666,7 @@ export const appRouter = router({
|
||||
let processed = 0;
|
||||
for (const id of input.invoiceIds) {
|
||||
const invoice = await getInvoiceById(id);
|
||||
if (!invoice || invoice.userId !== ctx.user.id) continue;
|
||||
if (!invoice || (ctx.user.role !== 'admin' && invoice.userId !== ctx.user.id)) continue;
|
||||
await updateInvoice(id, {
|
||||
bapValidated: 0,
|
||||
bapValidatedAt: null,
|
||||
@@ -680,7 +680,7 @@ export const appRouter = router({
|
||||
// ── Validation BAP en masse ──────────────────────────────
|
||||
validateBAPBulk: protectedProcedure
|
||||
.mutation(async ({ ctx }) => {
|
||||
const allInvoices = await getInvoicesByUser(ctx.user.id);
|
||||
const allInvoices = ctx.user.role === 'admin' ? await getAllInvoices() : await getInvoicesByUser(ctx.user.id);
|
||||
// Filtrer les factures éligibles (non déjà validées)
|
||||
const eligible = allInvoices.filter((inv: any) =>
|
||||
(inv.qualityScore || 0) >= 100 &&
|
||||
@@ -862,7 +862,7 @@ export const appRouter = router({
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
// Relance UNIQUEMENT les automatismes (sans re-extraction LLM)
|
||||
const { applyAutomationRules } = await import("./automationEngine");
|
||||
const allInvoices = await getInvoicesByUser(ctx.user.id);
|
||||
const allInvoices = ctx.user.role === 'admin' ? await getAllInvoices() : await getInvoicesByUser(ctx.user.id);
|
||||
const selected = allInvoices.filter(inv => input.invoiceIds.includes(inv.id));
|
||||
if (selected.length === 0) throw new TRPCError({ code: 'NOT_FOUND', message: 'Aucune facture trouvée' });
|
||||
|
||||
@@ -893,7 +893,7 @@ export const appRouter = router({
|
||||
.input(z.object({ invoiceId: z.number() }))
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const invoice = await getInvoiceById(input.invoiceId);
|
||||
if (!invoice || invoice.userId !== ctx.user.id) {
|
||||
if (!invoice || (ctx.user.role !== 'admin' && invoice.userId !== ctx.user.id)) {
|
||||
throw new TRPCError({ code: 'NOT_FOUND', message: 'Facture introuvable' });
|
||||
}
|
||||
if (!invoice.bapValidated) {
|
||||
@@ -983,7 +983,7 @@ export const appRouter = router({
|
||||
const { url } = await localStoragePut(bapKey, Buffer.from(signedPdfBytes), 'application/pdf');
|
||||
|
||||
// Mettre à jour la dernière entrée bapHistory de cette facture avec le nouveau pdfUrl
|
||||
const allEntries = await getBapHistoryByUser(ctx.user.id);
|
||||
const allEntries = ctx.user.role === 'admin' ? await getAllBapHistory() : await getBapHistoryByUser(ctx.user.id);
|
||||
const latestEntry = allEntries
|
||||
.filter(e => e.invoiceId === input.invoiceId)
|
||||
.sort((a, b) => new Date(b.validatedAt).getTime() - new Date(a.validatedAt).getTime())[0];
|
||||
@@ -1000,6 +1000,9 @@ export const appRouter = router({
|
||||
search: protectedProcedure
|
||||
.input(z.object({ query: z.string() }))
|
||||
.query(async ({ input, ctx }) => {
|
||||
if (ctx.user.role === 'admin') {
|
||||
return searchInvoices(null, input.query);
|
||||
}
|
||||
return searchInvoices(ctx.user.id, input.query);
|
||||
}),
|
||||
|
||||
@@ -1020,7 +1023,7 @@ export const appRouter = router({
|
||||
delete: protectedProcedure
|
||||
.input(z.object({ id: z.number() }))
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const entries = await getBapHistoryByUser(ctx.user.id);
|
||||
const entries = ctx.user.role === 'admin' ? await getAllBapHistory() : await getBapHistoryByUser(ctx.user.id);
|
||||
const entry = entries.find(e => e.id === input.id);
|
||||
if (!entry) throw new TRPCError({ code: 'NOT_FOUND' });
|
||||
await deleteBapHistoryEntry(input.id);
|
||||
@@ -1031,12 +1034,12 @@ export const appRouter = router({
|
||||
regenerate: protectedProcedure
|
||||
.input(z.object({ id: z.number() }))
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const entries = await getBapHistoryByUser(ctx.user.id);
|
||||
const entries = ctx.user.role === 'admin' ? await getAllBapHistory() : await getBapHistoryByUser(ctx.user.id);
|
||||
const entry = entries.find(e => e.id === input.id);
|
||||
if (!entry) throw new TRPCError({ code: 'NOT_FOUND' });
|
||||
|
||||
const invoice = await getInvoiceById(entry.invoiceId);
|
||||
if (!invoice || invoice.userId !== ctx.user.id) {
|
||||
if (!invoice || (ctx.user.role !== 'admin' && invoice.userId !== ctx.user.id)) {
|
||||
throw new TRPCError({ code: 'NOT_FOUND', message: 'Facture source introuvable' });
|
||||
}
|
||||
|
||||
@@ -1250,7 +1253,7 @@ export const appRouter = router({
|
||||
);
|
||||
|
||||
const validInvoices = invoices.filter(
|
||||
inv => inv && inv.userId === ctx.user.id
|
||||
inv => inv && (ctx.user.role === 'admin' || inv.userId === ctx.user.id)
|
||||
);
|
||||
|
||||
// Return invoice data for Excel generation on client side
|
||||
@@ -1301,7 +1304,7 @@ export const appRouter = router({
|
||||
);
|
||||
|
||||
const invalidInvoices = invoices.filter(
|
||||
inv => !inv || inv.userId !== ctx.user.id || (inv.qualityScore || 0) < 100
|
||||
inv => !inv || (ctx.user.role !== 'admin' && inv.userId !== ctx.user.id) || (inv.qualityScore || 0) < 100
|
||||
);
|
||||
|
||||
if (invalidInvoices.length > 0) {
|
||||
@@ -1560,7 +1563,7 @@ export const appRouter = router({
|
||||
for (const invoiceId of input.invoiceIds) {
|
||||
try {
|
||||
const invoice = await getInvoiceById(invoiceId);
|
||||
if (!invoice || invoice.userId !== ctx.user.id) {
|
||||
if (!invoice || (ctx.user.role !== 'admin' && invoice.userId !== ctx.user.id)) {
|
||||
errorCount++;
|
||||
continue;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user