fix: paginate import history and report
This commit is contained in:
29
server/db.ts
29
server/db.ts
@@ -571,10 +571,15 @@ export async function getAllImportLogs(): Promise<ImportLog[]> {
|
||||
* les paramètres sensibles de messagerie. L'administrateur peut ainsi relier
|
||||
* chaque import à son compte, fichier source et déclencheur.
|
||||
*/
|
||||
export async function getImportLogsWithDetailsByUser(userId: number) {
|
||||
export type ImportLogPageOptions = {
|
||||
limit: number;
|
||||
offset: number;
|
||||
};
|
||||
|
||||
export async function getImportLogsWithDetailsByUser(userId: number, options: ImportLogPageOptions) {
|
||||
const db = await getDb();
|
||||
if (!db) return [];
|
||||
return db.select({
|
||||
if (!db) return { items: [], total: 0 };
|
||||
const items = await db.select({
|
||||
...getTableColumns(importLogs),
|
||||
userName: users.name,
|
||||
userEmail: users.email,
|
||||
@@ -585,13 +590,17 @@ export async function getImportLogsWithDetailsByUser(userId: number) {
|
||||
.leftJoin(users, eq(importLogs.userId, users.id))
|
||||
.leftJoin(sourceFiles, eq(importLogs.sourceFileId, sourceFiles.id))
|
||||
.where(eq(importLogs.userId, userId))
|
||||
.orderBy(desc(importLogs.importedAt));
|
||||
.orderBy(desc(importLogs.importedAt))
|
||||
.limit(options.limit)
|
||||
.offset(options.offset);
|
||||
const [total] = await db.select({ total: count() }).from(importLogs).where(eq(importLogs.userId, userId));
|
||||
return { items, total: Number(total?.total ?? 0) };
|
||||
}
|
||||
|
||||
export async function getAllImportLogsWithDetails() {
|
||||
export async function getAllImportLogsWithDetails(options: ImportLogPageOptions) {
|
||||
const db = await getDb();
|
||||
if (!db) return [];
|
||||
return db.select({
|
||||
if (!db) return { items: [], total: 0 };
|
||||
const items = await db.select({
|
||||
...getTableColumns(importLogs),
|
||||
userName: users.name,
|
||||
userEmail: users.email,
|
||||
@@ -601,7 +610,11 @@ export async function getAllImportLogsWithDetails() {
|
||||
.from(importLogs)
|
||||
.leftJoin(users, eq(importLogs.userId, users.id))
|
||||
.leftJoin(sourceFiles, eq(importLogs.sourceFileId, sourceFiles.id))
|
||||
.orderBy(desc(importLogs.importedAt));
|
||||
.orderBy(desc(importLogs.importedAt))
|
||||
.limit(options.limit)
|
||||
.offset(options.offset);
|
||||
const [total] = await db.select({ total: count() }).from(importLogs);
|
||||
return { items, total: Number(total?.total ?? 0) };
|
||||
}
|
||||
|
||||
export async function deleteAllImportLogs(userId: number | null): Promise<void> {
|
||||
|
||||
22
server/importLogPagination.test.ts
Normal file
22
server/importLogPagination.test.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
DEFAULT_IMPORT_LOG_PAGE_SIZE,
|
||||
MAX_IMPORT_LOG_PAGE_SIZE,
|
||||
normalizeImportLogPagination,
|
||||
} from "../shared/importLogPagination";
|
||||
|
||||
describe("pagination des journaux d'import", () => {
|
||||
it("retourne une page bornée par défaut au lieu de l'historique complet", () => {
|
||||
expect(normalizeImportLogPagination()).toEqual({
|
||||
limit: DEFAULT_IMPORT_LOG_PAGE_SIZE,
|
||||
offset: 0,
|
||||
});
|
||||
});
|
||||
|
||||
it("borne les entrées utilisateur pour préserver la réactivité", () => {
|
||||
expect(normalizeImportLogPagination({ limit: MAX_IMPORT_LOG_PAGE_SIZE + 1, offset: -20 })).toEqual({
|
||||
limit: MAX_IMPORT_LOG_PAGE_SIZE,
|
||||
offset: 0,
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -3,6 +3,7 @@ import { COOKIE_NAME } from "@shared/const";
|
||||
import { BAP_MIN_QUALITY_SCORE, meetsBapQualityThreshold } from "@shared/bapEligibility";
|
||||
import { requiresBapBeforeOriginalPdfExport } from "@shared/bapExportGuard";
|
||||
import { calculateInvoiceQualityScore, withCalculatedInvoiceQuality } from "@shared/invoiceQuality";
|
||||
import { normalizeImportLogPagination } from "@shared/importLogPagination";
|
||||
import { webPortalUrlSchema } from "./webPortalUrl";
|
||||
|
||||
interface Condition {
|
||||
@@ -1727,12 +1728,15 @@ export const appRouter = router({
|
||||
|
||||
// ============= IMPORT LOGS ROUTES =============
|
||||
importLogs: router({
|
||||
getByUser: protectedProcedure.query(async ({ ctx }) => {
|
||||
getByUser: protectedProcedure
|
||||
.input(z.object({ limit: z.number().int().positive().optional(), offset: z.number().int().min(0).optional() }).optional())
|
||||
.query(async ({ ctx, input }) => {
|
||||
const pagination = normalizeImportLogPagination(input);
|
||||
// Les admins voient tous les logs d'import
|
||||
if (ctx.user.role === 'admin') {
|
||||
return getAllImportLogsWithDetails();
|
||||
return getAllImportLogsWithDetails(pagination);
|
||||
}
|
||||
return getImportLogsWithDetailsByUser(ctx.user.id);
|
||||
return getImportLogsWithDetailsByUser(ctx.user.id, pagination);
|
||||
}),
|
||||
|
||||
deleteAll: protectedProcedure.mutation(async ({ ctx }) => {
|
||||
|
||||
Reference in New Issue
Block a user