WFDASH-WEBAPP/scripts/migrations/2026-06-30-add-price-list-source-file.ts

64 lines
1.9 KiB
TypeScript
Raw Normal View History

/**
* Migration — add `source_file` (text) to `price_list`.
*
* Stores the `raw_price_list.id` that an extracted line item came
* from. Used by the n8n workflow's verification step:
*
* // After the POST loop
* const actual = await pb.collection('price_list').getList(1, expected, {
* filter: `source_file = "${rawId}"`,
* });
* if (actual.items.length === expected) {
* // safe to PATCH raw_price_list.status = "Completed"
* } else {
* // PATCH Failed with "X/Y items created"
* }
*
* Also useful for the agent at quote time: "give me the full price
* list for the file this row was sourced from."
*
* Idempotent: re-runs are safe.
*
* Run with:
* npm run pb:migrate:price-list-source-file
*/
import PocketBase from "pocketbase";
const PB_URL = process.env.NEXT_PUBLIC_POCKETBASE_URL || "http://127.0.0.1:8090";
const ADMIN_EMAIL = process.env.PB_ADMIN_EMAIL;
const ADMIN_PASSWORD = process.env.PB_ADMIN_PASSWORD;
if (!ADMIN_EMAIL || !ADMIN_PASSWORD) {
throw new Error("PB_ADMIN_EMAIL and PB_ADMIN_PASSWORD are required.");
}
async function main() {
const pb = new PocketBase(PB_URL);
await pb.collection("_superusers").authWithPassword(ADMIN_EMAIL, ADMIN_PASSWORD);
const cols = await pb.collections.getFullList();
const priceList = cols.find((c) => c.name === "price_list");
if (!priceList) {
throw new Error("price_list collection not found. Run the setup script first.");
}
if (priceList.fields.some((f) => f.name === "source_file")) {
console.log("price_list.source_file already exists, skipping.");
return;
}
await pb.collections.update(priceList.id, {
fields: [
...priceList.fields,
{ name: "source_file", type: "text", required: false, options: { max: 0 } },
],
});
console.log("Added price_list.source_file");
console.log("source_file migration complete.");
}
main().catch((err) => {
console.error(err);
process.exit(1);
});