From f7de9d44fd50576c5a2bdb5dda5b72c9581450bf Mon Sep 17 00:00:00 2001 From: SJCoetz Date: Thu, 30 Jul 2026 22:04:37 +0200 Subject: [PATCH] feat(stock-quick-draft): removeQuickDraftLine Co-authored-by: Orca --- .../server/stock-quick-draft-service.test.ts | 38 +++++++++++++++++++ src/lib/server/stock-quick-draft-service.ts | 28 ++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/src/lib/server/stock-quick-draft-service.test.ts b/src/lib/server/stock-quick-draft-service.test.ts index acb3221..528570c 100644 --- a/src/lib/server/stock-quick-draft-service.test.ts +++ b/src/lib/server/stock-quick-draft-service.test.ts @@ -162,6 +162,7 @@ vi.mock("./pocketbase-admin", () => ({ import { addQuickDraftLine, getStockItemSupplierHistory, + removeQuickDraftLine, searchStockItemsForQuickDraft, } from "./stock-quick-draft-service"; @@ -580,4 +581,41 @@ describe("addQuickDraftLine", () => { if (result.ok) return; expect(result.reason).toBe("stock_item_not_found"); }); +}); + +describe("removeQuickDraftLine", () => { + it("deletes the line and returns ok", async () => { + const supplierId = ( + await pbMock.collection("suppliers").create({ suppliername: "S" }) + ).id; + await pbMock.collection("stock_items").create({ + id: "item-1", + sku: "STK-CD-115", + name: "115mm Cutting Disc", + }); + const purchase = await pbMock.collection("stock_purchases").create({ + supplier: supplierId, + status: "draft", + purchase_number: "PO26070101STK", + }); + const line = await pbMock.collection("stock_purchase_items").create({ + purchase: purchase.id, + stock_item: "item-1", + description: "115mm Cutting Disc", + quantity: 10, + }); + + const result = await removeQuickDraftLine(pbMock as never, line.id); + + expect(result).toEqual({ ok: true }); + const remaining = await pbMock.collection("stock_purchase_items").getFullList(); + expect(remaining).toEqual([]); + }); + + it("returns line_not_found when the line id doesn't exist", async () => { + const result = await removeQuickDraftLine(pbMock as never, "does-not-exist"); + expect(result.ok).toBe(false); + if (result.ok) return; + expect(result.reason).toBe("line_not_found"); + }); }); \ No newline at end of file diff --git a/src/lib/server/stock-quick-draft-service.ts b/src/lib/server/stock-quick-draft-service.ts index 1af42c2..dcc1780 100644 --- a/src/lib/server/stock-quick-draft-service.ts +++ b/src/lib/server/stock-quick-draft-service.ts @@ -437,4 +437,32 @@ export async function addQuickDraftLine( message: err instanceof Error ? err.message : "line create failed", }; } +} + +/* ============================================================================ + * removeQuickDraftLine + * ========================================================================== */ + +/** + * Deletes a `stock_purchase_items` row by id. Used by the modal's + * cards-region "Remove" button so the buyer can clean up mistakes + * without leaving the modal. + * + * Returns `{ ok: true }` on success, or `{ ok: false, reason }` on + * failure. The modal surfaces the message as a toast. + */ +export async function removeQuickDraftLine( + pb: StockQuickDraftPb, + lineId: string, +): Promise { + try { + await pb.collection(STOCK_PURCHASE_ITEMS).delete(lineId); + return { ok: true }; + } catch (err) { + return { + ok: false, + reason: "line_not_found", + message: err instanceof Error ? err.message : "line delete failed", + }; + } } \ No newline at end of file