Purchase Orders Module
Phase 4 Purchasing module (Milestone 2) on the frozen platform. Mirrors the Estimates reference architecture — a header + line-item document with a status workflow, assignment, notes, and an activity timeline. Purchase Orders hard-depends on the Vendors module (Milestone 1) — every purchase order must reference a vendor.
Guides
| Audience | Document |
|---|---|
| Operators / workspace users | purchase-orders.md |
| Engineers | purchase-orders-developer.md |
| Production / ops | purchase-orders-production.md |
| Module Development Standard | module-development.md |
| Reference blueprint | estimates.md |
| Tenant API | ../api/tenant-v1-purchase-orders.md |
Capabilities
- Header: number (
PO-prefix, configurable), required vendor, title, status, currency, order date, expected date, notes, subtotal/tax/total - Line items (description, quantity, unit price, tax rate, optional product) — subtotal/tax/total recomputed server-side, draft-only edits
- Status workflow:
draft → sent → partially_received | received | cancelled(alsosent → cancelled,partially_received → received | cancelled) - Assignment (
created_by/assigned_to) with assignee scoping viapurchase-orders.assign - Notes (comments) + activity timeline
- Table view with search, status filter, assignee filter, and My Purchase Orders toggle
- KPIs via
GET /purchase-orders/stats(total, mine, draft, sent, partially received, received, cancelled) - Dashboard widget
open_purchase_orders(module +purchase-orders.view) - Download PO PDF + email vendor after Send (
GET /purchase-orders/{id}/pdf,POST /purchase-orders/{id}/email,purchase-orders.send) - Trash filtering plus Restore and Delete permanently
- Module licensing (
module:purchase-orders) + Spatie permissions — free Marketplace opt-in, hard-depends onvendors - Audit + activity logging
Permissions
purchase-orders.view · create · update · delete · restore · force.delete · assign · send · receive · cancel
Enable Purchase Orders from Marketplace (free) — Marketplace blocks the install until Vendors is already entitled. Catalog: slug purchase-orders, category purchasing (Purchasing), is_default_included = false, is_billable = false, sort_order = 20, version 1.3.0.
Receiving and Inventory
Partially received remains a status-only acknowledgement. When Products and Inventory are entitled, marking an order received posts stock-in for each product-linked line whose Product tracks stock. Receiving may select an optional warehouse; the default warehouse is used otherwise. Lines without product_id do not post stock.
Convert to expense (soft, Phase 4 Milestone 3)
Sent, partially received, or received purchase orders can be converted to a draft Expense — a one-way, one-time action gated by the purchase-orders.convert permission and a soft entitlement check on the Expenses module (no hard module_dependencies row). See Purchase Orders — User Guide.
Explicitly deferred
- Partial-quantity receiving per line item (status is currently header-level only)