Sample output from the Transaction Entry Performance Audit prompt in the Sonar AI Prompt Library, run against a NetSuite test account. Every name and number here is test data. Back to the post · The library

Sales Order Entry Performance Audit

Account: TD3016323 (Production, OneWorld)  ·  Transaction type: Sales Order  ·  Date: 2026-07-02  ·  Audited by: Timothy Dietrich (role id 3), via Sonar AI  ·  Mode: Read-only — no records, scripts, deployments, or settings were modified.

1. Executive Summary

Verdict: DEGRADED. Sales order entry in this account carries a heavy synchronous customization load: 13 active script deployments (7 client scripts, 6 user events) fire on every sales order, all deployed to every role. The single largest identified cost is a shipping-bundle client script that executes two database queries from the browser on every page load and again on field changes, with no caching. Remediating the top three findings below — caching the Packship preference lookup, narrowing deployment audiences, and reviewing the four unreadable bundle user events — is expected to measurably improve form-open and per-line entry time for sales roles.
LayerStatusSummary
User Event scripts (form open / save)MEDIUM6 active UEs run beforeLoad on every open; 4 of 6 have hidden source (bundle-protected) and could not be code-reviewed.
Client scripts (open / per-line)CRITICAL7 active client scripts; Packship CS runs uncached N/query round-trips on pageInit and fieldChanged.
WorkflowsGOODZero active workflows initiate on Sales Order create/view/update.
Custom field surfaceMEDIUM56 custom fields visible on SO (31 body, 25 line-level; 15 sourced line fields interact with client-script events).
Execution-log heatLIMITEDNo scriptnote entries exist for the 13 SO scripts — log evidence unavailable (levels above DEBUG or purged).
Bundle footprintMEDIUM4 bundles contribute 9 of 13 deployments; several are shipping/fulfillment features running on the sales-entry hot path.

2. Methodology

This audit followed the Sonar Transaction Entry Performance Audit protocol, six phases, all read-only:

  1. Phase 0 — Environment snapshot (account, role, features).
  2. Phase 1 — Script inventory: SuiteQL against scriptdeploymentscript for recordtype='SALESORDER'.
  3. Phase 2 — Static code analysis: pattern scans (fileGrep) of each readable source file for known anti-patterns.
  4. Phase 3 — Workflow analysis: all active released workflows, trigger types, and target record types.
  5. Phase 4 — Custom field surface: customfield rows whose visibleontransactions includes SalesOrd.
  6. Phase 5 — Execution-log heat: scriptnote volumes for the Phase-1 script ids.
  7. Phase 6 — Bundle attribution: script.frombundle + API version per script.

Every claim is tagged: MEASURED backed by account data · OBSERVED seen in actual source code · HYPOTHESIS plausible, unconfirmed, with the confirming step stated.

3. Environment Snapshot (Phase 0)

ItemValue
Account / environmentTD3016323 — PRODUCTION
OneWorldYes (multi-subsidiary; multi-currency OFF)
Relevant featuresInventory, Multi-Location Inventory, Matrix Items, Work Orders, Advanced Printing, CRM, Estimates
Auditing roleRole id 3 (broad read access; some bundle files inaccessible — see Concerns)

4. Findings

Phase 1 — Script inventory MEASURED

13 active deployments (status RELEASED, isdeployed=T) on Sales Order. All 13 are deployed to all roles (allroles=T). Two further deployments exist but are switched off (ATB_UE_SalesOrder, Packship Non-Adv-Inventory UE) — correctly excluded from cost.

