image image image image image image

Why are simple customizations in NetSuite so complicated?

Why are simple customizations in NetSuite so complicated?

Often things that sound simple reveal themselves to be a much more complicated and a much heavier lift to accomplish in NetSuite due to limitations of native functionality. While NetSuite has the capability to do so many things, it is a bit of a dinosaur that requires some nuance and work-arounds for common user interface functionality. Consider this scenario:

I want employees in different departments to place Purchase Orders only for their Department’s Locations.

Let’s say we have 3 departments:

  1. IT
  2. Warehouse
  3. Marketing

and 4 Locations:

  1. Headquarters
  2. Warehouse
  3. Brick and Mortar Store A
  4. Brick and Mortar Store B

Here are the locations I want my employees to order for each department:

Employee Department Location
Alice Johnson IT Headquarters
Warehouse
Brick and Mortar Store A
Brick and Mortar Store B
Bob Smith Warehouse Warehouse
Carol Gray Marketing Brick and Mortar Store A
Brick and Mortar Store B

The reason this is a difficult task is because NetSuite doesn’t allow filtering of the native fields such as Location.

A work-around to this could be:

  • hide the real Location field from the user upon loading the transaction.
  • show a custom filtered-Location field to the user which sets the real location field.
  • upon Save of the transaction we update the hidden Location field to our custom filtered-Location field’s value.

 

Add a custom Form Field we can filter

First, if you haven’t already, make sure you have these classifications enabled under the Enable Features setting:

Next, we add our custom transaction body field:

custbody_filtered_location

While on the Purchase Order you can create this under the Customize dropdown:

Here it is set to list all the Locations which we will later filter using the script below

We don’t need to store the value of this field to the database because that could add confusion having two of the same field, especially if they ever differed for some reason, and this field will only be ever used as a proxy to set the real location field.

Finally, here is a client script that could be deployed on the Purchase Order transaction to achieve this:


/**
 * @NApiVersion 2.x
 * @NScriptType ClientScript
 */

define(['N/currentRecord', 'N/search'], function(currentRecord, search) {

    /**
     * The pageInit function is executed when the record page is initialized.
     * It sets the 'custbody_filtered_location' field to the value of the 'location' field,
     * and then hides the 'location' field.
     *
     * @param {Object} context - Contains information about the current record.
     */
    function pageInit(context) {
        var record = context.currentRecord;
        var locationValue = record.getValue({ fieldId: 'location' });
        
        // Set the value of custbody_filtered_location to the value of the location field
        record.setValue({
            fieldId: 'custbody_filtered_location',
            value: locationValue
        });

        // Hide the standard location field
        var locationField = record.getField({ fieldId: 'location' });
        locationField.isDisplay = false;
    }

    /**
     * The fieldChanged function is called when the value of any field on the record is changed.
     * Specifically checks if the 'department' field is changed and calls
     * updateLocationField to filter the 'custbody_filtered_location' field's values.
     *
     * @param {Object} context - Contains information about the field that was changed.
     */
    function fieldChanged(context) {
        var record = context.currentRecord;
        var fieldId = context.fieldId;

        if (fieldId === 'department') {
            var department = record.getValue({ fieldId: 'department' });
            updateLocationField(record, department);
        }
    }

    /**
     * Updates the 'custbody_filtered_location' field options based on the selected department.
     * Uses a predefined mapping of departments to their respective locations to populate the dropdown.
     *
     * @param {Object} record - The current NetSuite record.
     * @param {String} department - The selected department value.
     */
    function updateLocationField(record, department) {
        var locationField = record.getField({ fieldId: 'custbody_filtered_location' });
        locationField.removeSelectOption({ value: null }); // Clear existing options

        // Define the department-location mapping
        var locationMapping = {
            'IT': ['Headquarters', 'Warehouse', 'Store A', 'Store B'],
            'Warehouse': ['Warehouse'],
            'Marketing': ['Store A', 'Store B']
        };

        var relevantLocations = locationMapping[department] || [];

        relevantLocations.forEach(function(locationName) {
            locationField.addSelectOption({
                value: locationName,
                text: locationName
            });
        });
    }

    /**
     * The saveRecord function is not needed in this case as we are not updating the standard location field.
     * The custbody_filtered_location field is used for display and selection purpose only.
     */

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

Another way to achieve this could be through a Workflow.

Workflows are great for certain tasks such as making form changes like this or business processes such as approval routing for purchase orders, expenses, or any other transaction. Additionally, they can be easier to maintain and good solution for non-developers, providing the logic doesn’t get too complicated.

Because there are limitations to workflows, such fields that can’t be reached, they offer workflow action scripts as a way to extend the functionality of workflows through plugging in scripting logic to certain actions within the workflow.

 

Looking for help with implementing simple business logic in NetSuite?

Book a meeting with us today to get the most out of NetSuite