diff --git a/src/app/(app)/collection-pool/view-model.test.ts b/src/app/(app)/collection-pool/view-model.test.ts index b018482..f2d03bc 100644 --- a/src/app/(app)/collection-pool/view-model.test.ts +++ b/src/app/(app)/collection-pool/view-model.test.ts @@ -266,6 +266,71 @@ describe("buildVisibleRows sort modes (nearby pinning)", () => { }); }); +describe("buildVisibleRows — supplier-first sort (operational mode)", () => { + const todayYmd = "2026-07-10"; + + it("sorts by supplierName first when sortMode is operational", () => { + const rows = buildVisibleRows( + [ + makeRow({ id: "beta", supplierName: "Beta" }), + makeRow({ id: "acme", supplierName: "Acme" }), + makeRow({ id: "alpha", supplierName: "Alpha" }), + ], + { todayYmd, searchText: "", readyFilter: "all", sortMode: "operational" }, + ); + expect(rows.map((r) => r.id)).toEqual(["acme", "alpha", "beta"]); + }); + + it("falls through to assignmentState within the same supplier", () => { + const rows = buildVisibleRows( + [ + makeRow({ + id: "acme-unassigned", + supplierName: "Acme", + item_status: "collection_pool", + }), + makeRow({ + id: "acme-today", + supplierName: "Acme", + item_status: "assigned", + drv_id: "drv-1", + assigned_at: `${todayYmd}T00:00:00.000Z`, + }), + ], + { todayYmd, searchText: "", readyFilter: "all", sortMode: "operational" }, + ); + expect(rows.map((r) => r.id)).toEqual(["acme-today", "acme-unassigned"]); + }); + + it("nearby mode still uses cluster prefix before supplier", () => { + const rows = buildVisibleRows( + [ + makeRow({ + id: "beta-cluster-a", + supplierName: "Beta", + clusterSortKey: "cluster-a", + }), + makeRow({ + id: "acme-cluster-b", + supplierName: "Acme", + clusterSortKey: "cluster-b", + }), + makeRow({ + id: "acme-cluster-a", + supplierName: "Acme", + clusterSortKey: "cluster-a", + }), + ], + { todayYmd, searchText: "", readyFilter: "all", sortMode: "nearby" }, + ); + expect(rows.map((r) => r.id)).toEqual([ + "acme-cluster-a", + "beta-cluster-a", + "acme-cluster-b", + ]); + }); +}); + describe("buildSupplierGroups", () => { it("returns an empty array for empty input", () => { expect(buildSupplierGroups([], new Map())).toEqual([]); diff --git a/src/app/(app)/collection-pool/view-model.ts b/src/app/(app)/collection-pool/view-model.ts index 8faa1d4..cfab542 100644 --- a/src/app/(app)/collection-pool/view-model.ts +++ b/src/app/(app)/collection-pool/view-model.ts @@ -109,6 +109,12 @@ export function buildVisibleRows( if (clusterDiff !== 0) return clusterDiff; } + // Supplier name is the primary group key. Rows in the same + // supplier are then ordered by assignment urgency (today → + // unassigned → future), then by updated, then by PO + description. + const supplierDiff = (a.supplierName ?? "").localeCompare(b.supplierName ?? ""); + if (supplierDiff !== 0) return supplierDiff; + const stateDiff = ASSIGNMENT_SORT_ORDER[getAssignmentState(a, options.todayYmd)] - ASSIGNMENT_SORT_ORDER[getAssignmentState(b, options.todayYmd)]; @@ -118,8 +124,8 @@ export function buildVisibleRows( const updatedB = b.updated ?? ""; if (updatedA !== updatedB) return updatedA.localeCompare(updatedB); - return `${a.supplierName ?? ""}|${a.poNumber ?? ""}|${a.description ?? ""}`.localeCompare( - `${b.supplierName ?? ""}|${b.poNumber ?? ""}|${b.description ?? ""}`, + return `${a.poNumber ?? ""}|${a.description ?? ""}`.localeCompare( + `${b.poNumber ?? ""}|${b.description ?? ""}`, ); }); }