📚 Appendix A: Code Examples

Annotated script templates and reusable patterns

User Event Script Template

/**
 * @NApiVersion 2.1
 * @NScriptType UserEventScript
 * @NModuleScope SameAccount
 */
define(['N/record', 'N/log'], (record, log) => {

    const beforeLoad = (context) => {
        // Runs before the record is displayed
        // context.type: create, edit, view, copy, print, email
        // context.form: the form object
        // context.newRecord: the record being loaded
    };

    const beforeSubmit = (context) => {
        // Runs after Save clicked, before database write
        // context.type: create, edit, delete, xedit (inline edit)
        // context.newRecord: record with new values
        // context.oldRecord: record with previous values (edit only)
    };

    const afterSubmit = (context) => {
        // Runs after database save
        // Good for: sending emails, updating related records
        const recordId = context.newRecord.id;
        log.audit('Record Saved', recordId);
    };

    return { beforeLoad, beforeSubmit, afterSubmit };
});

Client Script Template

/**
 * @NApiVersion 2.1
 * @NScriptType ClientScript
 * @NModuleScope SameAccount
 */
define(['N/currentRecord', 'N/log'], (currentRecord, log) => {

    const pageInit = (context) => {
        // Runs when page loads
        // context.mode: create, copy, edit
        const rec = context.currentRecord;
    };

    const fieldChanged = (context) => {
        // Runs when a field value changes
        const fieldId = context.fieldId;
        const rec = context.currentRecord;
        
        if (fieldId === 'quantity') {
            const qty = rec.getValue('quantity');
            const rate = rec.getValue('rate');
            rec.setValue('amount', qty * rate);
        }
    };

    const saveRecord = (context) => {
        // Runs when Save is clicked
        // Return true to allow save, false to block
        const rec = context.currentRecord;
        
        if (!rec.getValue('email')) {
            alert('Email is required');
            return false;
        }
        return true;
    };

    return { pageInit, fieldChanged, saveRecord };
});

Map/Reduce Template

/**
 * @NApiVersion 2.1
 * @NScriptType MapReduceScript
 * @NModuleScope SameAccount
 */
define(['N/search', 'N/record', 'N/log'], (search, record, log) => {

    const getInputData = () => {
        // Return: Search, Array, or Object
        return search.create({
            type: 'customer',
            filters: [['isinactive', 'is', 'F']],
            columns: ['entityid', 'email']
        });
    };

    const map = (context) => {
        // Process each result from getInputData
        const data = JSON.parse(context.value);
        const customerId = data.id;
        
        // Write to reduce stage
        context.write({
            key: customerId,
            value: data.values.email
        });
    };

    const reduce = (context) => {
        // Aggregate by key
        const customerId = context.key;
        const emails = context.values;
        
        log.audit('Customer', customerId + ': ' + emails.join(', '));
    };

    const summarize = (context) => {
        // Log errors and summary
        context.mapSummary.errors.iterator().each((key, error) => {
            log.error('Map Error', error);
            return true;
        });
        
        log.audit('Complete', 'Processed ' + context.inputSummary.recordCount + ' records');
    };

    return { getInputData, map, reduce, summarize };
});

Suitelet Template

/**
 * @NApiVersion 2.1
 * @NScriptType Suitelet
 * @NModuleScope SameAccount
 */
define(['N/ui/serverWidget', 'N/record', 'N/log'], (serverWidget, record, log) => {

    const onRequest = (context) => {
        if (context.request.method === 'GET') {
            // Display form
            const form = serverWidget.createForm({ title: 'Custom Form' });
            
            form.addField({
                id: 'custpage_name',
                type: serverWidget.FieldType.TEXT,
                label: 'Name'
            });
            
            form.addSubmitButton({ label: 'Submit' });
            context.response.writePage(form);
            
        } else {
            // Handle POST
            const name = context.request.parameters.custpage_name;
            log.audit('Submitted', name);
            
            // Redirect or show confirmation
            context.response.write('Submitted: ' + name);
        }
    };

    return { onRequest };
});

RESTlet Template

/**
 * @NApiVersion 2.1
 * @NScriptType Restlet
 * @NModuleScope SameAccount
 */
define(['N/record', 'N/log'], (record, log) => {

    const get = (requestParams) => {
        // Handle GET requests
        const customerId = requestParams.id;
        const customer = record.load({
            type: 'customer',
            id: customerId
        });
        
        return {
            id: customer.id,
            name: customer.getValue('companyname'),
            email: customer.getValue('email')
        };
    };

    const post = (requestBody) => {
        // Handle POST requests
        const customer = record.create({ type: 'customer' });
        customer.setValue('companyname', requestBody.name);
        customer.setValue('email', requestBody.email);
        
        const customerId = customer.save();
        return { success: true, id: customerId };
    };

    return { get, post };
});