ScriptscriptidTypeAPIBundleCost moment
ATB_CS_SalesOrdercustomscript_atb_cs_salesorderCLIENT2.1— (custom)open, per-line (validateLine)
Item Substitute Transactions CScustomscript_scm_is_transactions_csCLIENT2.047193open, per-line
LRC Field Manager Client Scriptcustomscript_lrc_field_manager_csCLIENT2.1— (custom)fieldChanged (subsidiary only)
Packship — Process on IF Order CScustomscript_packship_cs_order_ifprocessCLIENT2.1534418open + fieldChanged (queries!)
SCM Transactions CScustomscript_scm_cpn_cs_transactionsCLIENT1.047193open, per-field
STE CS Transactioncustomscript_ste_cs_transactionCLIENT2.0237702 (tax engine)open, per-line, save
USR CS Transactioncustomscript_usr_cs_transactionCLIENT2.1— (minified)unknown (minified)
Item Substitute Transactions UEcustomscript_scm_is_transactions_ueUSEREVENT2.047193open, save — source hidden
LRC Field Manager User Eventcustomscript_lrc_field_manager_ueUSEREVENT2.1— (custom)open (light)
RAC UE Sales Order Recordcustomscript_rac_ue_so_recordUSEREVENT2.0266623open, save — source hidden
SCM Transactions UEcustomscript_scm_cpn_ue_transactionsUSEREVENT1.047193open, save — source hidden
STE UE Transactioncustomscript_ste_ue_transactionUSEREVENT2.0237702 (tax engine)open, save
USR UE Transactioncustomscript_usr_ue_transactionUSEREVENT2.1open, save — source hidden

Phase 2 — Static code analysis

CRITICAL Packship client script runs uncached database queries on every page load and field change OBSERVED

Script: customscript_packship_cs_order_ifprocess · File: packship_cs_order.js (id 24196) · Bundle 534418 · Affects: form open + per-field entry · Effort: Moderate (vendor code — see Concerns)

pageInit calls disableOrEnableProcessShipmentOnIFFlag(), which calls getShipCentralPreference() — a full N/query execution against customrecord_packship_shippreference (~20 columns, several with FieldContext.DISPLAY, each a joined lookup) — from the browser, synchronously, on every sales order open. The same routine re-runs on every change to shipmethod, subsidiary, or location, and each shipmethod evaluation triggers a second query (getMigrationCarrierOrNotfetchDataFromQuery). No result caching anywhere.

