Repository Public
1// Vrai-Prix — admin méthode du coût : correspondances produit ↔ article (liste, création manuelle).2import { NextRequest, NextResponse } from "next/server";3import { adminAuth } from "@/lib/cost/connectors/admin";4import { getCostDb, sourceIdByKey } from "@/lib/cost/db";5import { reviewMapping } from "@/lib/cost/connectors/matching";6import { isRunnable } from "@/lib/cost/connectors/registry";78export const runtime = "nodejs";910export function GET(req: NextRequest) {11 const denied = adminAuth(req);12 if (denied) return denied;13 const status = req.nextUrl.searchParams.get("status");14 const rows = getCostDb().prepare(`SELECT m.id, s.key source, m.product_url url, m.product_title title, m.proposed_item_code itemCode, m.pack_qty packQty, m.pack_unit packUnit, m.method, m.confidence, m.rationale, m.status, m.reviewed_at reviewedAt, m.created_at createdAt15 FROM product_mappings m JOIN cost_sources s ON s.id=m.source_id ${status ? "WHERE m.status=?" : ""} ORDER BY m.created_at DESC LIMIT 500`).all(...(status ? [status] : []));16 return NextResponse.json({ mappings: rows });17}1819/** Création/approbation manuelle : { source, itemCode, url, title?, packQty?, packUnit? } */20export async function POST(req: NextRequest) {21 const denied = adminAuth(req);22 if (denied) return denied;23 let b: { source?: string; itemCode?: string; url?: string; title?: string; packQty?: number; packUnit?: string };24 try { b = await req.json(); } catch { return NextResponse.json({ error: "JSON invalide" }, { status: 400 }); }25 if (!b.source || !isRunnable(b.source) || !b.itemCode || !b.url) return NextResponse.json({ error: "source, itemCode et url requis" }, { status: 400 });26 const d = getCostDb();27 const item = d.prepare("SELECT id FROM cost_items WHERE canonical_code=?").get(b.itemCode) as { id: number } | undefined;28 if (!item) return NextResponse.json({ error: "article inconnu" }, { status: 404 });29 const sid = sourceIdByKey(b.source, d);30 d.prepare(`INSERT INTO product_mappings(source_id,product_url,product_title,proposed_item_code,pack_qty,pack_unit,method,confidence,rationale,status) VALUES(?,?,?,?,?,?,'manual',1,'saisie administrateur','pending')31 ON CONFLICT(source_id,product_url) DO UPDATE SET proposed_item_code=excluded.proposed_item_code, pack_qty=excluded.pack_qty, pack_unit=excluded.pack_unit, method='manual', confidence=1`).run(sid, b.url, b.title ?? null, b.itemCode, b.packQty ?? null, b.packUnit ?? null);32 const id = (d.prepare("SELECT id FROM product_mappings WHERE source_id=? AND product_url=?").get(sid, b.url) as { id: number }).id;33 reviewMapping(id, "approved", d);34 return NextResponse.json({ ok: true, id });35}36