PurchaseOrders
Purchase order header + items + receipts + receipt items. POs target either materials (raw inputs) or finished goods (resale), set on creation. Receipt ledger entries are written by MaterialsInventory / FinishedGoodsInventory via L3 — this component owns only the PO-side tables.
Tables owned
| Table | Purpose |
|---|---|
org.purchase_orders | PO header (number, vendor, target type, dates, ship-to, costs, status enum, QBO ID, notes). |
org.po_items | Line items. Polymorphic input (material_id XOR sku_id based on target type) with quantity and unit cost. |
org.po_receipts | Receipt headers (receipt date, notes) against a PO. |
org.po_receipt_items | Per-item received quantities for a receipt. |
Operations
Writes — Header
createPo(conn, input)→PurchaseOrder.input:{ number, vendorId, targetType, orderDate, expectedDeliveryDate?, shipToLocationId, costs?, status, qboId?, notes? }.targetType:'materials' | 'finished_goods'.status:po_statusenum.updatePo(conn, poId, patch)→PurchaseOrder. Partial update including status transitions.deletePo(conn, poId)→void. Cascades to items, receipts, receipt_items. L3 handles ledger reversal.
Writes — Items
addItem(conn, poId, item)→PoItem.item:{ materialId? | skuId?, quantity, unitCost }. Exactly one ofmaterialId/skuIdper target type.updateItem(conn, itemId, patch)→PoItem. Edits quantity / unit cost / referenced material or SKU.removeItem(conn, itemId)→void.
Writes — Receipts
createReceipt(conn, poId, input)→PoReceipt.input:{ receiptDate, notes? }. The associated ledger entries are written by L3 (which callsMaterialsInventory.recordReceipt/FinishedGoodsInventory.recordReceiptin the same transaction).updateReceipt(conn, receiptId, patch)→PoReceipt. Edits date / notes.deleteReceipt(conn, receiptId)→void. Cascades to receipt items.addReceiptItem(conn, receiptId, item)→PoReceiptItem.item:{ poItemId, receivedQuantity }.updateReceiptItem(conn, receiptItemId, patch)→PoReceiptItem. Edits received quantity.removeReceiptItem(conn, receiptItemId)→void.
Reads — Header
listPos(conn, filters?)→PurchaseOrder[]. Filters:{ status?, vendorId?, targetType?, dateFrom?, dateTo? }.getPoById(conn, poId)→PurchaseOrder | null.getPosByIds(conn, poIds)→PurchaseOrder[]. Batch hydration.getPoByNumber(conn, number)→PurchaseOrder | null. Used by ledger workflows to resolveref = PO number.
Reads — Items
listItemsByPo(conn, poId)→PoItem[].listItemsByPos(conn, poIds)→Map<poId, PoItem[]>. Batch hydration for list views.listAllItems(conn, filters?)→PoItem[]. Cross-PO lookups (e.g., "all items for material X"). Filters:{ materialId?, skuId?, status? }.getItemById(conn, itemId)→PoItem | null.
Reads — Receipts
listReceiptsByPo(conn, poId)→PoReceipt[].getReceiptById(conn, receiptId)→PoReceipt | null.listReceiptItems(conn, receiptId)→PoReceiptItem[].getReceivedTotalsByPo(conn, poId)→Map<poItemId, string>. Sums received quantities per line — used by L3 to compute PO line balance.
Notes
- "Generate PO PDF" is an L3 workflow (composes PO + items + vendor + org settings + ledger receipt data + Anthem template). No L2 op.
- "Bulk import POs" is an L3 workflow that parses input and calls
createPo+addItemin a transaction. No L2 batch op.