diff --git a/AGENTS.md b/AGENTS.md index 0cd434c..23bf95e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -16,7 +16,7 @@ MRP Codex is a modular Manufacturing Resource Planning platform intended to be a - filesystem-backed attachments - CRM customers/vendors, hierarchy, contacts, lifecycle metadata, and attachments - inventory items, BOMs, warehouses, locations, transactions, item attachments, and item pricing -- sales quotes and sales orders +- sales quotes, sales orders, and purchase orders - shipping shipments and packing-slip PDFs - Puppeteer PDF foundation - single-container Docker deployment @@ -101,6 +101,7 @@ If implementation changes invalidate those docs, update them in the same change - Non-filter operational lookups must use searchable pickers/autocomplete instead of long static dropdowns - Keep the denser UI baseline on active screens unless a specific workflow needs more space - Inventory items maintain both cost and price; sales entry should default from item price +- Purchase-order item lookup must only expose inventory items flagged as purchasable - Customer-facing and logistics PDFs should continue to use the backend documents module and Puppeteer pipeline - The landing experience should remain `Dashboard`, not `Overview`, and should evolve as a modular metric-first operational surface @@ -108,7 +109,7 @@ If implementation changes invalidate those docs, update them in the same change Near-term priorities are: -1. Purchase orders and vendor-side flow +1. Purchase receiving flow and vendor-side operational depth 2. Sales and purchasing PDF templates 3. Shipping labels, bills of lading, and logistics attachments 4. Live manufacturing gantt scheduling diff --git a/INSTRUCTIONS.md b/INSTRUCTIONS.md index 33baaa4..3a996e9 100644 --- a/INSTRUCTIONS.md +++ b/INSTRUCTIONS.md @@ -12,6 +12,7 @@ This repository implements the platform foundation milestone: - inventory master data, BOM, warehouse, stock-location, transactions, and item attachments - sales quotes and sales orders with quick actions and quote conversion - purchase orders with quick actions and searchable vendor/SKU entry +- purchase orders restricted to inventory items flagged as purchasable - shipping shipments linked to sales orders and packing-slip PDFs - Dockerized single-container deployment - Puppeteer PDF pipeline foundation @@ -27,6 +28,7 @@ This repository implements the platform foundation milestone: 7. Inventory items must carry both `defaultCost` and `defaultPrice`; sales documents should default line pricing from the selected item `defaultPrice`. 8. Maintain the denser UI baseline on active screens; avoid reintroducing oversized `px-4 py-3` style controls, tall action bars, or overly loose card spacing without a specific reason. 9. Treat the landing page as `Dashboard`: a metric-oriented, modular command surface that should accumulate reusable operational panels over time. +10. Purchase-order item selection must be restricted to inventory items where `isPurchasable = true`. ## Operational notes diff --git a/README.md b/README.md index f389880..a596e1b 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Current foundation scope includes: - CRM contact history, account contacts, and shared attachments - inventory item master, BOM, warehouse, stock-location, and stock-transaction flows - sales quotes and sales orders with searchable customer and SKU entry -- purchase orders with searchable vendor and SKU entry +- purchase orders with searchable vendor and SKU entry, restricted to purchasable inventory items - shipping shipments linked to sales orders with packing-slip PDFs - file storage and PDF rendering @@ -179,6 +179,7 @@ The current purchasing foundation supports: - purchase-order list, detail, create, and edit flows - searchable vendor lookup instead of a static vendor dropdown - SKU-searchable line entry for purchase-order lines +- purchase-order item lookup restricted to inventory items flagged as purchasable - document-level tax, freight, subtotal, and total calculations - quick status actions directly from purchase-order detail pages - vendor payment terms and currency surfaced on purchase-order forms and details @@ -253,7 +254,7 @@ As of March 14, 2026, the latest committed domain migrations include: - sales totals and commercial fields - shipping foundation -Recent roadmap-driving migrations should always be applied before validating new CRM, inventory, sales, or shipping features in a running environment. +Recent roadmap-driving migrations should always be applied before validating new CRM, inventory, sales, shipping, or purchasing features in a running environment. ## UI Notes diff --git a/ROADMAP.md b/ROADMAP.md index eedc1e8..b966e51 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -29,6 +29,7 @@ MRP Codex is being built as a streamlined, modular manufacturing resource planni - Inventory transactions, on-hand tracking, and item attachments - Sales quotes and sales orders with commercial totals logic - Purchase orders with vendor lookup, item lines, totals, and quick status actions +- Purchase-order line selection restricted to inventory items flagged as purchasable - Shipping shipment records linked to sales orders - Packing-slip PDF rendering for shipments - SKU-searchable BOM component selection for inventory-scale datasets @@ -103,6 +104,7 @@ QOL subfeatures: - Line duplication, drag ordering, and keyboard-first line editing - Saved customer defaults for tax, freight, and commercial terms - Inline stock visibility while building quotes and orders +- Restrict purchase-order item entry to purchasable inventory only - Richer dashboard widgets for recent quotes, open orders, purchasing queues, and shipping exceptions - Better totals breakdown visibility on list pages and detail pages - Revision comparison view for changed customer-facing documents diff --git a/STRUCTURE.md b/STRUCTURE.md index 571f8bc..365fd03 100644 --- a/STRUCTURE.md +++ b/STRUCTURE.md @@ -19,6 +19,7 @@ - Any non-filter lookup UI must be implemented as a searchable picker or autocomplete; do not use long static dropdowns for operational datasets such as items, customers, vendors, or document-linked records. - Inventory items expose both cost and sell price. Downstream sales document entry should default from the item price field rather than requiring duplicate price maintenance. - Future vendor-facing purchasing flows should follow the same searchable-lookup rule and shared document/totals model already used by sales. +- Purchase-order item pickers must only surface inventory items flagged as purchasable. - Shipping, sales, and future purchasing PDFs should be rendered through the backend documents module and shared Puppeteer pipeline rather than ad hoc frontend-only exports. - Preserve the current dense operations UI style on active module pages: compact controls, tighter card padding, and shorter empty states unless a screen has a clear reason to be more spacious. diff --git a/UNRAID.md b/UNRAID.md index 49068a4..9c47cd0 100644 --- a/UNRAID.md +++ b/UNRAID.md @@ -125,7 +125,7 @@ When you publish a new image: Because MRP Codex runs `prisma migrate deploy` during startup, committed migrations are applied automatically before the app launches. -This is especially important now that recent releases added CRM expansion, inventory transactions, sales documents, shipping, packing slips, and the inventory `defaultPrice` field. Let the container complete startup migrations before testing new screens. +This is especially important now that recent releases added CRM expansion, inventory transactions, sales and purchasing documents, shipping, packing slips, the inventory `defaultPrice` field, and purchasable-only purchase-order item selection. Let the container complete startup migrations before testing new screens. ## Backup guidance diff --git a/client/src/modules/purchasing/PurchaseFormPage.tsx b/client/src/modules/purchasing/PurchaseFormPage.tsx index 720318f..600a1b5 100644 --- a/client/src/modules/purchasing/PurchaseFormPage.tsx +++ b/client/src/modules/purchasing/PurchaseFormPage.tsx @@ -1,5 +1,4 @@ -import type { InventoryItemOptionDto } from "@mrp/shared/dist/inventory/types.js"; -import type { PurchaseLineInput, PurchaseOrderInput, PurchaseVendorOptionDto } from "@mrp/shared"; +import type { InventoryItemOptionDto, PurchaseLineInput, PurchaseOrderInput, PurchaseVendorOptionDto } from "@mrp/shared"; import { useEffect, useState } from "react"; import { Link, useNavigate, useParams } from "react-router-dom"; @@ -32,7 +31,7 @@ export function PurchaseFormPage({ mode }: { mode: "create" | "edit" }) { } api.getPurchaseVendors(token).then(setVendors).catch(() => setVendors([])); - api.getInventoryItemOptions(token).then(setItemOptions).catch(() => setItemOptions([])); + api.getInventoryItemOptions(token).then((options) => setItemOptions(options.filter((option: InventoryItemOptionDto) => option.isPurchasable))).catch(() => setItemOptions([])); }, [token]); useEffect(() => { diff --git a/server/src/modules/inventory/service.ts b/server/src/modules/inventory/service.ts index e53f139..4c2073f 100644 --- a/server/src/modules/inventory/service.ts +++ b/server/src/modules/inventory/service.ts @@ -373,6 +373,7 @@ export async function listInventoryItemOptions() { id: true, sku: true, name: true, + isPurchasable: true, defaultPrice: true, }, orderBy: [{ sku: "asc" }], @@ -382,6 +383,7 @@ export async function listInventoryItemOptions() { id: item.id, sku: item.sku, name: item.name, + isPurchasable: item.isPurchasable, defaultPrice: item.defaultPrice, })); } diff --git a/shared/src/inventory/types.ts b/shared/src/inventory/types.ts index 2aa6e28..2e57aae 100644 --- a/shared/src/inventory/types.ts +++ b/shared/src/inventory/types.ts @@ -31,6 +31,7 @@ export interface InventoryItemOptionDto { id: string; sku: string; name: string; + isPurchasable: boolean; defaultPrice: number | null; }