diff --git a/src/app/api/v1/buyer-tasks/mark-ready/route.test.ts b/src/app/api/v1/buyer-tasks/mark-ready/route.test.ts new file mode 100644 index 0000000..f9fd48f --- /dev/null +++ b/src/app/api/v1/buyer-tasks/mark-ready/route.test.ts @@ -0,0 +1,74 @@ +import { describe, it, expect, beforeEach, vi } from "vitest"; + +vi.mock("@/lib/server/buyer-tasks-service", () => ({ + markGroupReady: vi.fn(), +})); + +import { POST } from "./route"; +import { markGroupReady } from "@/lib/server/buyer-tasks-service"; + +function makeRequest(body: unknown) { + return new Request("http://test/api/v1/buyer-tasks/mark-ready", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(body), + }); +} + +describe("POST /api/v1/buyer-tasks/mark-ready", () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + it("returns result on success", async () => { + vi.mocked(markGroupReady).mockResolvedValue({ + updated: 2, + failed: [], + }); + + const res = await POST( + makeRequest({ + orderId: "order-1", + supplierId: "sup-1", + items: [{ id: "item-1" }, { id: "item-2" }], + }) as never + ); + expect(res.status).toBe(200); + const body = await res.json(); + expect(body.updated).toBe(2); + expect(body.failed).toEqual([]); + }); + + it("returns 400 on missing orderId", async () => { + const res = await POST( + makeRequest({ supplierId: "sup-1", items: [{ id: "item-1" }] }) as never + ); + expect(res.status).toBe(400); + }); + + it("returns 400 on missing supplierId", async () => { + const res = await POST( + makeRequest({ orderId: "order-1", items: [{ id: "item-1" }] }) as never + ); + expect(res.status).toBe(400); + }); + + it("returns 400 on empty items", async () => { + const res = await POST( + makeRequest({ orderId: "order-1", supplierId: "sup-1", items: [] }) as never + ); + expect(res.status).toBe(400); + }); + + it("returns 500 on service error", async () => { + vi.mocked(markGroupReady).mockRejectedValue(new Error("PB down")); + const res = await POST( + makeRequest({ + orderId: "order-1", + supplierId: "sup-1", + items: [{ id: "item-1" }], + }) as never + ); + expect(res.status).toBe(500); + }); +}); diff --git a/src/app/api/v1/buyer-tasks/mark-ready/route.ts b/src/app/api/v1/buyer-tasks/mark-ready/route.ts new file mode 100644 index 0000000..0deda14 --- /dev/null +++ b/src/app/api/v1/buyer-tasks/mark-ready/route.ts @@ -0,0 +1,37 @@ +import { NextRequest, NextResponse } from "next/server"; +import { markGroupReady } from "@/lib/server/buyer-tasks-service"; + +type Body = { + orderId?: string; + supplierId?: string; + items?: Array<{ id: string }>; +}; + +export async function POST(req: NextRequest) { + let body: Body; + try { + body = (await req.json()) as Body; + } catch { + return NextResponse.json({ error: "Invalid JSON body" }, { status: 400 }); + } + + if (!body.orderId) { + return NextResponse.json({ error: "orderId is required" }, { status: 400 }); + } + if (!body.supplierId) { + return NextResponse.json({ error: "supplierId is required" }, { status: 400 }); + } + if (!body.items || body.items.length === 0) { + return NextResponse.json({ error: "items must be non-empty" }, { status: 400 }); + } + + try { + const result = await markGroupReady(body.orderId, body.supplierId, body.items); + return NextResponse.json(result); + } catch (err) { + return NextResponse.json( + { error: err instanceof Error ? err.message : "Failed to mark group ready" }, + { status: 500 } + ); + } +}