/* eslint-disable */ // scripts/migrations/2026-07-15-stock-purchase-line-state.ts // // One-shot schema migration for the v2 stock-order driver flow: // // 1. `stock_purchases` — add a `documents` file field for the // generated PO PDF (and any other attachments the operator // wants to send to the supplier). // 2. `stock_purchase_items` — add a `status` select field for the // per-line state machine // (collection_pool | assigned_to_driver | collected | booked) // and an `assigned_at` date field for the driver-assignment // timestamp. // // Idempotent: re-running is a no-op when the fields are already // present. import { readFileSync } from "node:fs"; import { resolve } from "node:path"; function loadEnvFile(name: string) { try { const raw = readFileSync(resolve(process.cwd(), name), "utf8"); for (const line of raw.split("\n")) { const trimmed = line.trim(); if (!trimmed || trimmed.startsWith("#")) continue; const m = trimmed.match(/^([A-Z0-9_]+)\s*=\s*(.+)$/i); if (m && !process.env[m[1]]) { process.env[m[1]] = m[2].replace(/^["']|["']$/g, "").trim(); } } } catch { // .env.local may not exist; fall through. } } loadEnvFile(".env.local"); import { getAdminPocketBase } from "@/lib/server/pocketbase-admin"; const STOCK_PURCHASES = "stock_purchases"; const STOCK_PURCHASE_ITEMS = "stock_purchase_items"; const LINE_STATUS_VALUES = [ "collection_pool", "assigned_to_driver", "collected", "booked", ]; async function main() { const pb = await getAdminPocketBase(); // ── 1. stock_purchases.documents ────────────────────────────── { const col = await pb.collections.getOne(STOCK_PURCHASES); const fields = (col.fields ?? []) as Array<{ name: string }>; if (fields.some((f) => f.name === "documents")) { console.log(`[stock-purchase-line-state] stock_purchases.documents already present`); } else { const newField = { name: "documents", type: "file", required: false, presentable: false, protected: false, maxSelect: 5, // mirror the customer PO: up to 5 attachments maxSize: 0, // no PB cap mimeTypes: null, thumbs: null, }; await pb.collections.update(col.id, { fields: [...fields, newField] }); console.log( `[stock-purchase-line-state] added documents (file, multi, any mime) to stock_purchases`, ); } } // ── 2. stock_purchase_items.status + assigned_at ───────────── { const col = await pb.collections.getOne(STOCK_PURCHASE_ITEMS); const fields = (col.fields ?? []) as Array<{ name: string }>; let next = fields; let added = false; if (!fields.some((f) => f.name === "status")) { // Append at the end so existing reads / field indexes aren't // disturbed. Select field with the 4 state values. next = [ ...next, { name: "status", type: "select", required: false, maxSelect: 1, values: LINE_STATUS_VALUES, }, ]; added = true; } if (!fields.some((f) => f.name === "assigned_at")) { // Mirrors `order_items.assigned_at` — the timestamp the line // was bound to a driver. `null` = unassigned. We don't make it // required because lines that haven't been sent yet (status // null) have no assignment. next = [ ...next, { name: "assigned_at", type: "date", required: false, presentable: false, }, ]; added = true; } if (added) { await pb.collections.update(col.id, { fields: next }); console.log( `[stock-purchase-line-state] added status (select) + assigned_at (date) to stock_purchase_items`, ); } else { console.log( `[stock-purchase-line-state] stock_purchase_items.status + assigned_at already present`, ); } } console.log( `[stock-purchase-line-state] done. Verify via PB admin or by running the existing service tests.`, ); } main().catch((err) => { console.error("[stock-purchase-line-state] failed:", err); process.exit(1); });