SuiteScript Short - Reduce Repetition when Working with Records
Created: March 5, 2024
A pretty common complaint I hear about the SuiteScript API is that it's too verbose. It often takes a lot of repetitive typing to accomplish common tasks. I've seen some teams go so far as to build their own abstraction layer over the top of the SuiteScript API just to make it more palatable for themselves.
I completely agree that SuiteScript can be verbose, but I promise we don't need to do anything so elaborate or complex or fraught as re-writing SuiteScript in its entirety.
Rather, we can arrange our data in a data structure more conducive to iteration, then take advantage of native JavaScript iteration methods and syntactic sugar to focus our code on the characters that really matter.
Setting a bunch of fields on a record?
The N/record
API is notoriously verbose.
Turn this:
const customer = record.create({ type: record.Type.CUSTOMER })
.setFieldValue({
fieldId: 'subsidiary',
value: customerModule.getSubsidiary(customerData)
})
.setFieldValue({
fieldId: 'companyname',
value: customerModule.generateName(customerData)
})
.setFieldValue({
fieldId: 'email',
value: customerData.email
})
.setFieldValue({
fieldId: 'url',
value: customerData.website
})
.setFieldValue({
fieldId: 'phone',
value: customerData.phone
})
const customerId = customer.save()
into this:
const customer = record.create({ type: record.Type.CUSTOMER });
[
// [fieldId, fieldValue]
['subsidiary', customerModule.getSubsidiary(customerData)],
['companyname', customerModule.generateName(customerData)],
['email', customerData.email],
['url', customerData.website],
['phone', customerData.phone]
].forEach(([fieldId, value]) => {
customer.setValue({ fieldId, value })
})
const customerId = customer.save()
The latter has ~20%
fewer characters (not counting line breaks) -
428
compared to the former's 536
. The savings increase linearly as you add
more fields.
You add new field values by adding a new [fieldId, fieldValue]
pairing to the
Array, and that's it.
Retrieving data from a sublist?
Sublists are a particularly egregious offender.
Turn this:
const lineCount = salesOrder.getLineCount({ sublistId: 'item' })
const items = []
for (let i = 0; i < lineCount; i++) {
items.push({
id: salesOrder.getSublistValue({
sublistId: 'item',
fieldId: 'item',
line: i
}),
amount: salesOrder.getSublistValue({
sublistId: 'item',
fieldId: 'amount',
line: i
}),
rate: salesOrder.getSublistValue({
sublistId: 'item',
fieldId: 'rate',
line: i
}),
total: salesOrder.getSublistValue({
sublistId: 'item',
fieldId: 'total',
line: i
})
})
}
into this:
const itemFields = ['item', 'amount', 'rate', 'total']
const itemCount = salesOrder.getLineCount({ sublistId: 'item' })
const items = [...Array(itemCount)]
.map((_, line) => {
const currentLine = { sublistId: 'item', line }
return itemFields.reduce((itemData, fieldId) => {
itemData[fieldId] = salesOrder.getSublistValue({
...currentLine,
fieldId
})
return itemData
}, {})
})
The latter has ~29%
fewer characters (not counting line breaks) -
413
compared to the former's 582
. Again the savings increase linearly as you
add more fields.
You add more fields to the result by adding new field IDs to itemFields
, and
that's it.
Data First, Boilerplate Later
It's certainly nice that they require less typing, but what I like about them
the most is that they put the data you care about - the
fields and values you're setting or reading - right at the front, all in one
spot. You don't have to hunt through method call after repeated method call to
figure out which columns you're pulling or where the value for the email
field comes from.
If you're the type that likes to abstract SuiteScript like I mentioned above,
you could for instance take the map()
call above and encapsulate it in
a readSublist
method and shorten things even further. I prefer to shy away
from this myself so that my students and the folks who inherit my code
don't have to learn two separate APIs.
If you haven't been using SuiteScript 2.1, my approach probably looks wildly unfamiliar. I'm taking advantage of many modern JavaScript features here, which are available to you when you use SuiteScript 2.1:
If you're not already familiar with these JavaScript features, or you're not using SuiteScript 2.1, I can't recommend strongly enough that you start practicing reading and writing with these tools. They'll allow you to write code that brings the important stuff forward and pushes the boilerplate to the background.
SuiteScript 2.1
Are you taking advantage of the power of SuiteScript 2.1? Have an approach you like better?
Join the Sustainable SuiteScript community and share your thoughts.