WFDASH-WEBAPP/scripts/migrations/2026-07-06-order-items-assigned-at.ts
SJCoetz 7f924ccc45 refactor: switch hardcoded UI colors to semantic theme tokens
Overhaul the app's color system by replacing all hardcoded Tailwind color classes with semantic theme variables to ensure consistent theming across all components, pages, and tests.

Additional changes:
- Add assigned date support for order item status updates: add `assignedDate` field to the order item status PATCH API, implement server-side normalization/validation, and add corresponding tests
- Refactor purchase order PDF workflows to use the consolidated `purchase_orders.documents` field instead of the legacy separate `purchase_order_pdfs` collection
- Fix quote number parsing and formatting to support both dashed (Q-YYYY-MM-NNN) and dashless (QYYYYMMNNN) formats
- Rename `driver_pool` item status to `collection_pool` across the codebase
- Add null handling for order item quantities and pricing to display "—" for missing values
- Improve filter tab styling: make mobile tabs scrollable, prevent text wrapping, hide scrollbar
- Add new utility scripts, API routes, migrations, and polish small UI/UX fixes including tsconfig updates and theme hook improvements
2026-07-07 17:22:03 +02:00

106 lines
3.5 KiB
TypeScript

/**
* Migration — add `assigned_at` text field to `order_items`.
*
* Why:
* The assignment flow (operator picks a driver for a non-in-stock
* order item) needs a server-side timestamp that other surfaces —
* the driver app, the order detail page, future reporting — can
* sort and filter on without trusting `updated`. We already have
* `drv_id` (relation) and `drv_status` on the row; adding a
* dedicated `assigned_at` keeps the data model honest.
*
* `item_status` and `drv_status` already cover the boolean-ish
* state ("is this assigned right now"). `assigned_at` is the
* "when did the most recent assignment happen" timestamp — needed
* for downstream reports (per-driver collection velocity, SLA
* monitoring) and for re-assignment history if we add a log table
* later.
*
* Per-line status lifecycle stays on `item_status` (the existing
* enum: po_generated → assigned → collected). This field is pure
* metadata. Do not use it to derive "is this assigned" — check
* `item_status === "assigned"` for that.
*
* Idempotent — skips if `assigned_at` already exists.
*
* Run with:
* npx tsx scripts/migrations/2026-07-06-order-items-assigned-at.ts
*/
/* eslint-disable */
import PocketBase from "pocketbase";
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 {
/* fine — rely on shell env */
}
}
loadEnvFile(".env");
loadEnvFile(".env.local");
async function main() {
const url = process.env.NEXT_PUBLIC_POCKETBASE_URL;
const email = process.env.PB_ADMIN_EMAIL;
const password = process.env.PB_ADMIN_PASSWORD;
if (!url || !email || !password) {
throw new Error(
"Set NEXT_PUBLIC_POCKETBASE_URL, PB_ADMIN_EMAIL, PB_ADMIN_PASSWORD (e.g. sourced from .env.local).",
);
}
const pb = new PocketBase(url);
await pb.collection("_superusers").authWithPassword(email, password);
console.log(`[order-items-assigned-at] Authenticated against ${url}`);
const col = await pb.collections.getOne("order_items");
const fields = (col.fields as Array<{
name: string;
type: string;
required?: boolean;
options?: Record<string, unknown>;
}>).slice();
if (fields.some((f) => f.name === "assigned_at")) {
console.log(
"[order-items-assigned-at] assigned_at already exists — skip",
);
console.log("[order-items-assigned-at] Migration complete (no-op).");
return;
}
fields.push({
name: "assigned_at",
type: "date",
required: false,
options: {},
});
await pb.collections.update(col.id, { fields });
console.log(
"[order-items-assigned-at] added `assigned_at` (date, optional) to order_items",
);
const fresh = await pb.collections.getOne("order_items");
const verify = (fresh.fields as Array<{ name: string; type: string }>)
.filter((f) => f.name === "assigned_at")
.map((f) => `${f.name}:${f.type}`)
.join(", ");
console.log(`[order-items-assigned-at] Post-update → ${verify}`);
console.log("[order-items-assigned-at] Migration complete.");
}
main().catch((err) => {
console.error("[order-items-assigned-at] Migration failed:", err);
process.exit(1);
});