This article is relevant if you are looking for a way to get control over the locking (read only mode) of NetSuite form fields for specific situations where you are not satisfied with workflow locking methods.
Background
NetSuite’s form based customization generally works great. Yet, there are two major situations where the form based mode for managing the user experience is not ideal:
- Record State: Locking the record in question because it is in a specific state.
- Role Access: The role that is accessing the form needs specific behavior.
- Exception Fields: Most of the fields you want to lock, but not all of them.
The only way to get control over the record in a specific situations is to use Workflows or SuiteScript. Modifying forms for each user role can work but, as many NetSuite Administrators know, if you get a number of these, the ongoing form maintenance is cumbersome and error prone. Why not use your own logic to lock fields?
Solving the NetSuite Lock Fields to Read Only Challenge
For a recent client implementation where they leveraged our Record State Manager, we had situations where we wanted to lock down the sales order for edits while at the same time allow for some fields, such as the memo, to be edited after it had been approved. However, we also needed the ability to have specific roles edit the entire record as well.
One of our senior consultants produced the general SuiteScript 2.0 pattern to go after this challenge.
- Server Side: we can dynamically go over all the form fields and disable them before the page is rendered.
- Client Side: NetSuite does not quite go all the way server side (surprise, surprise), especially for list / column based fields. So we need some clients side helper scripts.
We want our script to do the heavy lifting work. But we discovered that NetSuite’s provided libraries which dynamically let us query the list of fields seemed insufficient. Instead of figuring out why the libraries were not returning the entire list of fields, we decided to create some helper list arrays to inform the script of “straggler” fields that were not getting our intended read-only behavior. Finally, we wanted a list of exceptions fields that should not get our read only locked down treatment.
Server Side SuiteScript 2.0 to Lock Fields
Here is the SuiteScript to lock down the fields.
/** *@NApiVersion 2.x *@NScriptType UserEventScript */ define(['N/log','N/record','N/search', 'N/runtime', 'N/ui/serverWidget'], function(log,record,search,runtime, serverWidget) { var scriptName = "v_UE_SOLockdown."; //hard code the roles that will not get locked down var ADMIN_ROLES = [3,1063]; function beforeLoad(context) { var funcName = scriptName + "beforeLoad"; //test record situation where we will perform lock if ((runtime.executionContext == runtime.ContextType.USER_INTERFACE) && (context.type == context.UserEventType.EDIT) && (context.newRecord.getValue("orderstatus") != "A")) { if (ADMIN_ROLES.indexOf(runtime.getCurrentUser().role) >= 0) { return; //exit the admin roles as specificed above } //get the list of fields available via NetSuite's library offer var REC = context.newRecord; var fieldList = REC.getFields(); //attack the fields that we can't get control of via NetSuite's standard field list lookup [don't know why; but get control anyways] var OTHER_FIELDS = ["custbody_v_az_latest_ship_date","memo","otherrefnum"]; //spin through the lists and disable for (var i = 0; i < fieldList.length; i++) disableField(context, fieldList[i]); for (var f in OTHER_FIELDS) disableField(context, OTHER_FIELDS[f]); } } function disableField(context, fieldName) { var funcName = scriptName + "disableField " + fieldName; //create an exception list of fields that we do NOT want disabled var FIELDS_TO_EXCLUDE = ["custbody_v_order_notes"]; if (FIELDS_TO_EXCLUDE.indexOf(fieldName) >= 0){ return; } //get reference to the form field to disable it. var fld = context.form.getField(fieldName); if (fld) { fld.updateDisplayType({displayType: serverWidget.FieldDisplayType.DISABLED}); log.debug(funcName, "Disabling field"); } else log.debug(funcName, "Unable to get reference to field"); } return { beforeLoad: beforeLoad } } );
Client Side SuiteScript 2.0 to Lock Fields
In the following script, we had to take control of the situation by accessing the browser’s DOM object to get references to the fields we care about. We discovered NetSuite supplied, but undocumented, Javascript functions to get control over field behavior. Keep in mind that this approach entails some risk as NetSuite does not officially provide support.
/** *@NApiVersion 2.x *@NScriptType ClientScript *@NModuleScope Public */ define(['N/record','N/search','N/runtime'], function(record, search, runtime){ //create reference to lists we want to control via client side script var REC; var BODY_FIELD_LIST = ["shipaddresslist","shipmethod"]; var ITEM_FIELD_LIST = ["item","quantity","description","amount","rate","price","class","taxcode","options"]; var ADMIN_ROLES = [3,1063]; function pageInit(context) { REC = context.currentRecord; if (!REC.id) return; if (ADMIN_ROLES.indexOf(runtime.getCurrentUser().role) >= 0) return; //spin through the list of fields we want to disable for (var f in BODY_FIELD_LIST) { nsDisableField(context, null, BODY_FIELD_LIST[f]); } for (var f in ITEM_FIELD_LIST) { nsDisableField(context, "item", ITEM_FIELD_LIST[f]); } } /* ----------------------------------------------------------------------------------------------------------------------------- */ function nsDisableField(context,formId,fieldId,lineNbr){ try { var fld; //using DOM referencing and NetSuite supplied functions, find the field and disable it if (formId) { fld = getFormElement(document.forms[formId+"_form"],getFieldName(fieldId)); if (fld == null) fld = getFormElement( document.forms[formId+'_form'], getFieldName(fieldId)+lineNbr); } else fld = getFormElement(document.forms["main_form"],getFieldName(fieldId)); if (isSelect(fld)){ disableSelect(fld,true); } else { disableField(fld,true); } fld = REC.getField(fieldId); if (fld) { fld.isDisabled = true; } } catch (e) { ; } } return { pageInit: pageInit }; });
Extend NetSuite Platform Capacities with Innovation Leadership
This article is designed to illustrate that we indeed can get control over the NetSuite environment, especially form driven situations. We must always remember that the NetSuite system sits inside the larger universe of software standards and constraints for which it must perform. Thus, we too can work in that software universe to get the desired logic and behavior we want, if we are willing to work for it. If you are the type of professional that respects the way we think and wants to be part of an organization that values creativity, ethics, autonomy and care, let’s have a conversation.
Hi,
I want to know how to restrict my script in view mode only.
detail: I have a field of item count, it shows up in view mode and edit mode only
The general pattern then is to have a BeforeFload script act if you are going into View and Edit Mode. If Edit, then you can have display:none attributes. Most folks, for counters, make these fields type inline so that even if they show in edit, they are not editable.
Hi Marty,
This is just what I needed as locking down sales order fields after the sales order is approved became a requirement within our organisation. NetSuite support had told me it would require addressing each field separately, which would have made for a very long and unwieldy piece of code!
Before I describe the problem I am having I just wanted to point out that in the server side script there is a small error that caused the code to fail on my first attempt to create the deployment script. On the line after “//spin through the lists and disable” there is an entry towards the end that begins with “//create an exception list of fields…” and further along there is a variable declaration and an “if” statement that cause this error because they are part of the comment rather than being on a separate line.
The problem that I am having with client side script is that it only locks down the fields on the next available empty line when editing a sales order, but the line(s) above can still be edited. I am certain that I have done something wrong somewhere, but perhaps you could shed some light on this as getting this to work is critical.
Many thanks for this fantastic article and I look forward to hearing from you.
Regards,
Lloyd P. Hunt