NetSuite sales order lifecycle

SO intake → credit → pick / pack / ship → invoice → payment → AR aging · 11 phases

Order-to-cash is the heart of the business. This pipeline traces a sales order from intake (manual / email / EDI / portal) through customer + credit validation, inventory check, pricing application, approval, pick + pack + ship, invoice, payment, AR aging, and finally the customer-health signal that feeds churn prediction. $15K average order value; bid-driven; K-12 + USDA + NYC schools dominant.

D1-mirrored from NS HITL outside guardrails EDI intake STUB

Pipeline — 11 phases, left to right (two rows)

idle
NS sales order lifecycle — SO intake → customer validation → inventory check → pricing → approval → pick → pack + ship → invoice → payment → AR aging → customer health signal 01 / Intake 02 / Customer 03 / Inventory 04 / Pricing 05 / Approval 06 / Pick 07 / Pack+Ship 08 / Invoice 09 / Payment 10 / AR aging 11 / Health SO INTAKE — Sales orders arrive via four channels. Manual NS UI is most common; email/portal/EDI being expanded. SOURCE manual: NS UI direct entry email: orders@ai-globalfoodsolutions.co → src/email.ts edi: 850 from K-12/NYC DOE → STUB autoparse portal: customer portal upload form TABLES write: transactions (SalesOrd) · so_lines STATUS manual+email: REAL edi: STUB portal: REAL SO intake manual · email EDI · portal 4 channels EXTERNAL · STUB EDI transactions (SalesOrd) i CUSTOMER VALIDATION — Lookup customers row, check credit_limit, check hold_status, enforce service hold rules. CHECKS customers.id_exists credit_limit vs current AR balance hold_status ∈ allowed service_hold flags TABLES read: customers · v_customer_ar_aging on_fail: block + propose_action STATUS: REAL customer validation credit_limit check hold_status check service hold check DATABASE · customers i INVENTORY CHECK — Per so_lines.item, validate quantityavailable at the fulfillment location. Short-pick flags raised; backorder logic surfaces. ACTION per_line: inventory_balance.quantityavailable ≥ so_qty backorder: stage if short TABLES read: inventory_balance · so_lines write: so_lines.backorder_flag STATUS: REAL inventory check qty_available ≥ so_qty per line backorder flag DATABASE · so_lines i PRICING APPLICATION — Lookup pricing_master + customer_programs to apply the right tier and discounts. Compute line margin and roll up to order margin. LOOKUPS pricing_master (item × effective_date) customer_programs (customer × item × override) contract overrides ACTION apply: tier_price OR program_price OR contract_price margin: (price - cost) / price TABLES read: pricing_master · customer_programs · contracts STATUS: REAL pricing pricing_master customer_programs margin computed BACKEND · pricing-cascade i SO APPROVAL — If margin < guardrail OR order_value > auto_threshold OR new customer, status='Pending Approval'. Otherwise auto-approve. GUARDRAILS margin_floor: 12% auto_threshold: $25,000 new_customer: always_review HITL proposed_actions · action_type='so_approval' TABLES write: transactions (status flip) · proposed_actions STATUS: REAL · risk 2-3 approval gate margin < 12% → HITL $>25K → HITL new cust → HITL SECURITY · risk 2-3 i PICK — Pick list generated at warehouse. NS itemfulfillment record opens with status='In Progress'. ACTION generate: pick_list per warehouse ns_record: itemfulfillment (open) TABLES write: transactions (ItemShip-pick) SURFACES warehouse pick form STATUS: REAL pick pick list generated itemfulfillment open warehouse staff FRONTEND · pick form i PACK + SHIP — Fulfillment record closes; itemfulfillment status='Shipped'. Inventory decremented. BOL + ASN generated. ACTION status: itemfulfillment → 'Shipped' inventory: decrement generate: BOL · ASN if EDI customer TABLES write: transactions (ItemShip) · inventory_balance STATUS: REAL pack + ship itemfulfillment closed inventory decremented BOL + ASN BACKEND · ItemShip i INVOICE — invoice_lines generated from so_lines using shipped qty (not ordered qty). CustInvc posted; AR balance updates. ACTION generate: invoice_lines per shipped so_line post: CustInvc transaction TABLES write: transactions (CustInvc) · invoice_lines recompute: v_customer_ar_aging STATUS: REAL invoice CustInvc posted invoice_lines shipped qty BACKEND · CustInvc i PAYMENT — Customer remits; CustPymt posted. payment_applications row matches the payment to one or more invoices. ACTION receive: customer_payments row apply: payment_applications (payment → invoice) TABLES write: customer_payments · payment_applications · transactions (CustPymt) STATUS: REAL payment CustPymt posted customer_payments payment_applications DATABASE · CustPymt i AR AGING — v_customer_ar_aging view recomputes from invoice + payment activity. Surfaces buckets: current, 30, 60, 90+. ACTION recompute: v_customer_ar_aging BUCKETS current · 1-30 · 31-60 · 61-90 · 91+ SURFACES customer entity page · admin-dashboard finance tile STATUS: REAL AR aging view recomputed current · 30 · 60 · 90+ finance tile DATABASE · v_*_aging i CUSTOMER HEALTH — order_velocity_decline baseline updates. customer_health_predictor model recomputes churn risk. Signal surfaces to chat tools + admin-dashboard. ACTION update: order_velocity baseline (rolling 90d) recompute: customer_health_score fire: events.customer.health_changed TABLES write: customer_health · events SURFACES /customer/<slug> · admin-dashboard health tile · chat get_customer_health STATUS: REAL (R549-R564 substrate) customer health velocity baseline churn score events fire CLOUD · health_predictor i pick complete → ship the load health score feeds next SO's pricing tier + credit check LEGEND Intake D1 / view Backend HITL Frontend Cloud / model

