PO triggered by an internal need · no customer side
Path 2 is the PO process triggered by an internal purchasing need — not by a Sales Order. The four common origins are: inventory replenishment (a location drops below its reorder point), assembly build components (an upcoming build needs BOM components not on hand), packaging supply (cases, labels, freight wrap), and general purchasing (services, MRO, freight, equipment, contracted goods).
Because there is no SO link, there is no customer PO# threading. The memo field on the PO and Vendor Bill carries an internal req# or vendor invoice# instead. Product arrives at the GFS facility, the loading dock physically receives it, Item Receipt is completed in NetSuite, and inventory_balance.quantityavailable += received qty at the correct location. The universal ★ automation alert then fires to Finance because receiving is at the dock but billing is Finance-owned.
Trigger conditions
inventory_balance.quantityavailable < items.reorder_pointat a location.- Upcoming assembly build run needs BOM components not currently on hand.
- Packaging supply restock (cases, labels, freight wrap, slip sheets).
- General purchasing: services, freight, equipment, contracted goods, MRO.
After Item Receipt completes and inventory is credited, the automation alert fires to Finance. Same event (events.po.finance_alert_fired) as Path 1 — only the threading and absence of customer-side cycle differ.
Bongards barrel cheddar replenishment to NJ Heartland
NJ Heartland inventory of Bongards barrel cheddar drops below 500 cases. Purchasing identifies the need; PO-7910 entered: entity = 412 (Bongards Creameries), memo = "REQ-04472" (internal req#), createdfrom = NULL, location = NJ Heartland, expected delivery day 10.
PO emailed (PDF) to Bongards on day 1. Bongards confirms order, locks pricing (CME trailing week + 35% moisture per the standing pricing model), commits to day 10 delivery.
Day 10: Bongards truck arrives at the NJ Heartland dock. Dock unloads, counts pallets, condition-checks (freezer integrity, lot codes), matches BOL + packing slip vs PO lines. No shortages.
Item Receipt completed in NS: createdfrom = "PO-7910", status = "Received", location = NJ Heartland. D1 mirror: inventory_balance.quantityavailable += received qty at NJ Heartland.
★ po.finance_alert_fired event fires. Finance reviews PO + Item Receipt + Bongards' invoice + packing slip. VendBill entered: memo = "REQ-04472", createdfrom = "PO-7910". No customer PO# anywhere. Paid per Net 30.
Purchasing need → PO → dock receive → inventory credit → Finance
- 01
Identify purchasing need
Inventory replenishment / assembly build components / packaging supply / general purchasing.
- 02
Enter PO in NetSuite
NS
PurchOrd:tranid,entity = vendor_id,memo = internal req# / vendor invoice#,location = destination location_id,createdfrom = NULL(no SO link), lines per item. - 03
Transmit PO to vendor
Manual email PDF today; STUB EDI 850 outbound.
- 04
Vendor confirms order, pricing, expected delivery date
Captured: order accepted, vendor cost locked per line, expected delivery date, any subs / shortages flagged.
- 05
Product arrives at the facility
Vendor truck arrives at the GFS receiving dock; BOL + packing slip handed off.
- 06
Loading dock receives the product
Unload, count pallets, condition check (damages, freezer integrity, lot codes), match BOL + packing slip vs PO lines, note any shortages / damages / substitutions.
- 07
Item Receipt completed in NetSuite
NS
ItemRcpt:createdfrom = po.id,status = "Received",location = location_id,lineFields[].quantity_received. - 08
Inventory + at correct location
UPDATE inventory_balance SET quantityavailable = quantityavailable + ? WHERE item_code=? AND location_id=?.events.inventory.creditedfires. - 09
★ Automation alert → Finance
Fires
events.po.finance_alert_fired. STUB until NS workflow build. - 10
Finance review
Finance reviews PO + Item Receipt + supporting docs (packing slip, vendor invoice). Checks qty match, pricing match, any flagged issues.
- 11
Vendor Bill entered
NS
VendBill:createdfrom = po.id,memo = "REQ-04472"(internal req#, no customer PO# thread). - 12
Vendor Bill paid per vendor terms
NS
VendPymt:appliedto = vendor_bill.id. - 13
Resolve issues · close PO
Any shortages / damages / subs / pricing reconciled. PO →
'Closed';events.po.closedfires.
What's different after the cycle
What can go wrong
Inventory not credited; future replenishment trigger fires again on stale signal. Dock team to backfill Item Receipt against the PO.
Short ship or over-ship. Flag for Finance reconcile; vendor credit / rebill before VendBill close.
Should be Path 1, not Path 2. Re-dispatch under po_lifecycle_sales_order_connected_path; backfill threading on memo.
Item Receipt location mismatch. Adjust inventory_balance at both locations; document the correction in proposed_actions.
Adjacent flows + diagrams
Code paths + invariants
| Concern | Where |
|---|---|
| Workflow contract | po_lifecycle_inventory_or_build_path (risk 2) |
| No-SO-link invariant | purchase_orders.createdfrom IS NULL or parent ≠ SalesOrd |
| VendBill ↔ PO link | vendor_bills.createdfrom = purchase_orders.id |
| Inventory credit | inventory_balance.quantityavailable += received qty at location_id |
| memo field | internal req# / vendor invoice# only (no customer PO# thread) |
| EDI 850 outbound | STUB — manual email today |
Dated trail
| Date | Round | Change | Touched by |
|---|---|---|---|
2026-05-26 | R593 | Built PO master + 2 path-details matching SO pattern. | Mike + Claude |
The machine-readable spec
workflow_type · po_lifecycle_inventory_or_build_path · risk_level · 2.
Customer PO# threading (Path 2 — not applicable)
Path 2 POs have no SO origin, so the customer PO# threading invariant from R592 / Path 1 does not apply. The memo field carries an internal reference instead:
| NS record | Field | Sample value |
|---|---|---|
| Purchase Order | bodyFields.createdfrom | NULL (no SO link) |
| Purchase Order | bodyFields.memo | "REQ-04472" (internal req#) |
| Purchase Order | bodyFields.location | NJ Heartland |
| Item Receipt | bodyFields.createdfrom | po.id (e.g. "PO-7910") |
| Item Receipt | bodyFields.location | NJ Heartland |
| Vendor Bill | bodyFields.memo | "REQ-04472" (no customer PO#) |
| Vendor Bill | bodyFields.createdfrom | po.id |
createdfrom pointing at a row in transactions where type='SalesOrd', it has been misclassified. Re-dispatch under po_lifecycle_sales_order_connected_path and backfill the customer PO# thread on memo.D1 tables touched
| Table | Operation |
|---|---|
purchase_orders | INSERT (header, no createdfrom) |
purchase_order_lines | INSERT (per line) |
item_receipts | INSERT (createdfrom = po.id, location captured) |
inventory_balance | UPDATE (quantityavailable += received qty at location) |
vendor_bills | INSERT (memo = internal req#) |
vendor_payments | INSERT |
transactions | UPDATE (status changes) |
events | INSERT (po.created, po.transmitted, inventory.credited, po.finance_alert_fired, po.closed) |
proposed_actions | INSERT (shortages, damages, subs HITL) |
It broke at 2am
Scenario · Product arrived but Item Receipt skipped
Inventory not credited.
- Verify physical arrival: dock team confirms unload, BOL on file.
- Backfill Item Receipt: stage proposed_action to post NS ItemRcpt with
createdfrom = po.idand the receive datetime. - Verify inventory credit:
SELECT quantityavailable FROM inventory_balance WHERE item_code=? AND location_id=?reflects the receive.
Scenario · Receipt qty ≠ PO qty
Short or over.
- Identify lines:
SELECT pol.item_code, pol.quantity AS ordered, irl.quantity_received AS received FROM purchase_order_lines pol LEFT JOIN item_receipt_lines irl ON irl.po_line_id = pol.id WHERE pol.po_id=? - Short ship: vendor credit / rebill; stage proposed_action.
- Over ship: reconcile vs vendor invoice; decide keep + bill / return.
Scenario · Misclassified PO has SO link
Path 2 invariant violation.
- Verify:
SELECT p.id, p.createdfrom, t.type FROM purchase_orders p LEFT JOIN transactions t ON p.createdfrom=t.id WHERE p.id=? - If
t.type = 'SalesOrd': re-dispatch as Path 1; backfillp.memofromt.otherrefnum.
Logs to check
workflow_run_logevents· po.created + po.transmitted + inventory.credited + po.finance_alert_fired + po.closedproposed_actions· HITL for short ships / damages / subs / VendBill
What's not done
-
STUB
Finance automation alert — NS workflow build
Platform fires
events.po.finance_alert_fired. NS workflow build pending Mike's deploy. -
STUB
EDI 850 outbound PO transmission
Today: manual email. EDI 850 would auto-transmit to EDI-enabled vendors.
-
OPEN
Auto-PO from reorder point signal
Today purchasing identifies the need manually via reports. A scheduled job could surface reorder-point breaches and stage a draft PO for HITL approval.
-
OPEN
Auto-link to upcoming Work Orders
For assembly build PO origins, link the PO back to the WO that drove the need. Helpful for variance + cost attribution.
-
DECISION
memo convention — internal req# vs vendor invoice#
Practice today varies (sometimes req#, sometimes vendor invoice#, sometimes free text). Confirm with Mike whether to standardize on one convention.