Drop-ship via PO · vendor side runs in parallel
Path 3 covers SO lines where the vendor ships product directly. For each dropship_line, a PO is created FROM the SO (purchaseorder.createdfrom = so.id). Customer PO# threads via PO.bodyFields.memo = SO.otherrefnum and PO.lineFields.links[].tranid = " (the SO/customer-PO combo string).
After Item Receipt closes the PO line and Item Fulfillment ships to the customer, the Vendor Bill is entered carrying three fields with the customer PO# thread: memo, tranid, and initialtranid. This is the path with the richest threading — the customer PO# appears in 7+ field positions across 5 NS records.
Diagram: ns-sales-order-path-3-dropship.html.
Trigger conditions
- SO entered; one or more lines have
items.dropship = trueoritems.special_order = true. - Vendor is active (
vendors.status = 'active'). - Master dispatches into
so_lifecycle_dropship_path.
After Item Fulfillment, the automation alert fires to Finance for the customer-side invoice cycle. The vendor-side cycle runs in parallel (vendor bill entered + paid per vendor terms).
Driscoll 3 dropship lines via Cardinal Foods
Driscoll's SO 1217 (PO# 72622) includes 3 dropship lines totaling $4,800 via Cardinal Foods vendor #891.
PO-7833 created FROM SO 1217: createdfrom = 1217, bodyFields.memo = "72622", lineFields.links[].tranid = "1217 / 72622", entity = 891. Manually transmitted to Cardinal Foods (email PDF; EDI 850 outbound is STUB).
Cardinal ships direct to Driscoll. Item Receipt closes PO line. Item Fulfillment posted: createdfrom = 1217, otherrefnum = "72622". ★ Finance alert fires.
Customer side: CustInvc with otherrefnum = "72622", $4,800, Net 30. Driscoll pays day 24.
Vendor side (parallel): Cardinal sends invoice; Finance enters VendBill memo = "72622", tranid = "1217 / 72622", initialtranid = "1217 / 72622", createdfrom = "PO-7833". Paid per vendor terms.
PO create → ship → receipt → fulfillment → Finance · vendor bill parallel
- 01
Create PO FROM SO
NS
PurchOrd:createdfrom = so.id,memo = customer_po_number,lineFields.links[].tranid = ",/ " entity = vendor_id. - 02
Transmit PO to vendor
Manual today (email PDF). EDI 850 outbound is STUB.
- 03
Vendor ships
Direct to customer or to GFS crossdock. Tracking + ETA captured.
- 04
Item Receipt against PO
NS
ItemRcpt:createdfrom = po.id,status = "Received". PO line closes. - 05
Item Fulfillment to customer
NS
ItemFulfill:createdfrom = so.id(the SO, not the PO),otherrefnum = "72622"from SO. - 06
★ Finance alert (STUB)
Fires
events.so.finance_alert_fired. - 07
Customer Invoice
Same Finance steps as Path 1.
CustInvc.otherrefnum = "72622". - 08
Customer Payment · SO closes
- 09
Vendor Bill entered (parallel)
NS
VendBill:memo = "72622",tranid = "1217 / 72622",initialtranid = "1217 / 72622",createdfrom = po.id,entity = vendor_id. - 10
Vendor Bill paid per vendor terms
NS
VendPymt:appliedto = vendor_bill.id.
What's different after the cycle
What can go wrong
PO transmitted, no Item Receipt after expected lead time. Customer-side SO blocked. Vendor outreach required.
Sign of receipt confusion. Pause and reconcile against PO state.
Customer PO# threading broken. Vendor can't reference the customer order. Patch PO.memo to SO.otherrefnum; resync to NS.
Expected: ". If different, reconcile vs originating PO.
Adjacent flows + diagrams
Code paths + invariants
| Concern | Where |
|---|---|
| Workflow contract | so_lifecycle_dropship_path |
| PO ↔ SO link | purchaseorder.createdfrom = transactions.id |
| VendBill ↔ PO link | vendor_bills.createdfrom = purchase_orders.id |
| PO# thread on PO | PO.memo = SO.otherrefnum |
| PO# thread on PO lines | PO.lineFields.links[].tranid = " |
| PO# thread on VendBill | memo = tranid (parsed) = initialtranid (parsed) = customer PO# |
| EDI 850 outbound | STUB — manual email today |
Dated trail
| Date | Round | Change | Touched by |
|---|---|---|---|
2026-05-26 | R592 | Split into master + 3 path-detail docs; added Customer PO# threading schema (including VendBill memo/tranid/initialtranid). | Mike + Claude |
The machine-readable spec
workflow_type · so_lifecycle_dropship_path · risk_level · 3.
Customer PO# threading (Path 3 · PO + vendor side)
| NS record | Field | Sample value |
|---|---|---|
| Sales Order | bodyFields.otherrefnum (thread origin) | "72622" |
| Purchase Order | bodyFields.memo | "72622" |
| Purchase Order | lineFields.links[].tranid | "1217 / 72622" |
| Item Receipt | inherits via NS std linkage from PO | traces via createdfrom = po.id |
| Item Fulfillment | inherits via NS std linkage from SO — createdfrom = so.id | carries otherrefnum = "72622" |
| Customer Invoice | bodyFields.otherrefnum | "72622" |
| Vendor Bill | bodyFields.memo | "72622" |
| Vendor Bill | bodyFields.tranid | "1217 / 72622" |
| Vendor Bill | bodyFields.initialtranid | "1217 / 72622" |
D1 tables touched
| Table | Operation |
|---|---|
purchase_orders | INSERT (createdfrom, memo, lineFields) |
item_receipts | INSERT (createdfrom = po.id) |
item_fulfillments | INSERT (createdfrom = so.id, otherrefnum) |
customer_invoices | INSERT (otherrefnum threaded) |
customer_payments | INSERT |
payment_applications | INSERT |
vendor_bills | INSERT (memo, tranid, initialtranid all carry PO#) |
vendor_payments | INSERT |
transactions | UPDATE (SO + PO + Invoice status changes) |
events | INSERT (purchaseorder.created, so.finance_alert_fired, vendor_bill.paid, order.closed) |
It broke at 2am
Scenario · PO sent but vendor didn't ship
Path 3 stalled.
- Check PO status:
SELECT id, status, trandate FROM purchase_orders WHERE createdfrom=? - Vendor outreach: contact vendor with PO + customer PO# combo (e.g. "1217 / 72622").
- Check premature vendor bill:
SELECT * FROM vendor_bills WHERE po_id=?— if present, pause + reconcile. - Alternate source: close original PO, post Item Receipt against the new source.
Scenario · PO.memo missing customer PO# thread
Threading invariant broken on customer side.
- Verify:
SELECT po.memo, so.otherrefnum FROM purchase_orders po JOIN transactions so ON po.createdfrom=so.id WHERE po.id=? - Patch:
UPDATE purchase_orders SET memo = ? WHERE id = ?with SO.otherrefnum value. - NS push back: stage proposed_action to update NS PurchOrd.memo.
Scenario · VendBill tranid/initialtranid don't match expected combo
Vendor-side threading broken.
- Verify:
SELECT memo, tranid, initialtranid FROM vendor_bills WHERE createdfrom=? - Expected pattern:
memo = customer_po_number,tranid = initialtranid = "./ " - Patch all three fields: threading depends on all three carrying the same combo.
Logs to check
workflow_run_logevents· purchaseorder.created + so.finance_alert_fired + vendor_bill.paidproposed_actions· HITL for PO/VendBill creation
What's not done
-
STUB
Finance automation alert — NS workflow build
Platform fires
events.so.finance_alert_fired. NS workflow build pending next round. -
STUB
EDI 850 outbound PO transmission
Today: manual email of PO PDF. EDI 850 outbound would auto-transmit the PO + threading to EDI-enabled vendors.
-
OPEN
Auto-match VendBill on receipt by tranid combo
When vendor invoice arrives referencing the "
/ " combo, auto-match against the originating PO without manual keying.