Phase detail — 11 phases

01 SO intake manual+email+portal REAL EDI STUB

Four channels: NS UI, inbound email, EDI 850, customer portal upload. EDI autoparse not yet wired.
Email
orders@ai-globalfoodsolutions.cosrc/email.ts
Tables write
transactions (SalesOrd) · so_lines
STUB
EDI 850 ingestion not yet auto-routed

02 Customer validation REAL

Verifies the customer exists, has credit headroom, and is not on service hold.
Tables read
customers · v_customer_ar_aging
Checks
credit_limit · hold_status · service_hold flags

03 Inventory check REAL

Per-line availability check; short rows flagged as backorder candidates.
Tables read
inventory_balance · so_lines
Tables write
so_lines.backorder_flag

04 Pricing application REAL

Pricing cascade resolves tier → program → contract overrides; margin computed per line.
Tables read
pricing_master · customer_programs · contracts
Cascade
tier → program → contract (most-specific wins)

05 SO approval gate risk 2-3

Margin floor, order-value ceiling, and new-customer flag drive HITL.
Guardrails
margin_floor 12% · auto_threshold $25,000 · new_customer always_review
Surface
/proposed-actions.html
Tables write
proposed_actions · transactions (status flip)

06 Pick REAL

Pick list generated; itemfulfillment opens In Progress.
NS record
itemfulfillment
D1 table
transactions (ItemShip-pick stage)

07 Pack + ship REAL

Fulfillment closes; inventory decrements; BOL + ASN generated.
NS record
itemfulfillment (status='Shipped')
Tables write
transactions (ItemShip) · inventory_balance

08 Invoice REAL

CustInvc posted using shipped qty (not ordered qty). invoice_lines mirror so_lines.
NS record
CustInvc
Tables write
transactions (CustInvc) · invoice_lines

09 Payment REAL

CustPymt posted; payment_applications ties payment to invoice(s).
NS record
CustPymt
Tables write
customer_payments · payment_applications

10 AR aging REAL

v_customer_ar_aging recomputes. Buckets surface on the customer entity page and finance tile.
View
v_customer_ar_aging
Buckets
current · 1-30 · 31-60 · 61-90 · 91+
Surfaces
/customer/<slug> · admin-dashboard finance tile

11 Customer health signal REAL · substrate

order_velocity_decline baseline updates (rolling 90d); customer_health_predictor recomputes churn risk. Feeds back into next SO's credit + pricing gate.
Tables write
customer_health · events
Event
events.customer.health_changed
Surfaces
/customer/<slug> · admin-dashboard health tile · chat get_customer_health
Code path
R549-R564 substrate · customer_health_predictor

Tables, endpoints, code paths

kindnamepurpose
D1 tabletransactionsSalesOrd, ItemShip, CustInvc, CustPymt rows
D1 tableso_linesline-level SO data · item, qty, price, backorder_flag
D1 tableinvoice_linesgenerated from so_lines using shipped qty
D1 tablecustomer_paymentspayment receipts · CustPymt mirror
D1 tablepayment_applicationsmatches payment to invoice(s)
D1 tablecustomerscredit_limit, hold_status, service_hold
D1 tablepricing_mastertier price · effective_date
D1 tablecustomer_programscustomer-specific overrides
D1 viewv_customer_ar_agingbuckets · current / 30 / 60 / 90+
D1 tablecustomer_healthscore, velocity baseline, churn_risk
D1 tableeventscustomer.health_changed event ledger row
NS recordSalesOrdsystem-of-record SO
NS recorditemfulfillmentpick + ship
NS recordCustInvcinvoice
NS recordCustPymtpayment
EndpointPOST /api/so/createorchestrates intake through pricing
EndpointPOST /api/so/approveHITL approval flip
EndpointGET /api/customer/{slug}/healthcustomer health surface
Code pathsrc/email.tsemail intake
Code pathsrc/index.ts (pricing-cascade)tier + program + contract resolution
Code pathcustomer_health_predictorR549-R564 substrate

Open gaps — honest punch list