The situation
A software company runs payroll in Workday and keeps its books in NetSuite. After every pay run, someone in finance took Workday's payroll accounting output and keyed it into NetSuite as a journal entry. Each line had to be matched by hand to a NetSuite department, class, location and GL account.
What we built
One Map/Reduce script with three deployments, one for the bi-weekly run and one each for the semi-monthly runs on the 1st and the 16th.
The script reads a Workday custom report as JSON over HTTPS. The report address is a script parameter. The username and password are NetSuite API secrets, referenced from a configuration record. The script builds the authorization header with secure strings, so the password never passes through the script as plain text. The semi-monthly deployments read their own class and region columns from the same report.
For each report line, the script looks up four values in NetSuite:
- the Workday cost centre, as a department;
- the class, as a class;
- the region, as a location;
- the ledger account number, as a GL account.
What it does now
When every line maps, the script posts one journal entry for the run, with each line carrying its account, debit or credit, department, class and location.
When any line fails to map, the script posts nothing. It emails the administrator a list of the missing regions, classes, cost centres and accounts, grouped by type, plus any report lines with empty values. Someone adds the missing value in NetSuite and runs the deployment again. A run that finds no report lines stops with an error instead of finishing quietly, and the summary stage emails any error from any stage.
Under the hood
- Posting is all or nothing per run, so a partial payroll journal never reaches the ledger.
- Lookups use names and account numbers, which finance can read and fix, instead of internal ids.
- The configuration record holds references to the secrets, not the secrets. The script checks that the username, password and report address are all present before it calls Workday.
- One script covers the three pay calendars through deployments, so a mapping fix applies to all of them.
- A shared error library collects failures from every Map/Reduce stage into one email.