From d5ed390de47d839250a7ff5888c5388effd8ddcd Mon Sep 17 00:00:00 2001 From: SJCoetz Date: Thu, 6 Aug 2026 23:32:12 +0200 Subject: [PATCH] feat(pb): add stock_purchases.additional_attachments file field (migration) Co-authored-by: Orca --- ...-stock-purchases-additional-attachments.ts | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 scripts/migrations/2026-08-06-stock-purchases-additional-attachments.ts diff --git a/scripts/migrations/2026-08-06-stock-purchases-additional-attachments.ts b/scripts/migrations/2026-08-06-stock-purchases-additional-attachments.ts new file mode 100644 index 0000000..8a9b29a --- /dev/null +++ b/scripts/migrations/2026-08-06-stock-purchases-additional-attachments.ts @@ -0,0 +1,68 @@ +// scripts/migrations/2026-08-06-stock-purchases-additional-attachments.ts +// +// One-shot schema migration: add an `additional_attachments` file +// field to the `stock_purchases` collection. Mirrors the +// `purchase_orders.additional_attachments` field added by +// `2026-07-09-po-additional-attachments.ts`. +// +// Why this exists: stock POs didn't have a place to attach supplier +// invoices, packing slips, or photos of damaged stock. The +// `documents` / `documents_history` fields are the versioned-PDF +// ledger for the operator-generated PO PDF, so we add a sibling +// field rather than reusing `documents`. +// +// The MCP `stock_purchases.add_attachment` tool, the REST upload / +// delete routes under `/api/v1/stock-purchases/[id]/attachments/...`, +// and the AttachmentsCard on `/stock-orders/[id]` all depend on this +// field existing in PB. +// +// Idempotent: re-running is a no-op when the field is already present. + +import { getAdminPocketBase } from "@/lib/server/pocketbase-admin"; + +const COLLECTION_NAME = "stock_purchases"; +const FIELD_NAME = "additional_attachments"; + +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-purchases-additional-attachments] field already present on ${COLLECTION_NAME}`, + ); + return; + } + + // PB file-field convention: `maxSelect: 0` means "no cap" (the + // route enforces 25 MB per file via MAX_BYTES). Matches the PO + // migration exactly. + const newField = { + name: FIELD_NAME, + type: "file", + required: false, + presentable: false, + protected: false, + maxSelect: 0, + maxSize: 0, + mimeTypes: null, + thumbs: null, + }; + + await pb.collections.update(collection.id, { + fields: [...existing, newField], + }); + + console.log( + `[stock-purchases-additional-attachments] created field on ${COLLECTION_NAME} (file, multi, any mime)`, + ); +} + +main().catch((err) => { + console.error( + "[stock-purchases-additional-attachments] failed:", + err, + ); + process.exit(1); +}); \ No newline at end of file