53 lines
2.9 KiB
JavaScript
53 lines
2.9 KiB
JavaScript
|
|
// Create the `suppliers` collection and link purchase orders + cash-float slips to it (idempotent).
|
||
|
|
//
|
||
|
|
// One supplier list for the whole business. Every purchase order and every petty-cash slip is
|
||
|
|
// booked against a supplier, so "how much did we spend at X" is one query.
|
||
|
|
//
|
||
|
|
// terms "cash" paid on the spot (petty cash)
|
||
|
|
// "30" account, payable in 30 days
|
||
|
|
// "60" account, payable in 60 days
|
||
|
|
// "" not set yet — a supplier that appeared on a PO before anyone classified it
|
||
|
|
//
|
||
|
|
// `key` is the supplier's name folded (case, punctuation, PTY/LTD/CC removed) and is UNIQUE, so
|
||
|
|
// "Lube Force Traders cc" and "LUBE FORCE TRADERS" cannot become two suppliers.
|
||
|
|
//
|
||
|
|
// Usage: node scripts/setup-suppliers-collection.mjs
|
||
|
|
import PocketBase from "pocketbase";
|
||
|
|
import { readFileSync } from "node:fs";
|
||
|
|
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 ref = await pb.collections.getOne("monthly_income");
|
||
|
|
const rules = {
|
||
|
|
listRule: ref.listRule ?? "", viewRule: ref.viewRule ?? "",
|
||
|
|
createRule: ref.createRule ?? "", updateRule: ref.updateRule ?? "", deleteRule: ref.deleteRule ?? "",
|
||
|
|
};
|
||
|
|
const fields = [
|
||
|
|
{ name: "name", type: "text", required: true },
|
||
|
|
{ name: "key", type: "text", required: true },
|
||
|
|
{ name: "code", type: "text" },
|
||
|
|
{ name: "terms", type: "text" },
|
||
|
|
{ name: "notes", type: "text" },
|
||
|
|
{ name: "source", type: "text" },
|
||
|
|
];
|
||
|
|
const indexes = ["CREATE UNIQUE INDEX idx_suppliers_key ON suppliers (key)"];
|
||
|
|
|
||
|
|
let suppliers = (await pb.collections.getFullList({ filter: 'name = "suppliers"', perPage: 1 }))[0];
|
||
|
|
if (!suppliers) {
|
||
|
|
suppliers = await pb.send("/api/collections", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ name: "suppliers", type: "base", fields, indexes, ...rules }) });
|
||
|
|
console.log(` ✓ created suppliers (${suppliers.id})`);
|
||
|
|
} else console.log(" · suppliers already present");
|
||
|
|
|
||
|
|
for (const target of ["purchases", "cash_float_entries"]) {
|
||
|
|
const c = await pb.collections.getOne(target).catch(() => null);
|
||
|
|
if (!c) { console.log(` ! ${target} missing — skipped`); continue; }
|
||
|
|
if (c.fields.some((f) => f.name === "supplier_ref")) { console.log(` · ${target}.supplier_ref already present`); continue; }
|
||
|
|
await pb.send(`/api/collections/${target}`, { method: "PATCH", headers: { "Content-Type": "application/json" },
|
||
|
|
body: JSON.stringify({ fields: [...c.fields, { name: "supplier_ref", type: "relation", collectionId: suppliers.id, minSelect: 0, maxSelect: 1, cascadeDelete: false }] }) });
|
||
|
|
console.log(` ✓ added ${target}.supplier_ref`);
|
||
|
|
}
|