• Heidi Lauberger

Caching your form data entry in the current Session with SuiteScript 2.0 - or how to circumvent the

In the context of our ongoing series on the awesomeness of SuiteScript 2.0 (and why you would not want to settle for anyone not making the best out of it), I would like to demonstrate the power of the new framework on a situation a many of the international users and developers have probably become aware of: the NetSuite Advanced Taxes and its client script with pageInit trigger on all transaction record types with the field {entity}.

In order to support the complexities of international tax nexuses, NetSuite has introduced Advanced Taxes (Setup > Enable Features > Tax), which provides support for a many international tax setups. In order to source the correct tax codes on transaction level, though, upon selection of the entity value (the customer on sales orders, invoices, and credit memos, or the vendor on purchase orders, vendor bills, and supplier credits respectively), the record gets refreshed and the principal tax nexus from the entity record gets populated on the record. In the UI, only the entity value persists.

In the UI, end users may have come across this when they entered the transaction date first. NetSuite Administrators and Functional Consultants leveraging on SuiteFlow may have come across it when trying to source additional field values from the entity record, just to see the actions returning empty values. (The workaround here is simple: Select the trigger point “Entry” rather than “After Field Sourcing” on your actions and make sure that the state is entered upon record load.)

The form refresh recently became a significant challenge in the implementation of the NetSuite Software Verticals Contract Renewals bundle, an advanced managed bundle by NetSuite allowing to manage, invoice, renew, and uplift software subscriptions, as the customer was significantly leveraging on the Channel Tier functionality of the bundle: While the software subscription licenses were meant to be shipped to the End User (recorded on the Sales Order), the invoice was meant to go to Distributors and Resellers respectively. Only at the point of sourcing the End User and the Product Line of Software offered, the list of Distributors and Resellers would have become available.

With the SuiteScript 2.0 API method runtime.getCurrentSession(), we found a convenient way to collect all data entry before the refresh and have it immediately reentered after the form is reloaded.

First, we drop some code into the fieldChanged function.

function fieldChanged(context) { if ( context.fieldId === ‘custbody_end_user’ || context.fieldId === ‘entity’ || context.fieldId === ‘subsidiary’ ) { var objRec = context.currentRecord; var objInput = {}; objInput[‘custbody_end_user’] = objRec.getValue({ fieldId: ‘custbody_end_user’ }); objInput[‘entity’] = objRec.getValue({ fieldId: ‘entity’ }); objInput[‘custbody_bill_to_tier’] = objRec.getValue({ fieldId: ‘custbody_bill_to_tier’ }); objInput[‘custbody_distributor’] = objRec.getValue({ fieldId: ‘custbody_distributor’ }); var objSess = runtime.getCurrentSession(); for ( var key in objInput ) { if ( !mavenchecks.isNullOrEmpty(objInput[key]) ) { sessionObj.set({ name: key, value: objInput[key] }); } } }

At this point, we have all relevant data for Contract Renewals cached in the session object.

With the page refreshed, we check on whether the Advanced Taxes refresh has taken place with the following pageInit trigger.

function pageInit(context) { // Having Advanced Taxes activated on the account, as soon as the {entity} field is populated, // the entire record form is reloaded and all values but the one in the {entity} field are lost. // A respective case #3165131 has been filed with NetSuite. // For this implementation, the invoice recipient and hence the company in the {entity} field may either be the end user, // the software supplier providing commissions (“Distributor”) or a third party (“Reseller”) and hence, // there’s a high risk that due to Advanced Taxes, the form gets refreshed several times impairing user experience. // The solution is to set in advance whether the End User, the Distributor, or the Reseller shall be invoiced, and then cache all other values across the form refresh. log.debug(‘Step 1 | pageInit initialised’, context.mode); if ( context.mode === ‘create’ ) { var objRec = context.currentRecord; var strForm = objRec.getText({ fieldId: ‘customform’ }); log.debug(‘Step 1 | strForm’, strForm); if ( strForm.indexOf(‘Contract Renewals’) > -1 ) { var idEntity = objRec.getValue({ fieldId: ‘entity’ }); if ( mavenchecks.isNullOrEmpty(idEntity) ) { // Step 1: This branch is triggered when the form is loaded for the first time. var objResult = assistSetup(context); } else { // Step 2: This branch is triggered when we actually already loaded the form once but Advanced Taxes refreshed it // At this stage, we leverage on the Session object to source the values we had entered previously // In a future version, we could work with the cache object because the Session object is universal across the runtime of the respective user updateRecord(context); } } } }

(At this stage, we ignore Step 1 which leads to a really neat popup workflow directly on the Sales Order.)

The associated function updateRecord() is simple.

function updateRecord(context) { var objSess = runtime.getCurrentSession(); var objRec = currentRecord.get(); for ( var key in objSess ) { var value = sessionObj.get({name: key}); objRec.setValue({ fieldId: key, value: value }); } }

Et voilà, all the data is back in the UI.

Now, this script sample does not leverage on a generic scan across all fields on the transaction record, something I would not recommend in light of client side processing. (Remember: Whenever possible, outsource extensive sourcing and searches in particular into backend Suitelets or even Map/Reduce scripts.) A dozen number of fields should be manageable, though.

In case you are curious about the Popup Workflow and the mavenchecks custom module, drop us a line! The code is freely available on our repository.


E-mail for contacts








Office Location


© 2020 Cloudmaven - Terms and Conditions