test(collection-map): pin-bucket split; absorb orphaned assigned items into pool

This commit is contained in:
SJCoetz 2026-07-11 23:45:42 +02:00
parent d4c72057bf
commit adfde8a0fa
2 changed files with 68 additions and 1 deletions

View file

@ -0,0 +1,64 @@
import { describe, expect, it } from "vitest";
import { splitSupplierBucket } from "./pin-model";
describe("splitSupplierBucket", () => {
it("returns empty buckets for empty input", () => {
const { assignedByDriver, poolItems } = splitSupplierBucket([]);
expect(assignedByDriver.size).toBe(0);
expect(poolItems).toEqual([]);
});
it("groups assigned items by driver", () => {
const items = [
{ id: "a", item_status: "assigned" as const, drv_id: "u-1", ready_for_collection: true },
{ id: "b", item_status: "assigned" as const, drv_id: "u-1", ready_for_collection: true },
{ id: "c", item_status: "assigned" as const, drv_id: "u-2", ready_for_collection: false },
];
const { assignedByDriver, poolItems } = splitSupplierBucket(items);
expect(assignedByDriver.size).toBe(2);
expect(assignedByDriver.get("u-1")?.items.map((i) => i.id)).toEqual(["a", "b"]);
expect(assignedByDriver.get("u-2")?.items.map((i) => i.id)).toEqual(["c"]);
expect(poolItems).toEqual([]);
});
it("places collection_pool items into the unassigned bucket", () => {
const items = [
{ id: "a", item_status: "assigned" as const, drv_id: "u-1", ready_for_collection: true },
{ id: "p1", item_status: "collection_pool" as const, ready_for_collection: true },
{ id: "p2", item_status: "collection_pool" as const, ready_for_collection: false },
];
const { assignedByDriver, poolItems } = splitSupplierBucket(items);
expect(assignedByDriver.size).toBe(1);
expect(poolItems.map((i) => i.id)).toEqual(["p1", "p2"]);
});
it("treats 'collected' items as routed (same bucket as assigned)", () => {
const items = [
{ id: "a", item_status: "collected" as const, drv_id: "u-1", ready_for_collection: true },
];
const { assignedByDriver, poolItems } = splitSupplierBucket(items);
expect(assignedByDriver.size).toBe(1);
expect(assignedByDriver.get("u-1")?.items.map((i) => i.id)).toEqual(["a"]);
expect(poolItems).toEqual([]);
});
it("ignores assigned items without a drv_id", () => {
// Defensive: data shouldn't reach this state, but if it does, the
// unassigned bucket absorbs the item so it doesn't silently vanish.
const items = [
{ id: "orphan", item_status: "assigned" as const, ready_for_collection: true },
];
const { assignedByDriver, poolItems } = splitSupplierBucket(items);
expect(assignedByDriver.size).toBe(0);
expect(poolItems.map((i) => i.id)).toEqual(["orphan"]);
});
it("reports readyAll=false when any item in a driver's bucket is not ready", () => {
const items = [
{ id: "a", item_status: "assigned" as const, drv_id: "u-1", ready_for_collection: true },
{ id: "b", item_status: "assigned" as const, drv_id: "u-1", ready_for_collection: false },
];
const { assignedByDriver } = splitSupplierBucket(items);
expect(assignedByDriver.get("u-1")?.readyAll).toBe(false);
});
});

View file

@ -39,7 +39,10 @@ export function splitSupplierBucket<
entry.items.push(it);
if (!it.ready_for_collection) entry.readyAll = false;
assignedByDriver.set(it.drv_id, entry);
} else if (it.item_status === "collection_pool") {
} else {
// Anything that isn't routed-to-a-driver (no `drv_id`; or
// `collection_pool`; or an unexpected status) goes into the pool
// bucket so it never silently vanishes from the map.
poolItems.push(it);
}
}