NetSuite sales order — master

Email intake → SO entry (capture otherrefnum=customer PO#) → branch into 3 path sub-contracts → converge at Item Fulfillment → ★ Finance handoff → invoice → payment / dunning

High-altitude master view of the entire SO process. Customer orders arrive at orders@globalfoodsolutions.co or danielle@globalfoodsolutions.co. The team reviews each one against the customer file and keys it into NetSuite as a Sales Order, capturing the otherrefnum field as the customer PO#. From there the SO branches by item type into three path sub-contracts — Path 1 inventory, Path 2 assembly (Work Orders FROM the SO), or Path 3 dropship (POs FROM the SO). All three paths converge at Item Fulfillment, which fires the ★ automation alert to Finance. The customer PO# (entered as otherrefnum on the SO) threads through every connected NS record — PO memo, Invoice otherrefnum, Vendor Bill memo / tranid / initialtranid. This is the trace thread for "where did Driscoll's PO 72622 go." See path detail docs for field-level depth.

D1-mirrored from NS HITL outside guardrails Path 1 · inventory Path 2 · assembly Path 3 · dropship EDI 850 auto-intake STUB

Pipeline — email intake → 3 fulfillment paths → finance convergence

idle
NS sales order lifecycle — email intake → SO review + entry → branch by item type into 3 paths (inventory / assembly / dropship) → Item Fulfillment → Finance alert (key handoff) → invoice → payment → close (dunning loopback if past due) 01 / Email intake 02 / SO review + entry (capture otherrefnum = customer PO#) 03 / Branch by item type · dispatch to sub-contract PATH 1 / Inventory fulfillment · see ns-sales-order-path-1-inventory.html PATH 2 / Assembly build · see ns-sales-order-path-2-assembly.html PATH 3 / Drop ship · see ns-sales-order-path-3-dropship.html 04 / Item Fulfillment (converge) 05 / Finance handoff · ★ STUB (pending NS automation deploy) 06 / Invoice · payment · close (dunning loopback) WHAT THIS DOES: The system watches two mailboxes for incoming customer orders. Each email carries a customer PO number, which is the trace ID we keep for the whole order. TECHNICAL DETAILS: EMAIL INTAKE — Most customer orders arrive by email at two mailboxes. MAILBOXES orders@globalfoodsolutions.co danielle@globalfoodsolutions.co SOURCE customer email — PO body, attached spreadsheet, or freeform EDI 850 — lands here today, keyed manually into NS (STUB autoparse) portal — customer portal upload form STATUS: REAL (manual intake) · STUB (EDI auto-parse) customer email intake orders@globalfoodsolutions.co danielle@globalfoodsolutions.co EXTERNAL · EMAIL ROUTING i WHAT THIS DOES: Less common channels (NetSuite UI, customer portal, EDI, phone). All eventually land in NetSuite as a Sales Order keyed by a human. TECHNICAL DETAILS: OTHER INTAKE CHANNELS — Less common than email today, but real. CHANNELS NS UI direct entry customer portal upload EDI 850 — STUB auto-parse phone → keyed by CS STATUS: REAL · EDI STUB other channels NS UI · portal · phone EDI 850 (manual keying) EXTERNAL · EDI STUB i WHAT THIS DOES: Before keying the order, the team reads it against the customer's file in NetSuite to confirm ship-to, pack sizes, prices, and special notes. TECHNICAL DETAILS: REVIEW + CONFIRM — Team reads the order against the customer file before keying. CHECKS customer record exists + correct ship-to item details (pack/size/UOM match) pricing alignment (contract / program / list) shipping requirements special instructions / delivery windows TABLES read: customers · pricing_master · customer_programs · contracts STATUS: REAL · operator-driven review customer order customer file · items · ship-to pricing · special instructions DATABASE · customers · pricing i WHAT THIS DOES: The team creates the Sales Order in NetSuite. We record who it is for and copy the customer's PO number into otherrefnum, which is the thread we follow. TECHNICAL DETAILS: ENTER SO IN NETSUITE — SO posted as system-of-record. Captures customer PO# on otherrefnum. ACTION create: NS Sales Order (SalesOrd) capture: bodyFields.otherrefnum = customer PO# (e.g. "72622") capture: bodyFields.tranid = NS-assigned SO number (e.g. "1217") mirror: D1 transactions + so_lines on next hot-tier sync (2min) TABLES write: NS SalesOrd · D1 transactions · so_lines THREADING otherrefnum threads to Item Fulfillment + CustInvc on this SO chain STATUS: REAL enter SO in NetSuite otherrefnum = customer PO# · tranid = NS SO# D1 sync (2-min hot tier) BACKEND · NS + D1 mirror i WHAT THIS DOES: Each line on the order is sorted into one of three paths: pull from stock, build it ourselves, or have the vendor drop-ship it. One order can use all three at once. TECHNICAL DETAILS: CLASSIFY EACH LINE BY ITEM TYPE — A single SO routinely spans multiple paths. LOGIC per so_line.item.type: inventory_item → Path 1 (fulfill from inventory) assembly_item → Path 2 (work order created from SO) dropship_item OR special_order → Path 3 (PO created from SO) TABLES read: items.itemtype · items.cost_method STATUS: REAL (operator-driven today) · STUB (auto-classify on /api/so/create) classify each line by item type inventory · assembly · dropship single SO can hit all 3 paths SECURITY · operator-driven · auto STUB i WHAT THIS DOES: Path 1: the item is already on the shelf. We reserve qty, pick, pack, stage, and ship. No production or PO needed. TECHNICAL DETAILS: PATH 1 · FULFILL FROM INVENTORY — Summary. See ns-sales-order-path-1-inventory.html for field-level depth. WORKFLOW so_lifecycle_inventory_path (sub-contract dispatched from master) SUMMARY inventory_balance check → reserve → pick → pack → stage → Item Fulfillment LINKAGE itemfulfillment.createdfrom = so.id itemfulfillment inherits otherrefnum from SO (customer PO# threading) NO PRODUCTION · NO PO STATUS: REAL PATH 1 · fulfill from inventory reserve · pick · pack · stage · Item Fulfillment itemfulfillment.createdfrom = so.id otherrefnum threads from SO → IF → Invoice PATH 1 · so_lifecycle_inventory_path DATABASE · see ns-sales-order-path-1-inventory.html i WHAT THIS DOES: Path 2: we have to build the item. A Work Order is created from the Sales Order, BOM components are consumed, and a finished-goods build is credited to inventory. TECHNICAL DETAILS: PATH 2 · ASSEMBLY BUILD — Summary. See ns-sales-order-path-2-assembly.html for field-level depth. WORKFLOW so_lifecycle_assembly_path (sub-contract dispatched from master) SUMMARY Per assembly_line: WO created FROM SO → BOM consume → assembly build → FG credit → Item Fulfillment ALTERNATE If FG already on hand → fulfill from inventory + close WO (marked "unused") LINKAGE workorder.createdfrom = so.id WO customer PO# field: TBD (Mike review pending; expected pattern bodyFields.memo) HITL /assembly-build.html → proposed_actions → Mike approves STATUS: REAL PATH 2 · Work Orders FROM SO workorder.createdfrom = so.id · BOM consume · build · FG credit alt: FG on hand → fulfill from inventory + close WO WO PO# field: TBD (Mike review pending) PATH 2 · so_lifecycle_assembly_path MESSAGEBUS · see ns-sales-order-path-2-assembly.html i WHAT THIS DOES: Path 3: a vendor ships directly to the customer. A Purchase Order is created from the Sales Order. Item Receipt and Item Fulfillment go in back-to-back. TECHNICAL DETAILS: PATH 3 · DROPSHIP — Summary. See ns-sales-order-path-3-dropship.html for field-level depth. WORKFLOW so_lifecycle_dropship_path (sub-contract dispatched from master) SUMMARY Per dropship_line: PO created FROM SO → transmit → vendor ships → Item Receipt → Item Fulfillment Vendor side: Vendor Bill entered → paid per vendor terms (parallel cycle) LINKAGE purchaseorder.createdfrom = so.id PO.bodyFields.memo = customer PO# (e.g. "72622") PO.lineFields.links[].tranid = "<so.tranid> / <customer_po>" (e.g. "1217 / 72622") VendBill.memo / tranid / initialtranid = customer PO# threading STATUS: REAL PATH 3 · POs FROM SO + vendor side purchaseorder.createdfrom = so.id · transmit · IR · Item Fulfillment PO.memo = customer PO# · lineFields.links[].tranid = "1217 / 72622" VendBill.memo · tranid · initialtranid all thread PO# PATH 3 · so_lifecycle_dropship_path MESSAGEBUS · see ns-sales-order-path-3-dropship.html i WHAT THIS DOES: All three paths land here. The Item Fulfillment record closes (status=Shipped), inventory is decremented, BOL and ASN are generated. This is what triggers the alert to Finance. TECHNICAL DETAILS: ITEM FULFILLMENT COMPLETED — All 3 paths converge here. SO fulfilled to customer. ACTION status: itemfulfillment → 'Shipped' inventory: decrement by shipped qty generate: BOL · ASN if EDI customer links: SO ↔ itemfulfillment ↔ (WO|PO if applicable) TABLES write: itemfulfillment (Shipped) · inventory_balance · transactions NOTE Convergence point — single SO with mixed-path lines hits this once per fulfillment event STATUS: REAL Item Fulfillment completed itemfulfillment → Shipped · inventory decremented · BOL/ASN CONVERGENCE · all 3 paths land here i WHAT THIS DOES: The single named handoff between Operations and Finance. The moment Item Fulfillment is marked Shipped, an alert fires telling Finance to invoice. TECHNICAL DETAILS: ★ AUTOMATION ALERT → FINANCE — THE KEY HANDOFF SIGNAL. TRIGGER itemfulfillment.status changes to 'Shipped' ACTION fire: NS workflow / scheduled script alert to Finance fire: events row so.finance_alert_fired SPEC see spec doc for finance alert NS automation (next round) STATUS: STUB — platform-side event fires (REAL); NS workflow build pending next round (Mike to deploy) ★ automation alert → Finance STUB · REAL once NS automation deployed (next round) FINANCE · emits so.finance_alert_fired event i WHAT THIS DOES: Before keying the order, the team reads it against the customer's file in NetSuite to confirm ship-to, pack sizes, prices, and special notes. TECHNICAL DETAILS: FINANCE REVIEW — Finance reviews the fulfillment before invoicing. CHECKS fulfilled qty matches expected pricing carried through correctly customer terms + tax handling correct any short-ships flagged TABLES read: itemfulfillment · so_lines · customer.terms STATUS: REAL · Finance-driven Finance review qty · pricing · terms · tax CLOUD · Finance role i WHAT THIS DOES: Finance posts the invoice in NetSuite. The customer's PO number is copied onto the invoice so the customer can match it on their end. TECHNICAL DETAILS: INVOICE CUSTOMER — Finance posts the customer invoice. ACTION generate: invoice_lines from shipped qty (not ordered qty) post: CustInvc transaction · AR balance updates TABLES write: transactions (CustInvc) · invoice_lines · v_customer_ar_aging STATUS: REAL invoice customer CustInvc · AR balance BACKEND · CustInvc i WHAT THIS DOES: We watch the invoice's due date. Current/30/60/90+ buckets are tracked in v_customer_ar_aging. TECHNICAL DETAILS: INVOICE OPEN · MONITOR PAYMENT TERMS — Track invoice until customer pays. ACTION monitor: due_date vs today surface: AR aging buckets (current / 30 / 60 / 90+) TABLES read: transactions · payment_applications · v_customer_ar_aging STATUS: REAL monitor terms AR aging · due_date DATABASE · v_*_aging i WHAT THIS DOES: If the invoice goes past due, the dunning ladder fires (escalating reminder emails at 30, 60, 90+ days until paid or service hold). TECHNICAL DETAILS: PAST DUE → DUNNING — If payment_terms exceeded, dunning workflow fires. ACTION trigger: ar_aging_action_plan workflow draft: dunning email at escalating tone (30/60/90+) TABLES read: v_customer_ar_aging · customers write: proposed_actions (dunning_email_draft) LOOPBACK emails sent → wait for payment → loop until paid OR service hold STATUS: REAL (workflow contract) · email send still HITL past due → dunning ar_aging_action_plan SECURITY · HITL email i WHAT THIS DOES: The customer pays. We post a Customer Payment in NetSuite, apply it against the invoice, and AR is reduced. TECHNICAL DETAILS: PAYMENT RECEIVED · APPLY — Customer remits; CustPymt posted. ACTION receive: customer_payments row apply: payment_applications match payment to invoice(s) TABLES write: customer_payments · payment_applications · transactions (CustPymt) STATUS: REAL payment received CustPymt · apply DATABASE · CustPymt i WHAT THIS DOES: Once shipped, invoiced, and paid, the SO is closed. We fire an order.closed event so the customer health watcher updates. TECHNICAL DETAILS: CLOSE ORDER — SO closed once fully shipped + invoiced + paid. ACTION status: SO → 'Closed' or 'Billed' fire: events.order.closed for customer health watcher TABLES write: transactions (status) · events STATUS: REAL close order SO status · events fire BACKEND · order.closed i WHAT THIS DOES: Drop-ship side cash cycle: we enter a Vendor Bill against the PO and pay it per vendor terms, in parallel to the customer-side invoice. TECHNICAL DETAILS: VENDOR-SIDE (Path 3 only) — Drop-ship orders also produce a vendor bill cycle. ACTION enter: vendor bill against PO pay: vendor bill per vendor terms TABLES write: vendor_bills · vendor_payments NOTE Runs in parallel to customer-side invoice/payment. Separate cash cycle. STATUS: REAL vendor bill cycle (Path 3) enter · pay per terms MESSAGEBUS · vendor side i asm line → Path 1 (sub-contract) → Path 2 (sub-contract) → Path 3 (sub-contract) asm line all 3 paths converge → Item Fulfillment ★ alert ★ automation alert ★ alert past due drp line loop: 30 / 60 / 90+ days until paid or service hold LEGEND Path 1 inventory Path 2 assembly Path 3 dropship ★ Finance handoff HITL / dunning CUSTOMER PO# THREADING · trace one PO across the entire SO chain (sample: customer PO# 72622, NS SO# 1217) Sales Order otherrefnum "72622" tranid "1217" Purchase Order (Path 3) memo · lineFields.links[].tranid "72622" / "1217 / 72622" createdfrom = so.id Customer Invoice otherrefnum "72622" createdfrom = so.id Vendor Bill (Path 3) memo · tranid · initialtranid "72622" / "1217 / 72622" createdfrom = po.id Work Order (Path 2) · TBD expected: bodyFields.memo "72622" (TBD) Mike review pending Item Fulfillment / Receipt inherits via NS std linkage otherrefnum → "72622" IF from SO · IR from PO Trace the customer PO# across every record — grep otherrefnum / memo / tranid / initialtranid for "72622" lights up every record in this SO chain.

Phase detail — Mike's actual 3-path process

01 Customer email intake REAL · manual EDI auto STUB

Most orders arrive by email at two mailboxes. EDI 850 lands here too but is keyed manually into NS today.
Mailboxes
orders@globalfoodsolutions.co · danielle@globalfoodsolutions.co
Other channels
NS UI · customer portal · phone · EDI (manual keying)
STUB
EDI 850 auto-parse into /api/so/create

02 Review customer order REAL · operator-driven

Team reads the order against the customer file before keying. Confirms item details, customer details, shipping, pricing, and special instructions.
Checks
customer record · ship-to · pack/UOM · pricing alignment · ship windows
Tables read
customers · pricing_master · customer_programs · contracts

03 Enter SO in NetSuite REAL

SO posted as system-of-record. D1 mirrors on next 2-min hot-tier sync.
NS record
SalesOrd
Tables write
transactions (SalesOrd) · so_lines

04 Classify each line by item type REAL · operator auto STUB

A single SO routinely spans multiple paths because line items differ in type. Today operators route mentally; auto-classification on intake is a stub.
Path 1
inventory_item → fulfill from inventory
Path 2
assembly_item → Work Order created FROM SO
Path 3
dropship_item / special order → Purchase Order created FROM SO

P1 Option 1 — Fulfill from inventory PATH 1 REAL

Items already on hand. No production. No PO. Pull, pick, pack, stage.
Steps
check qty → reserve → pick list → pack → stage
Tables write
itemfulfillment (open) · inventory_balance.reserved_qty

P2 Option 2 — Work Orders FROM SO PATH 2 REAL

For assembly items needing production. Work Orders are created from the Sales Order (parent_so_id preserved) so records stay linked end-to-end. If the assembly is already in inventory, fulfill from stock and close the WO.
NS records
workorder · assemblybuild
Linkage
WO.parent_so_id → SO.id
HITL
/assembly-build.htmlproposed_actions → Mike approves
Alternate
if FG on hand → fulfill from inventory + close WO

P3 Option 3 — Purchase Orders FROM SO PATH 3 REAL

For drop-ship items. PO created from the Sales Order (parent_so_id preserved). Vendor ships product (direct to customer or crossdock). Item Receipt closes the PO line. A vendor-bill cycle runs separately on the vendor side.
NS records
purchaseorder · itemreceipt · vendorbill
Linkage
PO.parent_so_id → SO.id
Vendor side
vendor bill entered → paid per terms (separate from customer-side invoice cycle)

05 Item Fulfillment completed (converge) REAL

All 3 paths land here. Itemfulfillment closes; inventory decrements; BOL/ASN generated.
NS record
itemfulfillment (status='Shipped')
Tables write
transactions (ItemShip) · inventory_balance

06 ★ Automation alert → Finance REAL (concept) code path verify

The single named handoff between Operations and Finance. Fires automatically on every Item Fulfillment completion. Finance is the next-step owner.
Trigger
itemfulfillment.status → 'Shipped'
Action
NS workflow / scheduled script alerts Finance queue
STUB
actual NS workflow trigger config needs code-level verification

07 Finance review REAL

Finance checks fulfilled qty matches expected, pricing carried correctly, customer terms + tax handling correct, any short-ships flagged.
Tables read
itemfulfillment · so_lines · customers.terms

08 Invoice customer REAL

Finance posts CustInvc using shipped qty. AR balance updates.
NS record
CustInvc
Tables write
transactions (CustInvc) · invoice_lines · v_customer_ar_aging

09 Monitor payment terms · past-due → dunning REAL

Invoice stays open until payment is received. If past due, dunning fires via the ar_aging_action_plan workflow. Loops at 30/60/90+ days until paid or escalated to service hold.
View
v_customer_ar_aging
Workflow
ar_aging_action_plan
HITL
dunning email send still operator-confirmed

10 Payment received · apply · close REAL

Customer remits; CustPymt posted; payment_applications matches payment to invoice(s). SO closes; order.closed event fires to customer health watcher.
NS record
CustPymt
Tables write
customer_payments · payment_applications
Event
events.order.closed

P3+ Vendor-side cycle (drop-ship only) PATH 3 sidecar REAL

Runs in parallel to the customer-side invoice/payment. Vendor bill is entered against the PO and paid per vendor terms.
NS records
vendorbill · vendorpayment

Tables, endpoints, code paths

kindnamepurpose
Mailboxorders@globalfoodsolutions.coprimary customer order intake
Mailboxdanielle@globalfoodsolutions.cosecondary customer order intake
D1 tabletransactionsSalesOrd, WorkOrd, PurchOrd, ItemShip, ItemRcpt, CustInvc, CustPymt, VendBill rows. Note: these are NS SuiteQL transactions.type discriminator strings — for example transactions.type='ItemShip' selects Item Fulfillment records (whose SuiteScript record type is itemfulfillment, NS record name ItemFulfill). The discriminator string and the record name are distinct.
D1 tableso_lines / transaction_linesline-level SO data · item, qty, price, createdfrom → SO.id
D1 tablework_ordersPath 2 — WO records linked to parent SO
D1 tablepurchase_ordersPath 3 — PO records linked to parent SO
D1 tableitem_receiptsPath 3 — vendor receipt closes PO line
D1 tablevendor_billsPath 3 — vendor-side billing
D1 tableitem_fulfillmentsconvergence point — all 3 paths land here
D1 tableinvoice_linesFinance-issued invoice from shipped qty
D1 tablecustomer_invoicesCustInvc mirror
D1 tablecustomer_paymentsCustPymt mirror
D1 tablepayment_applicationsmatches payment to invoice(s)
D1 viewv_customer_ar_agingdunning trigger · buckets current/30/60/90+
Workflowar_aging_action_plandunning sequence at 30/60/90+
NS recordSalesOrd · WorkOrd · PurchOrd · ItemFulfill · ItemRcpt · CustInvc · CustPymt · VendBillsystem-of-record across the 3 paths + finance tail
Code pathsrc/email.tsinbound email pipeline (5 mailboxes incl. orders@ + danielle@)

Open gaps — honest punch list

Side-step · Freight routing check R594

After SO entry passes credit + product validation, before fulfillment, freight_routing_check fires. It classifies the SO's freight needs (LTL / FTL / parcel-with-special-handling / customer pickup / freight collect) and, when human routing is needed, routes the record to the logistics review queue. The logistics team picks the carrier, schedules pickup, generates BOL, captures tracking, and confirms delivery. Customer PO# threads through to the BOL so the customer can trace on their end.

Side-step in the SO flow (parallel with Item Fulfillment) · runs on all 3 SO paths (inventory, assembly, dropship) · HITL-gated. See ns-freight-routing-check.html + ns-logistics-review-flow.html.

Path detail docs