Wiki · Purchase order · PATH 2 · R593

Path 2 · PO for inventory or assembly build

Triggered by an internal purchasing need — inventory replenishment, assembly build components, packaging supply, or general purchasing. No Sales Order link, no customer PO# threading. Loading dock receives, inventory credited at the correct location, Finance reviews + bills.

PATH 2 REAL ★ Finance alert pending NS automation
What this is

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.

Diagram: ns-purchase-order-path-2-inventory-or-build.html.

When to use it

Trigger conditions

★ The handoff

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.

Worked example

Bongards barrel cheddar replenishment to NJ Heartland

Scenario

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.

Step-by-step what happens

Purchasing need → PO → dock receive → inventory credit → Finance

  1. 01

    Identify purchasing need

    Inventory replenishment / assembly build components / packaging supply / general purchasing.

  2. 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.

    No PO# thread memo = internal req#
  3. 03

    Transmit PO to vendor

    Manual email PDF today; STUB EDI 850 outbound.

  4. 04

    Vendor confirms order, pricing, expected delivery date

    Captured: order accepted, vendor cost locked per line, expected delivery date, any subs / shortages flagged.

  5. 05

    Product arrives at the facility

    Vendor truck arrives at the GFS receiving dock; BOL + packing slip handed off.

  6. 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.

  7. 07

    Item Receipt completed in NetSuite

    NS ItemRcpt: createdfrom = po.id, status = "Received", location = location_id, lineFields[].quantity_received.

  8. 08

    Inventory + at correct location

    UPDATE inventory_balance SET quantityavailable = quantityavailable + ? WHERE item_code=? AND location_id=?. events.inventory.credited fires.

  9. 09

    ★ Automation alert → Finance

    Fires events.po.finance_alert_fired. STUB until NS workflow build.

  10. 10

    Finance review

    Finance reviews PO + Item Receipt + supporting docs (packing slip, vendor invoice). Checks qty match, pricing match, any flagged issues.

  11. 11

    Vendor Bill entered

    NS VendBill: createdfrom = po.id, memo = "REQ-04472" (internal req#, no customer PO# thread).

  12. 12

    Vendor Bill paid per vendor terms

    NS VendPymt: appliedto = vendor_bill.id.

  13. 13

    Resolve issues · close PO

    Any shortages / damages / subs / pricing reconciled. PO → 'Closed'; events.po.closed fires.

Outcomes

What's different after the cycle

PO
Closed
received + billed + paid
Inventory
Credited
at correct location
VendBill
Paid
per vendor terms
Customer side
None
no SO chain
Failure modes

What can go wrong

Product arrives but Item Receipt skipped

Inventory not credited; future replenishment trigger fires again on stale signal. Dock team to backfill Item Receipt against the PO.

Receipt qty ≠ PO qty

Short ship or over-ship. Flag for Finance reconcile; vendor credit / rebill before VendBill close.

Misclassified PO has createdfrom pointing at an SO

Should be Path 1, not Path 2. Re-dispatch under po_lifecycle_sales_order_connected_path; backfill threading on memo.

Inventory credited at wrong location

Item Receipt location mismatch. Adjust inventory_balance at both locations; document the correction in proposed_actions.

Related

Adjacent flows + diagrams

For developers

Code paths + invariants

ConcernWhere
Workflow contractpo_lifecycle_inventory_or_build_path (risk 2)
No-SO-link invariantpurchase_orders.createdfrom IS NULL or parent ≠ SalesOrd
VendBill ↔ PO linkvendor_bills.createdfrom = purchase_orders.id
Inventory creditinventory_balance.quantityavailable += received qty at location_id
memo fieldinternal req# / vendor invoice# only (no customer PO# thread)
EDI 850 outboundSTUB — manual email today
// Path 2 invariant — confirm no SO link SELECT p.id, p.memo, p.createdfrom, t.type FROM purchase_orders p LEFT JOIN transactions t ON p.createdfrom = t.id WHERE p.id = ? // expected: p.createdfrom IS NULL -- or t.type IS NOT 'SalesOrd' // if t.type = 'SalesOrd', this should be Path 1 instead
Changelog

Dated trail

DateRoundChangeTouched by
2026-05-26R593Built PO master + 2 path-details matching SO pattern.Mike + Claude
Schema · data contract

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 recordFieldSample value
Purchase OrderbodyFields.createdfromNULL (no SO link)
Purchase OrderbodyFields.memo"REQ-04472" (internal req#)
Purchase OrderbodyFields.locationNJ Heartland
Item ReceiptbodyFields.createdfrompo.id (e.g. "PO-7910")
Item ReceiptbodyFields.locationNJ Heartland
Vendor BillbodyFields.memo"REQ-04472" (no customer PO#)
Vendor BillbodyFields.createdfrompo.id
Audit recipe: if you find a PO with 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

TableOperation
purchase_ordersINSERT (header, no createdfrom)
purchase_order_linesINSERT (per line)
item_receiptsINSERT (createdfrom = po.id, location captured)
inventory_balanceUPDATE (quantityavailable += received qty at location)
vendor_billsINSERT (memo = internal req#)
vendor_paymentsINSERT
transactionsUPDATE (status changes)
eventsINSERT (po.created, po.transmitted, inventory.credited, po.finance_alert_fired, po.closed)
proposed_actionsINSERT (shortages, damages, subs HITL)
Runbook · when it breaks

It broke at 2am

Scenario · Product arrived but Item Receipt skipped

Inventory not credited.

  1. Verify physical arrival: dock team confirms unload, BOL on file.
  2. Backfill Item Receipt: stage proposed_action to post NS ItemRcpt with createdfrom = po.id and the receive datetime.
  3. 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.

  1. 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=?
  2. Short ship: vendor credit / rebill; stage proposed_action.
  3. Over ship: reconcile vs vendor invoice; decide keep + bill / return.

Scenario · Misclassified PO has SO link

Path 2 invariant violation.

  1. Verify: SELECT p.id, p.createdfrom, t.type FROM purchase_orders p LEFT JOIN transactions t ON p.createdfrom=t.id WHERE p.id=?
  2. If t.type = 'SalesOrd': re-dispatch as Path 1; backfill p.memo from t.otherrefnum.

Logs to check

Backlog · open questions

What's not done