// scripts/migrations/2026-07-15-add-stock-items-target-qty.ts // // One-shot schema migration: add a `target_qty` number field to the // `stock_items` collection. Used by the bulk-PO-from-low-stock flow // (see src/app/(app)/stock-orders/new/page.tsx) to compute the order // qty per line: `order_qty = max(0, target_qty - current_qty)`. Items // with `target_qty` unset or 0 are opted out of the bulk flow. // // Idempotent: re-running is a no-op when the field is already present. /* eslint-disable */ 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 doesn't exist — fall through; PB env vars may be // set in the shell. } } loadEnvFile(".env.local"); import { getAdminPocketBase } from "@/lib/server/pocketbase-admin"; const COLLECTION_NAME = "stock_items"; const FIELD_NAME = "target_qty"; async function main() { const pb = await getAdminPocketBase(); const collection = await pb.collections.getOne(COLLECTION_NAME); const existing = (collection.fields ?? []) as Array<{ name: string }>; if (existing.some((f) => f.name === FIELD_NAME)) { console.log(`[stock-items-target-qty] field already present on ${COLLECTION_NAME}`); return; } const newField = { name: FIELD_NAME, type: "number", required: false, options: { min: 0, noDecimal: false, }, }; await pb.collections.update(collection.id, { fields: [...existing, newField], }); console.log( `[stock-items-target-qty] created field on ${COLLECTION_NAME} (number, optional, min 0)`, ); } main().catch((err) => { console.error("[stock-items-target-qty] failed:", err); process.exit(1); });