NS Admin Lab

Rodolfo Guerra · NetSuite Specialist

What I learn running NetSuite, explained plainly.

I have worked with NetSuite every day for 7 years. Here I share practical notes on development, queries and administration: what works, and the mistakes worth avoiding.

About me

I’m Rodolfo Guerra. I started as a NetSuite administrator at a services company, and today I lead the NetSuite product at a multi-subsidiary company.

My work sits between the business and the system. I listen to what a team needs, turn it into configuration or code, and make sure it keeps working as volume grows.

I built this lab to organize what I learn and share it. Every note comes from a real case.

7 yearsrunning NetSuite
2.xSuiteScript: Map/Reduce, Suitelets, User Events, RESTlets
SuiteQLcustom queries and reports

Focus areas

What I work on day to day.

Development

SuiteScript 2.x

Automations that hold up under volume.

  • Map/Reduce and Scheduled
  • Suitelets and Client Scripts
  • User Events and validations
Data

SuiteQL and reporting

Clear answers from the data.

  • Custom queries
  • Saved searches
  • Backlog analysis
Operations

Administration

A tidy, secure system.

  • Roles, forms and workflows
  • Bulk CSV imports
  • Duplicate-safe REST integrations

Lab

Short notes, each based on a real case. Open one to see the details.

SuiteScript

It worked fine… until the volume grew

A Scheduled Script that processes everything in one run is fine with a few records. When volume grows, the trouble starts.

Scheduled Script

  • A single run, capped at 10,000 governance units.
  • If it runs out of units, it stops halfway.

Map/Reduce

  • Works in stages: getInputData, map, reduce and summarize.
  • Processes one record at a time: one error doesn’t stop the rest.
  • In summarize you review what failed and why.

Rule of thumb: Scheduled for short jobs with predictable volume. Map/Reduce for many records or growing volume. When in doubt, start with Map/Reduce.

Finance

Paying vendors shouldn’t take an afternoon

Before: the same payment was keyed into NetSuite, online banking, a spreadsheet and an email to the vendor. Four places, four chances for error.

After: one flow inside NetSuite

  1. You select the bills to pay inside NetSuite.
  2. NetSuite generates the bank file using your bank’s payment template.
  3. You upload once to the bank, instead of one transfer per payment.
  4. The payment is recorded against each bill.
  5. The vendor gets an email notification.

Heads-up: not everything comes out of the box. The Electronic Bank Payments SuiteApp gives you your country’s standard templates, batch approval and reversals. These need the Electronic Bank Payments license: custom templates, automatic bill processing, multi-currency, APIs and parallel processing (the last one also requires SuiteCloud Plus).

CSV imports

5 mistakes that ruin a customer import

MistakeWhat happensHow to avoid it
No External IDRe-importing duplicates everything“Add or Update” mode + External ID
List values that don’t match“Cash” ≠ “Cash - 0 days”Text identical to NetSuite’s
Dates in another formatDates rejected or misreadYour user’s date format
Broken accents“Perú” instead of “Perú”File and import in UTF-8
Testing with the whole file500 records to fix5 rows first, then the rest

Bonus: save the field mapping. The next import takes minutes.

Best practices

The sandbox is not optional

A “small” change in production can break:

  • A workflow that fires on another record.
  • A script that depends on that field.
  • An integration that expects the old format.

The rule

  1. Sandbox first: every change is tested there.
  2. Real data: copied from production.
  3. Deploy after hours: with a way to roll back.

It costs one more day. A production error costs several.

Integrations

Same order, two sales orders

An external system sends order A-1042 and NetSuite creates the sales order. The response never arrives because of a network drop. The system retries… and without protection, a second order is created.

The fix is to make retries safe (idempotency). Use the external system’s identifier as the External ID: NetSuite won’t allow two records of the same type with the same External ID.

// RESTlet (SuiteScript 2.1): look up before creating
const existing = query.runSuiteQL({
  query: 'SELECT id FROM transaction WHERE externalid = ?',
  params: [payload.orderId]
}).asMappedResults()[0];

if (existing) return { id: existing.id, duplicate: true };

const so = record.create({ type: record.Type.SALES_ORDER });
so.setValue({ fieldId: 'externalid', value: payload.orderId });

If the order already exists, you return the same one. The External ID is the second safeguard: even if two requests arrive at once, NetSuite rejects the duplicate.

SuiteQL

Readable names in SuiteQL, no extra JOIN

BUILTIN.DF turns an ID into the text you see on screen: the customer, sales rep or location name.

SELECT
  t.tranid AS order_no,
  BUILTIN.DF(t.entity)    AS customer,
  BUILTIN.DF(t.employee)  AS sales_rep,
  BUILTIN.DF(tl.location) AS location
FROM transaction t
JOIN transactionline tl
  ON tl.transaction = t.id
WHERE t.type = 'SalesOrd'
  AND tl.mainline = 'T'
  AND t.status IN ('E', 'F')

For display, not for filtering. In the WHERE clause always use the ID or code: it’s more efficient and doesn’t depend on how the text is spelled.

Let’s talk

If you work with NetSuite and want to discuss any of these notes, message me on LinkedIn.

Go to my LinkedIn ↗