File 24196, lines 8–14:
    const pageInit = (scriptContext) => {
        disableOrEnableProcessShipmentOnIFFlag(scriptContext);   // ← query on EVERY open
    }
    const fieldChanged = (scriptContext) => {
        if(['shipmethod', 'subsidiary', 'location'].includes(scriptContext.fieldId))
            disableOrEnableProcessShipmentOnIFFlag(scriptContext); // ← query again

File 24196, lines 149–150, 243:
    const getShipCentralPreference = () => {
        var shipPrefQuery = query.create({ type: 'customrecord_packship_shippreference' });
        ...
        return shipPrefQuery.run().asMappedResults();   // ← uncached round-trip

Remediation: cache the preference result in a module-scope variable after the first fetch (preferences don't change mid-session). Because this is managed-bundle code, the fix is a vendor request; the immediate mitigation is narrowing the deployment audience to fulfillment roles that actually use Ship Central (see next finding).

HIGH All 13 deployments target every role MEASURED

Evidence: scriptdeployment.allroles = 'T' on all 13 active rows · Affects: open + per-line + save for all users · Effort: Trivial (config)

Every user who opens a sales order — sales rep, accountant, executive — executes the full stack, including shipping/fulfillment logic (Packship) that only warehouse flows need. Narrowing Applies To → Roles on non-universal deployments is the highest-leverage zero-code fix available.

MEDIUM SCM (bundle 47193) scripts are SuiteScript 1.0 with module-load side effects OBSERVED

Scripts: customscript_scm_cpn_cs_transactions / _ue_transactions · File: WD_SCM_CPN_CS_Transactions.js (id 5015) · Effort: Significant (vendor)

The client script initializes a dictionary at pageInit and executes SCM.CPN.Transactions_CS.init() at file-load time (line 93 — comment says it must run "because workflow's BeforeUserEdit happens before client script's pageInit"). SS1.0 code paths (nlapi*) are synchronous by design. The paired UE's source is bundle-hidden, so its beforeLoad cost is unverified.

MEDIUM Four of six user-event sources could not be code-reviewed HYPOTHESIS

Files: 5021 (Item Substitute UE), 5899 (RAC UE), 5093 (SCM UE), 24736 (USR UE) — "You do not have access to the media item" · Effort: n/a (visibility)

These four run beforeLoad on every sales order open, and their contents are hidden (bundle-protected or restricted). Their aggregate cost is unknown — it could be trivial or it could be the dominant term. Confirming step: NetSuite APM's Page Time Summary attributes wall-clock per script without needing source access. Additionally, USR CS Transaction (file 24710) is minified (8 lines / 21 KB) and its entry points could not be pattern-matched.

LOW Oracle tax-engine (STE, bundle 237702) dispatchers fan out on every client event OBSERVED

Files: ste_ue_transaction.js (7568), ste_cs_transaction.js (7620) · Effort: n/a (leave as is)

The STE UE/CS are dispatcher shims that loop over sub-modules (custom-field lookup + prompt-payment discount) for beforeLoad, pageInit, fieldChanged, postSourcing, validateLine, and saveRecord. The dispatcher itself is clean; the beforeLoad adds a custpage_allnexuses form field. Bounded cost, required for tax; no action recommended.

INFO ATB_CS_SalesOrder routes all events through a controller + "SalesOrderGateway" HYPOTHESIS

File: ATB_CS_SalesOrder.js (15869) · custom, API 2.1

TypeScript-compiled controller pattern with pageInit, validateField, lineInit, validateLine. The imported SalesOrderGateway name suggests server communication; whether it fires per line was not confirmed in this pass. Confirming step: read the gateway module or profile with APM.

GOOD LRC Field Manager scripts are lightweight OBSERVED

Files: lrcfm_user_event.js (24576), lrcfm_client_script.js (90318)

UE beforeLoad does logging + field-visibility management only; client fieldChanged exits unless the changed field is subsidiary. Well-scoped, no searches, no loads.

Phase 3 — Workflows MEASURED

GOOD No active workflows initiate on Sales Order

All 10 active released workflows were enumerated with their trigger types and target record types. None target Sales Order. (Note: "Default Promise Date" — customworkflow_atlas_promise_date_dflt — targets the Purchase Order family per recordtypes=-106 and its companion field's visibility; an earlier informal pass had provisionally associated it with SO entry. The audit corrects that: zero workflow cost on SO.)

Phase 4 — Custom field surface MEASURED

Field typeVisible on SOSourcedMandatory
Body (CUSTBODY)3110
Line / column (CUSTCOL)25150
Total56160

MEDIUM 25 line-level fields multiply with every order line, and 15 of them are sourced — each sourcing evaluation stacks with the 7 client scripts' fieldChanged/postSourcing handlers on the same keystroke. Many are bundle-owned (Electronic Payments CUSTCOL_2663_*/CUSTCOL_9572_* file-format and entity-bank fields, STE tax columns, Packship pack-instructions). No mandatory custom fields — good. Remediation is form hygiene: hide unused bundle fields from the active SO entry form rather than deleting them.

Phase 5 — Execution-log heat MEASURED, limited

The scriptnote table (script reference column: scripttype) contains zero entries for the 13 SO-deployed scripts — log levels are set above DEBUG and/or entries have aged out. Log-volume heat ranking is therefore unavailable in this account; findings above rest on code inspection instead. This also means script logging is not itself a performance drag here.

Phase 6 — Bundle attribution MEASURED

BundleContribution to SO entry path
47193 (SCM / Item Substitute + CPN)4 deployments (2 CS + 2 UE), two of them SS1.0; UE sources hidden
237702 (STE tax engine — Oracle)2 deployments (CS + UE), dispatcher pattern, bounded
534418 (Packship / Ship Central)1 CS with the CRITICAL uncached-query finding; plus SO-visible custom fields
266623 (RAC)1 UE, source hidden
Custom (no bundle)ATB SO controller CS, LRC Field Manager CS+UE, USR CS+UE (minified/hidden)

5. Concerns & Risks

6. Prioritized Remediation Plan

  1. Narrow deployment audiences (Trivial, admin config): change allroles to targeted role lists on Packship CS and any fulfillment-only deployments. Expected effect: immediate open/per-line improvement for sales roles. Do this first.
  2. Escalate the uncached query to the Packship vendor (Moderate, vendor): request module-scope caching of getShipCentralPreference() results. Expected effect: removes 1–2 client-side query round-trips per open and per ship-field change for remaining users.
  3. Instrument with NetSuite APM (Trivial, admin install): Page Time Summary will attribute wall-clock per script — including the four hidden UEs and the minified USR script — converting the HYPOTHESIS items to MEASURED.
  4. Form hygiene pass (Trivial–Moderate, admin): hide unused bundle CUSTCOL fields (Electronic Payments bank/file-format columns, etc.) from the active SO entry form.
  5. Review ATB SalesOrderGateway (Moderate, developer): confirm whether the custom controller makes per-line server calls; if so, batch or debounce them.
  6. Plan SS1.0 retirement with the SCM bundle owner (Significant, vendor/dev): upgrade path off 1.0 APIs for bundle 47193 scripts.

7. Next Steps Beyond This Audit

8. Appendix — Reproducibility

All queries executed via SuiteQL under role id 3 on 2026-07-02. Tool calls: agentSession, accountFeaturesGet, runSql ×10, fileGrep ×9, fileGetLines ×3, evalJs (aggregation).

-- Phase 1: script inventory (15 rows; 13 active)
SELECT s.id, s.name, s.scripttype, s.scriptid, s.scriptfile, sd.id, sd.status,
       sd.isdeployed, sd.allroles, sd.eventtype
FROM scriptdeployment sd JOIN script s ON s.id = sd.script
WHERE sd.recordtype = 'SALESORDER'
ORDER BY sd.isdeployed DESC, s.scripttype, s.name;

-- Phase 3: workflows (10 rows; none target SalesOrder)
SELECT name, scriptid, recordtypes, inittriggertype, initoncreate,
       initonvieworupdate, initsavedsearchcondition, islogenabled, frombundle
FROM workflow WHERE isinactive = 'F' AND releasestatus = 'RELEASED';

-- Phase 4: custom field surface (grouped; aggregated client-side to
-- BODY=31, COLUMN=25 containing token 'SalesOrd'. Note: LIKE/INSTR on
-- customfield.visibleontransactions returns 0 in WHERE context in this
-- account — a SuiteQL quirk; grouping by the raw column then filtering
-- client-side is the reliable pattern.)
SELECT fieldtype, visibleontransactions, COUNT(*) cnt,
       SUM(CASE WHEN source IS NOT NULL THEN 1 ELSE 0 END) sourced,
       SUM(CASE WHEN ismandatory='T' THEN 1 ELSE 0 END) mandatory
FROM customfield WHERE fieldtype IN ('BODY','COLUMN')
GROUP BY fieldtype, visibleontransactions;

-- Phase 5: execution-log heat (0 rows — no log entries for these scripts;
-- note scriptnote's script-reference column is named 'scripttype')
SELECT scripttype, type, COUNT(*) FROM scriptnote
WHERE scripttype IN (1793,473,3365,2182,477,1201,2386,418,2192,801,436,1155,2389)
GROUP BY scripttype, type;

-- Phase 6: bundle attribution + API version (13 rows)
SELECT id, name, frombundle, apiversion FROM script
WHERE id IN (1793,473,3365,2182,477,1201,2386,418,2192,801,436,1155,2389);

Files inspected: 24196 (packship_cs_order.js — full anti-pattern review), 7568/7620 (STE dispatchers), 24576/90318 (LRC), 15869 (ATB CS), 5015 (SCM CPN CS), 24710 (USR CS — minified, unreviewable). Access denied: 5021, 5899, 5093, 24736.

Limitations: static analysis only — no wall-clock measurements; four UE sources and one minified CS unreviewed; scriptnote empty for target scripts; audit reflects account state as of 2026-07-02.