diff --git a/src/app/(app)/orders/[id]/process/page.tsx b/src/app/(app)/orders/[id]/process/page.tsx index d89a934..c72ed48 100644 --- a/src/app/(app)/orders/[id]/process/page.tsx +++ b/src/app/(app)/orders/[id]/process/page.tsx @@ -1441,14 +1441,26 @@ export default function ProcessOrderPage({ params }: { params: Promise<{ id: str const markInStockReady = async (supplierId: string) => { const supplier = suppliers.find((s) => s.id === supplierId); if (!supplier) return; + // Filter is loose on purpose: the per-row in-stock checkbox + // flips `item_status` to `ready_invoice` (legacy behaviour, no + // PO created by that path) which used to push these lines out + // of this filter and hide the bottom button. We want to issue + // the paper-trail PO from this button for ANY in-stock line + // that doesn't already have one, regardless of item_status, + // so the operator can tick the checkbox and then fire the PO + // from the same page without losing access to the action. + // + // The `purchase_order` guard skips lines already linked to a + // PO — a re-click must not duplicate. const inStock = items.filter( (it) => (it.supplier || "") === supplierId && - ["pending", "processed"].includes(it.item_status) && - it.in_stock, + it.in_stock && + (typeof it.purchase_order !== "string" || + it.purchase_order === ""), ); if (inStock.length === 0) { - toast.error("No in-stock items for this supplier"); + toast.error("No in-stock items need a PO"); return; } @@ -2086,12 +2098,26 @@ export default function ProcessOrderPage({ params }: { params: Promise<{ id: str const editable = list.filter((it) => ["pending", "processed"].includes(it.item_status), ); - if (editable.length === 0) return null; + // Lines that still need a stock-replenishment PO: + // any `in_stock=true` line without one yet, regardless + // of item_status. The per-row in-stock checkbox flips + // a line to `ready_invoice` (without creating a PO), + // which would otherwise push it out of `editable` and + // hide this button — yet the operator still needs to + // fire the paper-trail PO for it. + const needsStockPo = list.filter( + (it) => + it.in_stock && + (typeof it.purchase_order !== "string" || + it.purchase_order === ""), + ); + if (editable.length === 0 && needsStockPo.length === 0) { + return null; + } const nonInStockCount = editable.filter( (it) => !it.in_stock, ).length; - const inStockCount = editable.filter((it) => it.in_stock) - .length; + const inStockCount = needsStockPo.length; const isBusy = sendingSupplier === supplierId || markingInStockSupplier === supplierId;