125 lines
4.5 KiB
TypeScript
125 lines
4.5 KiB
TypeScript
import { NextRequest, NextResponse } from "next/server";
|
|
import { getDb } from "@/lib/db";
|
|
|
|
export async function GET(request: NextRequest) {
|
|
try {
|
|
const sql = getDb();
|
|
const { searchParams } = new URL(request.url);
|
|
const supplierId = searchParams.get("supplier_id");
|
|
const statusFilter = searchParams.get("status"); // "active" = draft,ordered,partially_received | "received" | null = all
|
|
|
|
const baseSelect = `SELECT sp.*, s.name AS supplier_name, s.code AS supplier_code,
|
|
(SELECT COUNT(*) FROM supplier_po_items WHERE supplier_po_id = sp.id) AS item_count,
|
|
(SELECT COALESCE(SUM(quantity * unit_price), 0) FROM supplier_po_items WHERE supplier_po_id = sp.id) AS total_value,
|
|
(SELECT COALESCE(SUM(received_quantity), 0) FROM supplier_po_items WHERE supplier_po_id = sp.id) AS total_received,
|
|
(SELECT COALESCE(SUM(quantity), 0) FROM supplier_po_items WHERE supplier_po_id = sp.id) AS total_ordered
|
|
FROM supplier_pos sp
|
|
JOIN suppliers s ON s.id = sp.supplier_id`;
|
|
|
|
const conditions: string[] = [];
|
|
const values: (string | number)[] = [];
|
|
let paramIdx = 1;
|
|
|
|
if (supplierId) {
|
|
conditions.push(`sp.supplier_id = $${paramIdx++}`);
|
|
values.push(Number(supplierId));
|
|
}
|
|
if (statusFilter === "active") {
|
|
conditions.push(`sp.status IN ('draft', 'ordered', 'partially_received')`);
|
|
} else if (statusFilter === "received") {
|
|
conditions.push(`sp.status IN ('received', 'cancelled')`);
|
|
}
|
|
|
|
const where = conditions.length > 0 ? ` WHERE ${conditions.join(" AND ")}` : "";
|
|
const rows = await sql(`${baseSelect}${where} ORDER BY sp.created_at DESC`, values);
|
|
|
|
return NextResponse.json(rows);
|
|
} catch (error) {
|
|
console.error("Supplier POs GET error:", error);
|
|
return NextResponse.json(
|
|
{ error: "Failed to fetch supplier POs" },
|
|
{ status: 500 }
|
|
);
|
|
}
|
|
}
|
|
|
|
export async function POST(request: NextRequest) {
|
|
try {
|
|
const sql = getDb();
|
|
const body = await request.json();
|
|
const { orders, planning_id } = body;
|
|
// orders: Array<{ supplier_id, supplier_name, items: Array<{ component_id, part_number, component_name, supplier_part_number, quantity, unit_price }> }>
|
|
|
|
if (!orders || !Array.isArray(orders) || orders.length === 0) {
|
|
return NextResponse.json({ error: "No orders provided" }, { status: 400 });
|
|
}
|
|
|
|
const createdPos: Record<string, unknown>[] = [];
|
|
|
|
for (const order of orders) {
|
|
// Generate PO number: PO-EACH-YYYY_MM_DD-RR-SUPPLIERNAME (matching packing list pattern)
|
|
const now = new Date();
|
|
const yyyy = now.getFullYear();
|
|
const mm = String(now.getMonth() + 1).padStart(2, "0");
|
|
const dd = String(now.getDate()).padStart(2, "0");
|
|
const supplierSlug = (order.supplier_name || "UNKNOWN")
|
|
.toUpperCase()
|
|
.replace(/[^A-Z0-9]/g, "")
|
|
.slice(0, 20);
|
|
const datePrefix = `PO-EACH-${yyyy}_${mm}_${dd}`;
|
|
const existingRows = await sql(
|
|
`SELECT COUNT(*) AS cnt FROM supplier_pos WHERE po_number LIKE $1`,
|
|
[`${datePrefix}%-${supplierSlug}`]
|
|
);
|
|
const revision = String(Number(existingRows[0].cnt) + 1).padStart(2, "0");
|
|
const poNumber = `${datePrefix}-${revision}-${supplierSlug}`;
|
|
|
|
const poRows = await sql(
|
|
`INSERT INTO supplier_pos (po_number, supplier_id, planning_id, status, notes)
|
|
VALUES ($1, $2, $3, 'draft', $4)
|
|
RETURNING *`,
|
|
[
|
|
poNumber,
|
|
Number(order.supplier_id),
|
|
planning_id ? Number(planning_id) : null,
|
|
order.notes || null,
|
|
]
|
|
);
|
|
|
|
const po = poRows[0];
|
|
|
|
for (const item of order.items) {
|
|
await sql(
|
|
`INSERT INTO supplier_po_items
|
|
(supplier_po_id, component_id, part_number, component_name,
|
|
supplier_part_number, quantity, unit_price)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7)`,
|
|
[
|
|
po.id,
|
|
Number(item.component_id),
|
|
item.part_number,
|
|
item.component_name,
|
|
item.supplier_part_number || null,
|
|
Number(item.quantity),
|
|
Number(item.unit_price),
|
|
]
|
|
);
|
|
}
|
|
|
|
createdPos.push({
|
|
...po,
|
|
supplier_name: order.supplier_name,
|
|
item_count: order.items.length,
|
|
});
|
|
}
|
|
|
|
return NextResponse.json(createdPos, { status: 201 });
|
|
} catch (error) {
|
|
console.error("Supplier POs POST error:", error);
|
|
return NextResponse.json(
|
|
{ error: error instanceof Error ? error.message : "Failed to create supplier POs" },
|
|
{ status: 500 }
|
|
);
|
|
}
|
|
}
|