SuiteCloud Developer study materials
SuiteCloud Developer study resources

User Event Script on Item Fulfillment During Bulk CSV Import

SuiteCloud Developer · Put your knowledge to work in context.

All case studies

User Event Script on Item Fulfillment During Bulk CSV Import

A CSV import of 300 item fulfillments (average 25 lines, largest 60) runs with scripts enabled and triggers a user event script deployed on Item Fulfillment. In afterSubmit, the script loops over every line, calls search.lookupFields to read the item's custitem_hazmat_class, creates a customrecord_hazmat_log record, and when the class is H also creates a journal entry. Roughly 15 percent of transactions fail with SSS_USAGE_LIMIT_EXCEEDED. A handful end with an unexpected error after the journal entry was already created, and the team's standard fix, rerunning the whole file, produces duplicate hazard logs and duplicate journals. Users also report that manually editing one large fulfillment in the UI now takes 40 to 60 seconds and sometimes times out. The business will not accept losing the hazard log or the journal, and the nightly import window is fixed.

1. Explain the failures as three separate problems, not one, and say which part of the script causes each.

Read the worked answer

The symptoms come from three different mechanisms, and fixing only one will not help.

Usage-unit exhaustion. Every lookupFields call and every record create consumes governance units from a single execution budget. A 60-line fulfillment can mean 60 lookups, 60 log creates, and up to 60 journal entries in one afterSubmit run, so the largest transactions fail while smaller ones pass. That is why roughly 15 percent fail and the rest do not: it is a size threshold, not random failure.

Partial writes with no atomicity. Each record.create commits independently. If the journal entry succeeds and a later line throws, the earlier work is already persisted. There is no wrapping transaction that unwinds it, so the unexpected error leaves real financial records behind.

Non-idempotent retry. Nothing keys the log or the journal to the fulfillment and line. Rerunning the file creates a second log and a second journal for work that already succeeded, which is exactly what the team is doing.

A fourth, quieter problem is placement: afterSubmit cannot modify the triggering record in place, so any correction requires a second save. Heavy work in a synchronous afterSubmit also blocks the UI, which explains the 40-to-60-second edits.

2. Redesign the script. Where should the work happen, and how do you make the log and journal safe to retry?

Read the worked answer

Split the synchronous trigger from the heavy processing.

Keep afterSubmit minimal. Its only job should be to mark the work as pending and hand off. A flag field on the fulfillment or, better, a search-driven queue means afterSubmit does one small write and returns.

Do the work in Map/Reduce. A map/reduce script triggered from afterSubmit with N/task (or swept by a scheduled run, so nothing is lost if the task submission fails) gives each phase its own execution budget and lets one bad fulfillment fail without taking down the batch. getInputData searches for pending fulfillments, map handles one fulfillment per key, and reduce can aggregate counts for the daily hazard summary.

Batch the item lookups. Instead of one lookup per line, collect the line item internal IDs and run a single search with an anyof filter on item, requesting internal ID and custitem_hazmat_class. Page results with getRange. One search per fulfillment replaces 25 to 60.

Make every write idempotent. Give customrecord_hazmat_log a deterministic unique key built from fulfillment ID plus line ID, such as an external ID or a mandatory unique name, and check existence before creating. Give each journal entry a deterministic external ID built from the fulfillment, so a retry either finds the existing entry or is rejected as a duplicate. Use record.upsert with external ID where the object supports it.

With this design a rerun is safe, so the team can stop treating a failed file as an all-or-nothing event.

3. The business wants the journal same day and the import must stay inside the nightly window. What entry point and trigger do you recommend, and what would you refuse to do?

Read the worked answer

Recommendation: validate in beforeSubmit, process asynchronously, and report per record.

  • beforeSubmit is the right place for validation, because throwing an error there blocks the save and the CSV import reports it against the specific row. Use it to reject a fulfillment whose item has no hazmat class, rather than discovering that later in a background job.
  • afterSubmit should only enqueue. It is synchronous with the user request and the import row, so anything heavy directly damages UI responsiveness and import throughput.
  • Processing continues through Map/Reduce immediately after the enqueue, or through a scheduled sweep every few minutes. Same-day is comfortably met; the journal does not need to exist inside the import transaction.
  • Persist a processing status per fulfillment so operations can see outstanding work instead of guessing from script logs.

What I would refuse:

  • Creating records in a loop inside afterSubmit and hoping the budget holds.
  • Using a user event script's error as the retry signal, since that produces the duplicate journals already observed.
  • Turning off scripts for the import as a workaround. That removes the hazmat log and the journal entirely, which is the outcome the business explicitly ruled out.