Files
website-secure/app/api/customers/[id]/stats/route.ts
T
pm 9c14a19a87
DevSecOps Enterprise Pipeline / security-gate-and-deploy (push) Failing after 41s
chore: upload parte 1 - logica
2026-06-01 15:35:53 +01:00

85 lines
3.1 KiB
TypeScript

import { NextRequest, NextResponse } from "next/server";
import { getDb } from "@/lib/db";
export async function GET(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) {
try {
const sql = getDb();
const { id } = await params;
const { searchParams } = new URL(request.url);
const period = searchParams.get("period") || "month"; // week | month | year
// --- On Order by product (not completed/cancelled) ---
const onOrder = await sql(
`SELECT p.id AS product_id, p.name AS product_name, p.sku,
SUM(poi.quantity) AS total_ordered,
SUM(COALESCE(poi.shipped_quantity, 0)) AS total_shipped,
SUM(poi.quantity - COALESCE(poi.shipped_quantity, 0)) AS on_order
FROM purchase_order_items poi
JOIN purchase_orders po ON po.id = poi.purchase_order_id
JOIN products p ON p.id = poi.product_id
WHERE po.customer_id = $1
AND po.status NOT IN ('completed', 'cancelled')
AND poi.quantity > COALESCE(poi.shipped_quantity, 0)
GROUP BY p.id, p.name, p.sku
ORDER BY on_order DESC`,
[Number(id)]
);
// --- Produced/shipped by product over time ---
let dateFilter = "";
if (period === "week") {
dateFilter = "AND pl.created_at >= NOW() - INTERVAL '7 days'";
} else if (period === "month") {
dateFilter = "AND pl.created_at >= NOW() - INTERVAL '30 days'";
} else if (period === "year") {
dateFilter = "AND pl.created_at >= NOW() - INTERVAL '365 days'";
}
// Aggregate shipped quantities by product (from packing lists)
const produced = await sql(
`SELECT p.id AS product_id, p.name AS product_name, p.sku,
SUM(pl.quantity) AS total_produced
FROM packing_lists pl
JOIN purchase_orders po ON po.id = pl.purchase_order_id
JOIN purchase_order_items poi ON poi.id = pl.po_item_id
JOIN products p ON p.id = poi.product_id
WHERE po.customer_id = $1
${dateFilter}
GROUP BY p.id, p.name, p.sku
ORDER BY total_produced DESC`,
[Number(id)]
);
// Produced over time bucketed by date for chart
let dateTrunc = "day";
if (period === "year") dateTrunc = "month";
const producedTimeline = await sql(
`SELECT DATE_TRUNC('${dateTrunc}', pl.created_at) AS bucket,
p.name AS product_name,
p.sku,
SUM(pl.quantity) AS quantity
FROM packing_lists pl
JOIN purchase_orders po ON po.id = pl.purchase_order_id
JOIN purchase_order_items poi ON poi.id = pl.po_item_id
JOIN products p ON p.id = poi.product_id
WHERE po.customer_id = $1
${dateFilter}
GROUP BY bucket, p.id, p.name, p.sku
ORDER BY bucket ASC`,
[Number(id)]
);
return NextResponse.json({ onOrder, produced, producedTimeline });
} catch (error) {
console.error("[v0] Customer stats GET error:", error);
return NextResponse.json(
{ error: error instanceof Error ? error.message : "Failed to fetch customer stats" },
{ status: 500 }
);
}
}