WFDASH-WEBAPP/scripts/migrations/2026-06-26-add-orders-rep.ts
SJCoetz 6c07a91693 refactor: drop order-level status, shift to item-driven workflow
This commit overhauls the order management system to use item-level status tracking instead of a single order-level status:
- Remove deprecated `orders.status` field and add `invoiced` and quote match audit fields
- Add `isOrderComplete` utility with tests to validate fully delivered orders
- Add purchase order PDF rendering support and tooling
- Add geo coordinate fields for companies/customers with map link UI
- Add REST management APIs for customers, companies, and suppliers
- Update customer/company services to use relation fields instead of free text
- Add status pill and tab filter components for item status visualization
- Add quote-to-order matching logic and unit tests
- Update all pages, components, and tests to match the new schema
- Include all required PocketBase migrations and schema updates
2026-06-29 13:06:01 +02:00

75 lines
No EOL
2.4 KiB
TypeScript

/**
* One-shot migration: add `rep` (text, optional) to the `orders` collection.
*
* Run with:
*
* npx tsx scripts/migrations/2026-06-26-add-orders-rep.ts
*
* What this does (idempotent — safe to re-run):
*
* 1. Reads the `orders` collection schema.
* 2. If a `rep` text field already exists, prints "already present" and exits.
* 3. Otherwise appends a new text field named `rep` (no max length,
* not required, default empty string) and PATCHes the collection.
*
* The field is intentionally free-text (not a relation) to keep it loose:
* reps can be referenced by name from the customer's `rep` field, or typed
* ad-hoc on company-only orders where no customer record exists. PB will
* accept null/empty values on existing rows.
*
* Rollback: delete the `rep` field from the orders collection in the PB
* admin UI. No data is lost because no rows have it yet.
*/
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;
async function main() {
if (!ADMIN_EMAIL || !ADMIN_PASSWORD) {
throw new Error(
"Set PB_ADMIN_EMAIL and PB_ADMIN_PASSWORD env vars (e.g. sourced from .env.local)."
);
}
const pb = new PocketBase(PB_URL);
await pb.collection("_superusers").authWithPassword(ADMIN_EMAIL, ADMIN_PASSWORD);
console.log(`[orders-rep] Authenticated against ${PB_URL}`);
const orders = await pb.collections.getOne("orders");
const hasRep = orders.fields.some(
(f: { name: string }) => f.name === "rep"
);
if (hasRep) {
console.log("[orders-rep] orders.rep already exists — skipping.");
return;
}
await pb.collections.update(orders.id, {
fields: [
...orders.fields,
{
name: "rep",
type: "text",
required: false,
presentable: false,
// No max length — operator can type a full name or rep id.
// PB text fields without `max` accept long values; we don't
// need to constrain it for this field.
max: 0,
min: 0,
pattern: "",
autogeneratePattern: "",
},
],
});
console.log("[orders-rep] Added orders.rep (text, optional). Migration complete.");
}
main().catch((err) => {
console.error("[orders-rep] Migration failed:", err);
process.exit(1);
});