For an ordinary Sales Order with one header shipping address, read shipaddresslist through N/record and compare it with internalid on that customer’s addressbook sublist. Require exactly one matching ID, then copy the customer and address IDs into stored custom fields for reporting. Do not choose an address by matching its street text.
The transaction’s shippingaddress subrecord is its shipping snapshot. Its internal ID is not a substitute for the selected customer address-book reference. A field exposed through a Customer search join also does not prove that the same join is available in a Transaction search.
Before you start
This walkthrough uses existing Sales Orders with a single header ship-to. Multiple Shipping Routes, line-level shipping, invoices, fulfillments and historical address reconciliation need separate designs.
Two stored Free-Form Text transaction body fields already apply to Sales Orders and appear on Shipping:
- Ship-to Customer ID:
custbody_shipto_customer_id - Ship-to Address Book ID:
custbody_shipto_address_id
The JavaScript workbench executes the visible source against a local API model. It has no NetSuite connection. Test the selected-reference relationship in your target account and release, with representative custom, missing, duplicate and inaccessible addresses. A deployed script needs edit permission for the orders and custom fields. Real submitFields calls can trigger account-specific workflows, user events and other automation.
1. Compare the address-book entries
Open Northgate Fabrication > Address. Customer 6101 has North Dock, ID 4101, and South Dock, ID 4102. Both contain the same address text. The IDs identify the entries; neither street text nor a label is a safe universal match key.
The example enables Show Internal IDs. Your role, preferences and form can affect which columns appear.
2. Inspect the selected ship-to and initial report
Open SO7201 > Shipping. Ship To Select is South Dock. Its underlying selected address-book reference is 4102; both capture fields start blank.
Run Sales Order Ship-to References. Both SO7201 and SO7202 start with blank captured fields. SO7202 uses a custom shipping address whose text happens to match the customer’s saved addresses.
3. Validate the reference before writing custom fields
Review capture_shipto_reference.js in the local workbench. The example:
- Skips Multiple Shipping Routes.
- Reads
entityandshipaddresslist, normalizes them to strings and requires positive IDs. - Loads the selected customer and checks
addressbook.internalidwith zero-based sublist indexes. - Requires exactly one matching ID. Missing and duplicate matches are exceptions to review.
- Writes only the two configured custom fields with
record.submitFields.
The sublist line index is not the address ID. The comparison uses the internalid value returned from that line.
Click Run local example for selected Sales Order IDs 7201, 7202. Confirm CAPTURED 7201: 6101 - 4102, SKIP 7202 for its custom or unresolved selector, and Updated: 1 · Unchanged: 1.
4. Reopen both orders
Reopen SO7201 > Shipping. Ship-to Customer ID is 6101, Ship-to Address Book ID is 4102, and South Dock remains selected.
Open SO7202 > Shipping. Its selector remains - Custom - and both capture fields remain blank. Matching address text does not establish an address-book relationship.
5. Build an informational display key
Open the Transaction search criteria. Restrict Type to Sales Order and Main Line to true. Keep the two stored custom-field result columns.
On Results, add Formula (Text). Open its formula editor and enter:
CASE
WHEN {custbody_shipto_address_id} IS NOT NULL
AND {custbody_shipto_customer_id} IS NOT NULL
THEN {custbody_shipto_customer_id}
|| ' - ' || {custbody_shipto_address_id}
END
Set the custom label to Customer - Address Key, add the result column, then Save & Run. SO7201 reports 6101 - 4102. SO7202 has no captured customer, address or display key.
The combined value is an informational display key, not a native foreign-key field or a join to the address book. Do not use it as an accounting or fulfillment control. If users can manually edit these fields, add validation for malformed or whitespace-only values.
Common questions
Why not use shippingaddress.internalid?
A transaction’s shipping-address snapshot and the customer’s selected address-book entry have different purposes. For this single-header workflow, read shipaddresslist and validate it against the selected customer’s addressbook.internalid.
Can I use Address 1 or the address label to find the ID?
Text and labels can repeat or change. This example deliberately gives two saved addresses identical text. The selected reference identifies South Dock without choosing the first text match.
Is shipaddresslist available directly in a saved-search formula?
This walkthrough reads it through N/record. It does not establish direct saved-search field availability. The report uses the two stored custom fields instead.
What happens for Custom addresses or Multiple Shipping Routes?
The example skips them. A custom address can match saved text without being a saved address-book selection. Multiple Shipping Routes requires line-level handling beyond this header-only script.
Do these captured fields update automatically?
No. If the customer or selected address changes, refresh or clear them through a separate controlled process. A skipped row can retain an earlier stale capture. Consider a status or last-checked timestamp for operational use.
Does a captured ID prove the current address matches a historical shipment?
No. The customer address can be edited or removed after capture. The stored identifiers do not reconcile historical shipping text with the current customer record.
Supporting references: Sales Order shipping-address selection and customer address IDs and Show Internal IDs. The second reference discusses Multiple Shipping Routes; this lesson uses only its address-ID visibility guidance.