fix(orders): correct page math in backfill endpoint (perPage must equal limit)

This commit is contained in:
Dave 2026-08-31 01:05:54 +02:00
parent 463265fe36
commit 2dbe96da23
2 changed files with 17 additions and 16 deletions

View file

@ -72,16 +72,16 @@ describe("POST /api/v1/orders/backfill-duplicate-checks", () => {
it("returns done=false and advances nextSkip when more rows remain", async () => {
const { getAdminPocketBase } = await import("@/lib/server/pocketbase-admin");
// Fetch of 100 with limit=2 yields 3 rows (limit+1) — implies
// more rows remain after this 2-row chunk.
// perPage=limit=2 returns 2 items, totalItems=5 → hasMore=true
// (2 items consumed, 3 rows remain after offset 2).
vi.mocked(getAdminPocketBase).mockResolvedValueOnce({
autoCancellation: vi.fn(),
collection: () => ({
getList: vi.fn().mockResolvedValue({
items: [{ id: "a" }, { id: "b" }, { id: "c" }],
totalItems: 3,
items: [{ id: "a" }, { id: "b" }],
totalItems: 5,
page: 1,
perPage: 3,
perPage: 2,
}),
}),
} as unknown as Awaited<ReturnType<typeof getAdminPocketBase>>);
@ -106,7 +106,7 @@ describe("POST /api/v1/orders/backfill-duplicate-checks", () => {
items: [{ id: "x" }],
totalItems: 1,
page: 5,
perPage: 3,
perPage: 2,
});
vi.mocked(getAdminPocketBase).mockResolvedValueOnce({
autoCancellation: vi.fn(),
@ -115,8 +115,8 @@ describe("POST /api/v1/orders/backfill-duplicate-checks", () => {
const res = await POST(backfillRequest("?limit=2&skip=8"));
expect(res.status).toBe(200);
// skip=8, limit=2 → page = floor(8/2) + 1 = 5
expect(getListSpy).toHaveBeenCalledWith(5, 3, expect.any(Object));
// skip=8, limit=2 → page = skip/limit + 1 = 5, perPage = limit = 2
expect(getListSpy).toHaveBeenCalledWith(5, 2, expect.any(Object));
expect((await res.json()).nextSkip).toBe(9);
});

View file

@ -89,22 +89,23 @@ export async function POST(req: NextRequest) {
const pb = await getAdminPocketBase();
pb.autoCancellation(false);
// Convert `skip` to a 1-based page number. PB's getList uses page,
// not offset, so we compute `page = floor(skip/limit) + 1`.
const page = Math.floor(skip / limit) + 1;
// PB pagination: getList(page, perPage) returns items at offsets
// [(page-1)*perPage, page*perPage). With perPage = limit and
// page = skip/limit + 1, the slice starts exactly at offset `skip`.
// `hasMore` is derived from `totalItems` rather than fetching +1.
const page = skip / limit + 1;
const perPage = limit;
// Fetch `limit + 1` so we can detect whether more rows remain after
// this chunk without a second `count` query.
const orders = await pb.collection("orders").getList<{ id: string }>(
page,
limit + 1,
perPage,
{
fields: "id",
sort: "created",
},
);
const slice = orders.items.slice(0, limit);
const hasMore = orders.items.length > limit;
const slice = orders.items;
const hasMore = skip + slice.length < orders.totalItems;
let ordersProcessed = 0;
const failures: Array<{ orderId: string; error: string }> = [];