import Link from "next/link"; import { getPb } from "../lib/pb"; export const dynamic = "force-dynamic"; export default async function StockCodesPage({ searchParams, }: { searchParams: { q?: string }; }) { const pb = getPb(); const q = (searchParams.q || "").trim(); // Fetch all stock codes let codes: any[] = []; try { // Don't pass filter when empty — SDK serializes `undefined` as literal "undefined" const opts: any = { sort: "code", perPage: 500 }; if (q) opts.filter = `code~"${q.replace(/"/g, '\\"')}" || description_goods~"${q.replace(/"/g, '\\"')}"`; const r = await pb.collection("JEI_stock_codes").getList(1, 500, opts); codes = r.items; } catch (e: any) { return (

Stock Codes

Cannot reach PocketBase: {String(e?.message || e)}
); } // Fetch all invoice lines once, aggregate per stock code let linesByStock: Record = {}; try { const lr = await pb.collection("JEI_invoice_lines").getList(1, 5000); for (const line of lr.items) { const sc = line.stock_code; if (!linesByStock[sc]) linesByStock[sc] = { qty: 0, value: 0, count: 0 }; linesByStock[sc].qty += line.quantity || 0; linesByStock[sc].value += line.net_amount || 0; linesByStock[sc].count += 1; } } catch (e) { // Lines unavailable — show codes without totals } return (

Stock Codes

{codes.length} code(s)
{q && ( Clear )}
{codes.length === 0 && ( )} {codes.map((c) => { const s = linesByStock[c.id] || { qty: 0, value: 0, count: 0 }; return ( ); })}
Code Description Total Qty Total (£) Lines
No stock codes yet. Run python scripts/import_to_pb.py to import.
{c.code} {c.description_goods} {s.qty.toFixed(0)} £{s.value.toFixed(2)} {s.count}
); }