Repository Public
1// Vrai-Prix — méthode du coût : recherche d'articles (coûts unitaires) avec prix canonique courant.2import { NextRequest, NextResponse } from "next/server";3import { buildContext, loadItems, searchItems } from "@/lib/cost/catalog";4import { cached } from "@/lib/cost/cache";56export const runtime = "nodejs";78export function GET(req: NextRequest) {9 const q = (req.nextUrl.searchParams.get("q") ?? "").trim();10 const loc = req.nextUrl.searchParams.get("location") ?? "QC-MTL";11 const cat = req.nextUrl.searchParams.get("category");12 try {13 const ctx = cached(`ctx:${loc}`, 10 * 60_000, () => buildContext({ locationCode: loc }));14 let items = q.length >= 2 ? searchItems(q, 40) : [...loadItems().values()];15 if (cat) items = items.filter((i) => i.category === cat);16 const out = items.slice(0, 200).map((i) => {17 const p = ctx.prices.get(i.code) ?? null;18 return { code: i.code, nameFr: i.nameFr, nameEn: i.nameEn, unit: i.unit, category: i.category, masterformat: i.masterformat, division: i.division, trade: i.trade,19 price: p ? Math.round(p.price * 100) / 100 : null, low: p ? Math.round(p.low * 100) / 100 : null, high: p ? Math.round(p.high * 100) / 100 : null, kind: p?.kind ?? null, sourceCount: p?.sourceCount ?? 0, observedAt: p?.observedAt ?? null, confidence: p?.confidence ?? null, note: p?.note ?? null, sources: p?.sources ?? [] };20 });21 return NextResponse.json({ asOf: ctx.asOf, location: ctx.location.code, count: out.length, items: out });22 } catch (e) {23 return NextResponse.json({ error: (e as Error).message }, { status: 500 });24 }25}26