feat(buyer-tasks): POST generate-po route

Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
SJCoetz 2026-07-29 20:03:26 +02:00
parent 275a47e28f
commit 4f0be21732
2 changed files with 54 additions and 0 deletions

View file

@ -0,0 +1,13 @@
import { describe, it, expect, beforeEach, vi } from "vitest";
vi.mock("@/lib/server/buyer-tasks-service", () => ({ generatePoForGroup: vi.fn(), }));
import { POST } from "./route";
import { generatePoForGroup } from "@/lib/server/buyer-tasks-service";
function makeRequest(body: unknown) { return new Request("http://test/api/v1/buyer-tasks/generate-po", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body), }); }
describe("POST /api/v1/buyer-tasks/generate-po", () => {
beforeEach(() => { vi.clearAllMocks(); });
it("creates PO and returns id", async () => { vi.mocked(generatePoForGroup).mockResolvedValue("po-new"); const res = await POST(makeRequest({ orderId: "order-1", supplierId: "sup-1", items: [{ id: "item-1", costPrice: 25, quantity: 2 }] }) as never); expect(res.status).toBe(200); const body = await res.json(); expect(body.purchaseOrderId).toBe("po-new"); });
it("returns 400 on missing orderId", async () => { const res = await POST(makeRequest({ supplierId: "sup-1", items: [] }) as never); expect(res.status).toBe(400); });
it("returns 400 on missing supplierId", async () => { const res = await POST(makeRequest({ orderId: "order-1", items: [] }) 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(generatePoForGroup).mockRejectedValue(new Error("PB down")); const res = await POST(makeRequest({ orderId: "order-1", supplierId: "sup-1", items: [{ id: "item-1", costPrice: 25, quantity: 1 }] }) as never); expect(res.status).toBe(500); });
});

View file

@ -0,0 +1,41 @@
import { NextRequest, NextResponse } from "next/server";
import { generatePoForGroup } from "@/lib/server/buyer-tasks-service";
type Body = {
orderId?: string;
supplierId?: string;
items?: Array<{ id: string; costPrice: number; quantity: number }>;
};
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 purchaseOrderId = await generatePoForGroup(
body.orderId,
body.supplierId,
body.items
);
return NextResponse.json({ purchaseOrderId });
} catch (err) {
return NextResponse.json(
{ error: err instanceof Error ? err.message : "Failed to generate PO" },
{ status: 500 }
);
}
}