From 98a0bc414357ff1f33748d5f29d2a9067578ee07 Mon Sep 17 00:00:00 2001 From: SJCoetz Date: Wed, 29 Jul 2026 19:58:07 +0200 Subject: [PATCH] feat(buyer-tasks): generatePoForGroup creates PO and updates items Co-authored-by: Orca --- src/lib/server/buyer-tasks-service.test.ts | 57 ++++++++++++++++++++++ src/lib/server/buyer-tasks-service.ts | 28 +++++++++++ 2 files changed, 85 insertions(+) diff --git a/src/lib/server/buyer-tasks-service.test.ts b/src/lib/server/buyer-tasks-service.test.ts index 22021bc..024c0f4 100644 --- a/src/lib/server/buyer-tasks-service.test.ts +++ b/src/lib/server/buyer-tasks-service.test.ts @@ -251,4 +251,61 @@ describe("listBuyerTasks", () => { expect(groups).toHaveLength(1); expect(groups[0].step).toBe("po_sent"); }); +}); + +describe("generatePoForGroup", () => { + it("creates a PO and updates items", async () => { + const createPo = vi.fn().mockResolvedValue({ id: "po-new" }); + const updateItem = vi.fn().mockResolvedValue({}); + const admin = { + collection: vi.fn().mockImplementation((name: string) => { + if (name === "purchase_orders") return { create: createPo }; + if (name === "order_items") return { update: updateItem }; + return { getList: vi.fn(), getFullList: vi.fn() }; + }), + }; + vi.mocked(getAdminPocketBase).mockResolvedValue(admin as never); + + const { generatePoForGroup } = await import("./buyer-tasks-service"); + const poId = await generatePoForGroup("order-1", "sup-1", [ + { id: "item-1", costPrice: 25, quantity: 2 }, + ]); + + expect(poId).toBe("po-new"); + expect(createPo).toHaveBeenCalledWith({ + order: "order-1", + supplier: "sup-1", + status: "draft", + }); + expect(updateItem).toHaveBeenCalledWith("item-1", { + purchase_order: "po-new", + item_status: "po_generated", + }); + }); + + it("returns null when no items provided", async () => { + const admin = { collection: vi.fn() }; + vi.mocked(getAdminPocketBase).mockResolvedValue(admin as never); + + const { generatePoForGroup } = await import("./buyer-tasks-service"); + const poId = await generatePoForGroup("order-1", "sup-1", []); + + expect(poId).toBeNull(); + }); + + it("throws when orderId is missing", async () => { + const admin = { collection: vi.fn() }; + vi.mocked(getAdminPocketBase).mockResolvedValue(admin as never); + + const { generatePoForGroup } = await import("./buyer-tasks-service"); + await expect(generatePoForGroup("", "sup-1", [{ id: "item-1", costPrice: 25, quantity: 1 }])).rejects.toThrow(/orderId/i); + }); + + it("throws when supplierId is missing", async () => { + const admin = { collection: vi.fn() }; + vi.mocked(getAdminPocketBase).mockResolvedValue(admin as never); + + const { generatePoForGroup } = await import("./buyer-tasks-service"); + await expect(generatePoForGroup("order-1", "", [{ id: "item-1", costPrice: 25, quantity: 1 }])).rejects.toThrow(/supplierId/i); + }); }); \ No newline at end of file diff --git a/src/lib/server/buyer-tasks-service.ts b/src/lib/server/buyer-tasks-service.ts index ba5bf56..fc3091d 100644 --- a/src/lib/server/buyer-tasks-service.ts +++ b/src/lib/server/buyer-tasks-service.ts @@ -118,3 +118,31 @@ export async function listBuyerTasks(tab: BuyerTaskTab): Promise +): Promise { + if (!orderId) throw new Error("orderId is required"); + if (!supplierId) throw new Error("supplierId is required"); + if (items.length === 0) return null; + + const admin = await getAdminPocketBase(); + const po = await admin.collection("purchase_orders").create({ + order: orderId, + supplier: supplierId, + status: "draft", + }); + + await Promise.all( + items.map((item) => + admin.collection("order_items").update(item.id, { + purchase_order: po.id, + item_status: "po_generated", + }) + ) + ); + + return po.id; +}