NetSuite freight routing check

SO entry OR PO creation → read freight fields → classify → assess special handling → estimate cost → flag for logistics → notify → write freight_status

A new check that fires automatically when a Sales Order or Purchase Order has freight relevance. Reads the standard NS body fields bodyFields.shipmethod, bodyFields.shipcarrier, bodyFields.shippingcost, bodyFields.shipdate, bodyFields.shipaddress, plus per-line lineFields.shippingcost. Classifies into one of six freight types (LTL / FTL / parcel / dropship vendor freight / customer pickup / freight collect), assesses special handling (refrigerated / frozen / hazmat / oversize), estimates cost from prior freight_lane_history, and routes the record onto the dedicated logistics review queue. The freight status is written to the D1-side freight_status_mirror table keyed by (source_record_type, source_record_id). Custom NS body fields custbody_freight_status and custbody_freight_classification are TBD pending Mike's review.

D1-mirrored from NS Auto-fires on SO + PO SO entry PO creation routes → logistics review custbody_* TBD pending Mike

Pipeline — freight check on SO + PO → logistics queue

idle
layers
WHAT THIS DOES: This is the ns freight routing check — so entry or po creation → freight relevance gate → classify type → assess special handling → estimate cost → flag for logistics review → notify logistics → write freight_status → dispatch into logistics_review_workflow step. It happens as part of the work-order / order-integration chain and produces the data, status change, or record described below. NS RECORD: see TECHNICAL DETAILS TECHNICAL DETAILS: NS freight routing check — SO entry OR PO creation → freight relevance gate → classify type → assess special handling → estimate cost → flag for logistics review → notify logistics → write freight_status → dispatch into logistics_review_workflow 01 / SO entry · ns-sales-order-master.html 01 / PO creation · ns-purchase-order-master.html 02 / Freight relevance gate (read standard NS body fields) 03 / Context load (lane history, special handling flags, address pair) 04 / Classify + assess + estimate (chat tool fan-out) 05 / Stage proposed action + notify + write status 06 / Dispatch → logistics_review_workflow (separate flow) WHAT THIS DOES: This is the so entry — trigger source 1 of 2. fires when a new sales order is entered with freight relevance. step. It happens as part of the work-order / order-integration chain and produces the data, status change, or record described below. NS RECORD: see TECHNICAL DETAILS TECHNICAL DETAILS: SO ENTRY — Trigger source 1 of 2. Fires when a new Sales Order is entered with freight relevance. NS BODY FIELDS READ bodyFields.shipmethod (e.g. "LTL", "FedEx Freight", "Customer Pickup") bodyFields.shipcarrier (e.g. "R+L Carriers") bodyFields.shippingcost (header) bodyFields.shipdate (target ship date) bodyFields.shipaddress / bodyFields.shipaddresslist bodyFields.otherrefnum (customer PO# — threads to freight_status_mirror.customer_po_number) LINE FIELDS READ lineFields.shippingcost (per line, when freight is line-allocated) SOURCE ns-sales-order-master.html / Path 1 inventory / Path 3 dropship STATUS: REAL · auto on SO save Sales Order entered (NS) bodyFields.shipmethod · shipcarrier bodyFields.shippingcost · shipdate · shipaddress otherrefnum = customer PO# (threads) DATABASE · transactions WHERE type='SalesOrd' i WHAT THIS DOES: This is the so lines read — per-line freight detail (line-allocated freight). step. It happens as part of the work-order / order-integration chain and produces the data, status change, or record described below. NS RECORD: see TECHNICAL DETAILS TECHNICAL DETAILS: SO LINES READ — Per-line freight detail (line-allocated freight). LINE FIELDS lineFields.shippingcost (per line) lineFields.item (drives special handling lookup) lineFields.quantity / lineFields.weight (TBD field availability) TABLES READ transaction_lines WHERE parent_id = ? (SO) NOTE When freight is header-only, line shippingcost is 0; classification uses bodyFields.shippingcost. STATUS: REAL SO lines read lineFields.shippingcost (per line) item · quantity · weight (TBD) drives special handling lookup DATABASE · transaction_lines i WHAT THIS DOES: This is the po creation — trigger source 2 of 2. fires when a new purchase order is created with freight relevance — especially dropship pos where vendor freight is on us. step. It happens as part of the work-order / order-integration chain and produces the data, status change, or record described below. NS RECORD: see TECHNICAL DETAILS TECHNICAL DETAILS: PO CREATION — Trigger source 2 of 2. Fires when a new Purchase Order is created with freight relevance — especially dropship POs where vendor freight is on us. NS BODY FIELDS READ bodyFields.shipmethod bodyFields.shipcarrier bodyFields.shippingcost (header — vendor freight charged back to GFS) bodyFields.shipdate (target receipt date) bodyFields.shipaddress (destination — customer site for dropship) bodyFields.memo (carries customer PO# on Path 1 SO-connected POs) LINE FIELDS READ lineFields.shippingcost (per line, when freight is per-line) SOURCE ns-purchase-order-master.html / PO Path 1 SO-connected (dropship) STATUS: REAL · auto on PO save Purchase Order created (NS) bodyFields.shipmethod · shipcarrier bodyFields.shippingcost · shipdate · shipaddress memo = customer PO# (Path 1 dropship) MESSAGEBUS · transactions WHERE type='PurchOrd' i WHAT THIS DOES: This is the po lines read — per-line freight on the po. step. It happens as part of the work-order / order-integration chain and produces the data, status change, or record described below. NS RECORD: see TECHNICAL DETAILS TECHNICAL DETAILS: PO LINES READ — Per-line freight on the PO. LINE FIELDS lineFields.shippingcost lineFields.item · lineFields.quantity TABLES READ transaction_lines WHERE parent_id = ? (PO) NOTE Dropship POs (Path 1) usually have vendor freight on bodyFields.shippingcost; inventory POs (Path 2) often have inbound freight on line. STATUS: REAL PO lines read lineFields.shippingcost item · quantity dropship vs inbound classification MESSAGEBUS · transaction_lines i WHAT THIS DOES: This is the freight relevance gate — block precondition. only fan out if freight applies. step. It happens as part of the work-order / order-integration chain and produces the data, status change, or record described below. NS RECORD: see TECHNICAL DETAILS TECHNICAL DETAILS: FREIGHT RELEVANCE GATE — Block precondition. Only fan out if freight applies. LOGIC IF bodyFields.shipmethod IS NOT NULL OR bodyFields.shipcarrier IS NOT NULL OR bodyFields.shippingcost > 0 OR ANY lineFields.shippingcost > 0 THEN proceed ELSE skip — pure pickup-at-counter or fully prepaid by customer SHORT CIRCUIT bodyFields.shipmethod = "Customer Pickup" → still log + flag, skip carrier select downstream STATUS: REAL · auto-gate freight relevance gate shipmethod | shipcarrier | shippingcost > 0 | line_shippingcost > 0 skip if none → no logistics review needed short-circuit: Customer Pickup → log + flag only PRECONDITION · block-severity i WHAT THIS DOES: This is the lane history lookup — prior freight on the same origin → destination zip pair. step. It happens as part of the work-order / order-integration chain and produces the data, status change, or record described below. NS RECORD: see TECHNICAL DETAILS TECHNICAL DETAILS: LANE HISTORY LOOKUP — Prior freight on the same origin → destination zip pair. SQL SELECT carrier, avg_cost, on_time_pct, last_used_at FROM freight_lane_history WHERE origin_zip = ? AND destination_zip = ? ORDER BY last_used_at DESC LIMIT 5 PURPOSE Feeds carrier suggestion + cost estimate in classify step. STATUS: REAL · new D1 table from migration 134 prior_freight_lane lookup freight_lane_history carrier · avg_cost · on_time_pct 5 most-recent rows per lane DATABASE · new in migration 134 i WHAT THIS DOES: This is the special handling flags — item-level attributes that change carrier selection. step. It happens as part of the work-order / order-integration chain and produces the data, status change, or record described below. NS RECORD: see TECHNICAL DETAILS TECHNICAL DETAILS: SPECIAL HANDLING FLAGS — Item-level attributes that change carrier selection. SQL SELECT item_code, refrigerated, frozen, hazmat, oversize FROM items WHERE item_code IN (lines on this SO/PO) FLAGS refrigerated → reefer LTL or temp-controlled parcel frozen → reefer FTL preferred hazmat → carrier hazmat cert required oversize → FTL or specialized handling STATUS: REAL · items table already mirrors NS special handling flags items.refrigerated · frozen · hazmat · oversize drives carrier qualifier list reefer · hazmat cert · oversize DATABASE · items lookup i WHAT THIS DOES: This is the address pair + customer/vendor — origin and destination plus the entity's freight terms. step. It happens as part of the work-order / order-integration chain and produces the data, status change, or record described below. NS RECORD: see TECHNICAL DETAILS TECHNICAL DETAILS: ADDRESS PAIR + CUSTOMER/VENDOR — Origin and destination plus the entity's freight terms. SQL SELECT id, name, billaddress, shipaddress FROM customers (SO) OR vendors (PO) WHERE id = ? ALSO prior freight_terms (PrePaid · Collect · 3rd Party · Prepaid Add) preferred_carrier (per customer/vendor preference if set) NOTE Drives whether GFS pays freight or invoices the customer/vendor for it. STATUS: REAL address pair + terms origin → destination zip pair freight_terms · preferred_carrier customer (SO) or vendor (PO) DATABASE · customers / vendors i WHAT THIS DOES: This is the customer po# capture — one trace field that threads through the freight chain. step. It happens as part of the work-order / order-integration chain and produces the data, status change, or record described below. NS RECORD: see TECHNICAL DETAILS TECHNICAL DETAILS: CUSTOMER PO# CAPTURE — One trace field that threads through the freight chain. SOURCE SO: bodyFields.otherrefnum (e.g. "72622") PO: bodyFields.memo (Path 1 SO-connected, threaded from parent SO) WRITE freight_status_mirror.customer_po_number = captured value PURPOSE Trace the freight record back to the customer PO# all the way through carrier, BOL, tracking, and delivery. STATUS: REAL · threading invariant customer PO# capture SO.otherrefnum OR PO.memo → freight_status_mirror .customer_po_number DATABASE · thread field i WHAT THIS DOES: This is the classify freight type — chat_tool: classify_freight_type step. It happens as part of the work-order / order-integration chain and produces the data, status change, or record described below. NS RECORD: see TECHNICAL DETAILS TECHNICAL DETAILS: CLASSIFY FREIGHT TYPE — chat_tool: classify_freight_type INPUTS shipmethod, shipcarrier, total_weight, line_count origin → destination distance, prior_freight_lane suggestions OUTPUT (one of 6) LTL — Less-than-truckload (palletized, < 10K lbs) FTL — Full truckload (full trailer, 10K+ lbs OR exclusive use) parcel — Small package (UPS / FedEx / USPS) dropship_vendor_freight — vendor handles outbound; GFS pays back customer_pickup — buyer arranges; no carrier select freight_collect — buyer-pays; carrier billed to buyer's account WRITES freight_status_mirror.freight_classification = <type> STATUS: REAL · tool fan-out classify_freight_type LTL · FTL · parcel · dropship_vendor_freight customer_pickup · freight_collect shipmethod + weight + distance + lane history SECURITY · chat_tool fan-out · 6-class enum writes freight_status_mirror.freight_classification i WHAT THIS DOES: This is the assess special handling — chat_tool: assess_freight_special_handling step. It happens as part of the work-order / order-integration chain and produces the data, status change, or record described below. NS RECORD: see TECHNICAL DETAILS TECHNICAL DETAILS: ASSESS SPECIAL HANDLING — chat_tool: assess_freight_special_handling INPUTS per-line items + their refrigerated / frozen / hazmat / oversize flags OUTPUT { refrigerated: bool, frozen: bool, hazmat: bool, oversize: bool } EFFECT - any flag true → carrier shortlist filters to qualified carriers - hazmat → adds HazMat fee to cost estimate - frozen → forces reefer (temperature-controlled) carrier WRITES freight_status_mirror.special_handling_json = { ... } STATUS: REAL · tool fan-out assess_freight_special_handling refrigerated · frozen · hazmat · oversize filters carrier shortlist forces reefer if frozen · adds HazMat fee SECURITY · chat_tool fan-out writes freight_status_mirror.special_handling_json i WHAT THIS DOES: This is the estimate freight cost — chat_tool: estimate_freight_cost step. It happens as part of the work-order / order-integration chain and produces the data, status change, or record described below. NS RECORD: see TECHNICAL DETAILS TECHNICAL DETAILS: ESTIMATE FREIGHT COST — chat_tool: estimate_freight_cost INPUTS classification, special_handling, weight, lane (origin → dest zip) prior freight_lane_history (avg_cost on this lane) carrier rate cards if integrated (TBD which carriers we have rate-card access to) OUTPUT estimated_cost (number) freight_cost_finalized = 0 (flagged for logistics review to lock down actual) FALLBACK No lane history + no rate card → flag for manual quoting (logistics calls carriers) WRITES freight_status_mirror.estimated_cost = <number> STATUS: REAL (with manual-quote fallback for new lanes) estimate_freight_cost classification + special_handling + lane history rate cards if integrated · else manual quote freight_cost_finalized = 0 (lock at review) SECURITY · chat_tool fan-out · manual fallback writes freight_status_mirror.estimated_cost i WHAT THIS DOES: This is the flag for logistics review — stage_proposed_action with action_type=freight_logistics_review step. It happens as part of the work-order / order-integration chain and produces the data, status change, or record described below. NS RECORD: see TECHNICAL DETAILS TECHNICAL DETAILS: FLAG FOR LOGISTICS REVIEW — stage_proposed_action with action_type=freight_logistics_review PAYLOAD source_record_type, source_record_id, customer_po_number classification, special_handling_json, estimated_cost origin/destination, target ship date WRITES proposed_actions (status='pending') · risk_level=2 DOWNSTREAM logistics-review.html UI surfaces this queue STATUS: REAL flag for logistics review stage_proposed_action(freight_logistics_review) classification + special handling + estimated cost surfaces on /logistics-review.html queue BACKEND · proposed_actions write i WHAT THIS DOES: This is the notify logistics — hitl_email_draft (template: logistics_review_inbound) step. It happens as part of the work-order / order-integration chain and produces the data, status change, or record described below. NS RECORD: see TECHNICAL DETAILS TECHNICAL DETAILS: NOTIFY LOGISTICS — hitl_email_draft (template: logistics_review_inbound) DRAFTS Subject: "New freight item on review queue — SO #1217 / customer PO 72622" Body: classification, special handling, cost estimate, target ship date, queue link TO logistics team distribution (TBD — logistics@globalfoodsolutions.co expected) HITL Mike (or logistics lead once delegated) approves before send. STATUS: REAL (draft) · HITL approval still required for send notify logistics hitl_email_draft · template logistics_review_inbound to logistics@globalfoodsolutions.co (TBD) draft staged for HITL approval before send CLOUD · email draft + HITL gate i WHAT THIS DOES: This is the write freight_status = pending_logistics_review — d1_write to freight_status_mirror step. It happens as part of the work-order / order-integration chain and produces the data, status change, or record described below. NS RECORD: see TECHNICAL DETAILS TECHNICAL DETAILS: WRITE freight_status = pending_logistics_review — d1_write to freight_status_mirror SQL INSERT OR REPLACE INTO freight_status_mirror (source_record_type, source_record_id, freight_status, freight_classification, special_handling_json, estimated_cost, customer_po_number, created_at, updated_at) VALUES (?, ?, 'pending_logistics_review', ?, ?, ?, ?, datetime('now'), datetime('now')) TBD — NS WRITE-BACK Once Mike confirms custbody_freight_status field on SO/PO, also push back to NS via ns_pending_pushes. STATUS: REAL on D1 · STUB on NS push (pending custbody_* confirmation) write freight_status = pending_logistics_review d1_write · freight_status_mirror (UPSERT) customer_po_number threads NS write-back STUB · custbody_freight_status TBD BACKEND · D1 write · NS push pending i WHAT THIS DOES: This is the dispatch → logistics_review_workflow — workflow_class_invoke (separate flow) step. It happens as part of the work-order / order-integration chain and produces the data, status change, or record described below. NS RECORD: see TECHNICAL DETAILS TECHNICAL DETAILS: DISPATCH → logistics_review_workflow — workflow_class_invoke (separate flow) TARGET logistics_review_workflow (risk 2) PAYLOAD HANDED OFF source_record_id, source_record_type, classification_from_check, special_handling, estimated_freight_cost, target_ship_date SEPARATE FLOW Carrier select → schedule pickup → BOL → tracking → delivery confirm. Logistics team operates that flow on their dashboard. EVENT FIRED freight.routed_to_logistics (source_record_type, source_record_id, classification) STATUS: REAL · contract in migration 134 ★ dispatch → logistics_review_workflow workflow_class_invoke · hands off classification + cost + special handling fires event freight.routed_to_logistics MESSAGEBUS · see ns-logistics-review-flow.html i SO ↔ WO SO ↔ WO step step next step next step next step next step key flow key flow key flow key flow step step step step step step LEGEND SO trigger PO trigger Decision gate Logistics output chat_tool fan-out FREIGHT FIELD MAP · what the check reads vs writes (sample: SO #1217, customer PO 72622) NS body fields (read) shipmethod · shipcarrier · shippingcost shipdate · shipaddress · otherrefnum/memo SO + PO header fields NS line fields (read) lineFields.shippingcost (per line) item · quantity · weight (TBD) transaction_lines join D1 freight_status_mirror (write) freight_status · classification special_handling_json · estimated_cost customer_po_number threads NS custbody_* (write — TBD) custbody_freight_status custbody_freight_classification pending Mike review key flow key flow step
Legend · color codes + icons used in this diagram
Color codes:
backend / NS record
work order / SO link
finance / invoice
TBD / escalation
cloud / worker
external / generic
Icon meanings:

Phase detail — what the check does

01a SO entry trigger SO source REAL

Fires when a new Sales Order is saved in NS with freight relevance. Reads header + line freight fields.
NS body fields
bodyFields.shipmethod · bodyFields.shipcarrier · bodyFields.shippingcost · bodyFields.shipdate · bodyFields.shipaddress · bodyFields.otherrefnum (customer PO# threading)
NS line fields
lineFields.shippingcost
Source diagrams

01b PO creation trigger PO source REAL

Fires when a new PO is created. Especially relevant for dropship POs where vendor freight is charged back to GFS.
NS body fields
same set as SO + bodyFields.memo (carries customer PO# on Path 1 SO-connected POs)
NS line fields
lineFields.shippingcost
Source diagrams

02 Freight relevance gate REAL · block precondition

Only proceed if at least one freight signal is present. Skip if pure counter pickup or fully prepaid customer freight with no carrier involvement.
Logic
shipmethod IS NOT NULL OR shipcarrier IS NOT NULL OR shippingcost > 0 OR any line_shippingcost > 0
Short-circuit
shipmethod = "Customer Pickup" → log + flag, skip carrier-select downstream

03 Context load REAL

Load 4 context surfaces before classifying: lane history, special handling flags, address pair + terms, and customer PO# thread.
Lane history
freight_lane_history WHERE origin_zip = ? AND destination_zip = ?
Special handling
items.refrigerated · frozen · hazmat · oversize
Terms + carrier pref
customer (SO) or vendor (PO) freight_terms · preferred_carrier
PO# thread
freight_status_mirror.customer_po_number = SO.otherrefnum OR PO.memo

04 Classify + assess + estimate (3 chat tools in parallel) REAL · tool fan-out

Three chat tools run in parallel: classify the freight type, assess special handling, estimate cost.
classify_freight_type
LTL / FTL / parcel / dropship_vendor_freight / customer_pickup / freight_collect
assess_freight_special_handling
refrigerated · frozen · hazmat · oversize
estimate_freight_cost
lane history + rate cards (TBD which carriers integrated) → estimated_cost · fallback flag for manual quote

05 Stage proposed action + notify + write status LOGISTICS OUTPUT REAL NS push STUB

Three side effects: stage the routing decision into proposed_actions, draft a notify email to logistics, write freight_status.
Stage action
proposed_actions (action_type='freight_logistics_review', status='pending')
Notify draft
hitl_email_draft (template=logistics_review_inbound) — HITL approve before send
D1 write
freight_status_mirror.freight_status = 'pending_logistics_review'
NS write (TBD)
custbody_freight_status + custbody_freight_classification pending Mike review

06 ★ Dispatch → logistics_review_workflow HANDOFF REAL

Hand off to the dedicated logistics review flow. Logistics team operates carrier select / pickup schedule / BOL / tracking / delivery confirm on their dashboard.
Target workflow
logistics_review_workflow (risk 2)
Event fired
freight.routed_to_logistics (source_record_type, source_record_id, classification)
Detail diagram

Tables, endpoints, code paths

kindnamepurpose
D1 tabletransactionsSO + PO source records · reads shipmethod, shipcarrier, shippingcost, shipdate, shipaddress, otherrefnum, memo
D1 tabletransaction_linesper-line shippingcost, items + qty for special handling lookup
D1 tableitemsrefrigerated / frozen / hazmat / oversize flags
D1 tablecustomers · vendorsfreight_terms, preferred_carrier, billing/shipping addresses
D1 tablefreight_status_mirrorNEW (migration 134) — freight_status keyed by (source_record_type, source_record_id)
D1 tablefreight_lane_historyNEW (migration 134) — prior carrier + cost + on-time per origin→dest zip pair
D1 tableproposed_actionsHITL queue — action_type='freight_logistics_review'
D1 tableeventsfreight.routed_to_logistics + workflow.completed
Workflow contractfreight_routing_checkthis check · risk 2 · contract_version 2
Workflow contractlogistics_review_workflowdownstream · risk 2 · contract_version 2
NS field (read)bodyFields.shipmethod · shipcarrier · shippingcost · shipdate · shipaddress · otherrefnum · memostandard NS freight fields on SO + PO
NS field (read)lineFields.shippingcostper-line freight when line-allocated
NS field (write, TBD)custbody_freight_status · custbody_freight_classificationpending Mike review — expected names

Open gaps — honest punch list

Related docs