Two things that meant going into PocketBase by hand or jumping between screens. Deleting a quote - Quotes had no delete action - a test quote could only be removed through the PocketBase admin UI. Purchase orders already soft delete by flipping a `deleted` flag, so quotes now do the same: the Delete action confirms first, then hides the quote from the list while the record and its PDF stay in PocketBase for audit. - The quotes list filters out soft-deleted quotes, so a deleted quote is out of the way but recoverable by clearing the flag. Adding a customer while writing a quote - Typing a customer name that was not in the list used to create a name-only stub, which then had to be edited from the Customers screen before the quote could show an address or VAT number. - The picker now opens the full customer form right there - address, VAT number, email and phone - with the name pre-filled. The new customer is created, added to the list and selected, so the quote carries on and the PDF has the details.
58 lines
1.8 KiB
JavaScript
58 lines
1.8 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Add the `deleted` flag to the `quotes` collection.
|
|
*
|
|
* Purchase orders already soft delete this way - the record and its PDF
|
|
* stay in PocketBase for audit, but the list hides it. Quotes had no
|
|
* such flag, so a test quote could only be removed through the
|
|
* PocketBase admin UI by hand.
|
|
*
|
|
* Usage:
|
|
* node scripts/add-quote-deleted-flag.mjs # dry run (default)
|
|
* node scripts/add-quote-deleted-flag.mjs --apply # apply to the instance
|
|
*/
|
|
|
|
import PocketBase from "pocketbase";
|
|
|
|
const PB_URL = process.env.POCKETBASE_URL || "https://pb.jeistk.apphub.co.za";
|
|
const PB_EMAIL = process.env.POCKETBASE_ADMIN_EMAIL || "david@wfsales.co.za";
|
|
const PB_PASSWORD = process.env.POCKETBASE_ADMIN_PASSWORD || "1234567890";
|
|
|
|
const APPLY = process.argv.includes("--apply");
|
|
|
|
const pb = new PocketBase(PB_URL);
|
|
pb.autoCancellation(false);
|
|
|
|
await pb.admins.authWithPassword(PB_EMAIL, PB_PASSWORD);
|
|
|
|
const collection = await pb.collections.getOne("quotes");
|
|
|
|
const hasField = collection.fields.some((f) => f.name === "deleted");
|
|
|
|
console.log("=== BEFORE ===");
|
|
console.log(` fields: ${collection.fields.map((f) => f.name).join(", ")}`);
|
|
console.log(` deleted flag: ${hasField ? "already present" : "MISSING - will be added"}`);
|
|
|
|
if (!APPLY) {
|
|
console.log("\nDry run. Re-run with --apply to write the field to the instance.");
|
|
process.exit(0);
|
|
}
|
|
|
|
if (!hasField) {
|
|
collection.fields.push({
|
|
hidden: false,
|
|
id: "bool_quote_deleted",
|
|
name: "deleted",
|
|
presentable: false,
|
|
required: false,
|
|
system: false,
|
|
type: "bool",
|
|
});
|
|
|
|
const updated = await pb.collections.update(collection.id, collection);
|
|
|
|
console.log("\n=== AFTER ===");
|
|
console.log(` fields: ${updated.fields.map((f) => f.name).join(", ")}`);
|
|
}
|
|
|
|
console.log("\nDone. Existing quotes keep deleted = false - nothing disappears.");
|