mega-plant/scripts/backfill-suppliers.mjs
David cfd54385b3 Add Suppliers list; book purchase orders and petty-cash slips against it
- /expenses/suppliers: terms (cash / 30 / 60 days), PO + petty cash totals per supplier,
  period filters, add/edit/delete, due dates
- POs and slips resolve to a supplier by code then folded name; new PO suppliers start
  with terms unset, new slip suppliers as cash
- Full-user guard on cash-float and job-card write routes

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 15:43:57 +02:00

39 lines
2.1 KiB
JavaScript

// Book every existing purchase order and cash-float slip against a supplier (idempotent).
// New suppliers from POs start with terms unset; ones from slips start as "cash".
// Usage: node scripts/backfill-suppliers.mjs
import PocketBase from "pocketbase";
import { readFileSync } from "node:fs";
import { supplierKey } from "../lib/supplier.ts";
for (const l of readFileSync(new URL("../.env.local", import.meta.url), "utf8").split("\n")) {
const i = l.indexOf("="); if (i > 0 && !l.trim().startsWith("#")) process.env[l.slice(0, i).trim()] = l.slice(i + 1).trim();
}
const pb = new PocketBase(process.env.NEXT_PUBLIC_PB_URL);
pb.autoCancellation(false);
await pb.collection("_superusers").authWithPassword(process.env.PB_ADMIN, process.env.PB_PASS);
const list = await pb.collection("suppliers").getFullList();
const byKey = new Map(list.map((s) => [s.key, s]));
const byCode = new Map(list.filter((s) => s.code).map((s) => [s.code.toUpperCase(), s]));
async function ensure(name, code, terms, source) {
const key = supplierKey(name);
if (!key) return null;
let s = (code && byCode.get(code.toUpperCase())) || byKey.get(key);
if (!s) {
s = await pb.collection("suppliers").create({ name: name.trim(), key, code: (code || "").toUpperCase(), terms, source });
byKey.set(key, s); if (code) byCode.set(code.toUpperCase(), s);
console.log(` + ${name.trim()} (${source}${terms ? `, ${terms}` : ", terms not set"})`);
}
return s;
}
let linked = 0;
for (const p of await pb.collection("purchases").getFullList()) {
if (p.supplier_ref) continue;
const s = await ensure(p.supplier || "", p.supplier_code || "", "", "Purchase order");
if (s) { await pb.collection("purchases").update(p.id, { supplier_ref: s.id }); linked++; }
}
for (const e of await pb.collection("cash_float_entries").getFullList({ filter: 'kind = "expense"' })) {
if (e.supplier_ref || !e.supplier) continue;
const s = await ensure(e.supplier, "", "cash", "Cash float");
if (s) { await pb.collection("cash_float_entries").update(e.id, { supplier_ref: s.id }); linked++; }
}
console.log(`✓ ${linked} record(s) booked against a supplier; ${byKey.size} supplier(s) in the list`);