Published on

Map/Reduce SuiteQL input

getInputData can return a SuiteQL query object. NetSuite runs and pages it for you, with no row limit. Each map call gets one row, with the column values in values, in SELECT order.

mr_close_stale_quotes.js
/**
* @NApiVersion 2.1
* @NScriptType MapReduceScript
*/
define(['N/record', 'N/log'], (record, log) => {
const getInputData = () => ({
type: 'suiteql',
query: `
SELECT t.id, t.tranid
FROM transaction t
WHERE t.type = 'Estimate'
AND t.status = 'A'
AND t.trandate < SYSDATE - ?`,
params: [90],
})
const map = (ctx) => {
const [id, tranid] = JSON.parse(ctx.value).values
record.submitFields({
type: record.Type.ESTIMATE,
id,
values: { entitystatus: 14, memo: 'Closed automatically after 90 days' },
options: { enableSourcing: false, ignoreMandatoryFields: true },
})
ctx.write({ key: tranid, value: 'closed' })
}
const summarize = (summary) => {
if (summary.inputSummary.error) log.error('Input error', summary.inputSummary.error)
summary.mapSummary.errors.iterator().each((key, error) => {
log.error(`Map failed for ${key}`, JSON.parse(error).message)
return true
})
let closed = 0
summary.output.iterator().each(() => {
closed++
return true
})
log.audit('Done', `${closed} quotes closed, ${summary.usage} units used`)
}
return { getInputData, map, summarize }
})

Notes:

  • status = 'A' and entitystatus: 14 are examples. Check the status codes and IDs in your account first.
  • Uncaught errors in map do not stop the script. They show up only in summarize, so always log them there.
  • Map stages can run more than once after a restart. Make each map call safe to repeat.