feat(stock): add POST /api/v1/stock/items/set-pricing

This commit is contained in:
Dave 2026-08-31 16:54:03 +02:00
parent ab639eea6d
commit 6f8c6da0fe

View file

@ -0,0 +1,78 @@
import { NextResponse } from "next/server";
import { updateStockItemsPricing } from "@/lib/server/stock-pricing-service";
import { getAdminPocketBase } from "@/lib/server/pocketbase-admin";
const MAX_UPDATES = 100;
const PB_ID_RE = /^[a-z0-9]{15}$/;
type Body = {
updates?: Array<{ id?: unknown; costPrice?: unknown; sellingPrice?: unknown; markup?: unknown }>;
actor?: { id?: unknown; name?: unknown };
};
export async function POST(req: Request) {
let body: Body;
try {
body = (await req.json()) as Body;
} catch {
return NextResponse.json(
{ code: "invalid_json", message: "Body is not valid JSON" },
{ status: 400 },
);
}
if (!Array.isArray(body.updates) || body.updates.length === 0) {
return NextResponse.json(
{ code: "validation_error", message: "updates must be a non-empty array" },
{ status: 400 },
);
}
if (body.updates.length > MAX_UPDATES) {
return NextResponse.json(
{
code: "validation_error",
message: `At most ${MAX_UPDATES} updates per call`,
},
{ status: 400 },
);
}
if (!body.actor || typeof body.actor.id !== "string" || !body.actor.id) {
return NextResponse.json(
{ code: "validation_error", message: "actor.id is required" },
{ status: 400 },
);
}
const updates = body.updates.map((u, i) => {
if (typeof u.id !== "string" || !PB_ID_RE.test(u.id)) {
throw new Error(`updates[${i}].id must be a 15-char PB id`);
}
const out: { id: string; costPrice?: number; sellingPrice?: number; markup?: number } = {
id: u.id,
};
if (u.costPrice !== undefined) out.costPrice = Number(u.costPrice);
if (u.sellingPrice !== undefined) out.sellingPrice = Number(u.sellingPrice);
if (u.markup !== undefined) out.markup = Number(u.markup);
return out;
});
let pb;
try {
pb = await getAdminPocketBase();
} catch (err) {
const message = err instanceof Error ? err.message : String(err);
return NextResponse.json(
{ code: "pb_error", message },
{ status: 500 },
);
}
const result = await updateStockItemsPricing({
pb,
updates,
actor: { id: body.actor.id, name: String(body.actor.name ?? body.actor.id) },
});
return NextResponse.json(result, { status: 200 });
}