🎯 Project Overview
Build a Map/Reduce script that:
- Loads customers from a saved search (script parameter)
- Queries each customer's transactions
- Formats data as CSV lines
- Creates a CSV file in the File Cabinet
- Emails the file as an attachment
📋 Stage 1: getInputData
function getInputData(context) {
const runtime = require('N/runtime');
// Load saved search from script parameter
const searchId = runtime.getCurrentScript().getParameter({
name: 'custscript_customer_search'
});
return search.load({ id: searchId });
}💡 Script Parameters
Using a script parameter for the saved search ID makes the script flexible—administrators can change which customers are processed without modifying code.
🔄 Stage 2: map
function map(context) {
const query = require('N/query');
const customerId = context.value;
// Query transactions for this customer
const results = query.runSuiteQL({
query: `
SELECT tranid, trandate, total
FROM transaction
WHERE entity = ?
AND type = 'SalesOrd'
`,
params: [customerId]
}).asMappedResults();
// Format as CSV line and write to reduce
results.forEach(txn => {
const csvLine = [customerId, txn.tranid, txn.trandate, txn.total].join(',');
context.write({
key: 'csv',
value: csvLine
});
});
}📊 Stage 3: reduce
function reduce(context) {
const file = require('N/file');
const email = require('N/email');
// Collect all CSV lines
const header = 'Customer ID,Order Number,Date,Total';
const lines = context.values;
const csvContent = header + '\n' + lines.join('\n');
// Create CSV file
const csvFile = file.create({
name: 'customer_transactions.csv',
fileType: file.Type.CSV,
contents: csvContent,
folder: 12345 // File Cabinet folder ID
});
csvFile.save();
// Email with attachment
email.send({
author: 207,
recipients: 'admin@company.com',
subject: 'Daily Transaction Report',
body: 'Please find the attached report.',
attachments: [csvFile]
});
}📝 Stage 4: summarize
function summarize(context) {
// Log any errors
context.mapSummary.errors.iterator().each((key, error) => {
log.error('Map Error', error);
return true;
});
log.audit('Complete', 'CSV export finished');
}📖 Finding This in the Docs
This capstone combines multiple modules. Key references:
- Map/Reduce Script Type → getInputData, map, reduce, summarize stages
- N/query Module → runSuiteQL() for transaction queries
- N/file Module → file.create() for CSV generation
- N/email Module → email.send() with attachments
Key pages to bookmark:
- Map/Reduce Script Type → context.write() for passing data between stages
- file.create(options) → name, fileType, contents, folder
- file.Type enum → CSV, PLAINTEXT, PDF options
- N/runtime Module → Script.getParameter() for script parameters
🎯 Key Takeaways
- getInputData returns a search object; NetSuite iterates it automatically
- map processes each customer, writes CSV lines to reduce
- reduce consolidates all data, creates file, sends email
- summarize logs errors and completion status
- Script parameters make solutions configurable without code changes
- Combine N/query, N/file, and N/email in Map/Reduce stages