I'm not very familiar with SuiteScript or javascript in general (typically I'd just use workflows but I can't for this specific field 'Item Source'), but I am currently attempting to set the line 1 (linenumber) items' Item Source (itemsource) field to 'Stock' on a work order upon workflow edit if the custom line field Pack Out Item (custcol_is_packout) is checked. I've tried my hand at writing the code myself but I'm honestly not sure where to really begin, I've just been trying to piece it together using multiple sources online.
Here is my code (setup as a user event script, not sure if this is correct):
/**
* @NApiVersion 2.1
* @NScriptType UserEventScript
*/
define(['N/currentRecord', 'N/log', 'N/record'],
/**
* @param{currentRecord} currentRecord
* @param{log} log
* @param{record} record
*/
(currentRecord, log, record) => {
/**
* Defines the function definition that is executed before record is submitted.
* @param {Object} scriptContext
* @param {Record} scriptContext.newRecord - New record
* @param {Record} scriptContext.currentRecord - Current record
* @param {Record} scriptContext.oldRecord - Old record
* @param {string} scriptContext.type - Trigger type; use values from the context.UserEventType enum
* @since 2015.2
*/
const beforeSubmit = (scriptContext) => {
const curRec = scriptContext.currentRecord;
if (scriptContext.sublistId == 'item') {
const lineList = curRec.getCurrentSublistValue({
lineNum : 'linenumber',
packOut : 'custcol_is_packout'
});
if (lineNum == 0 && packOut == true) {
curRec.setCurrentSublistValue({
itemsource : 'Stock'
});
}
}
}
return {beforeSubmit}
});
I'm handling the event type (edit) and context (workflow) on the script deployment in NetSuite so I didn't add anything to filter for that in my code.
For some context:
I have a scheduled Workflow that runs every 30 minutes (based on a filtered saved search), the saved search only shows work orders created within the last 30 minutes that has a assembly item with the pack out item checkbox checked (on the item record).
The workflow sets the first component on the work order to be the same item as the assembly item, this is in order to circumvent the component loop error we get when building a BOM with the assembly as its own component.
The workflow works great, however these "packout" items are also Special Work Order items (meaning they auto-check the Create WO checkbox and set the Item Source to Work Order).
This is where the script comes in, I am attempting to catch the workflow editing the component line and set the item source on that line to Stock before submitting, this way that line doesn't generate a work order and create an infinite loop of work orders (because that generated work order would run on the workflow again and again).
My next question is, would this be a Client Script instead of a User Event Script?
Here is an edit of my script as a client script instead of a user event script, trying to use Krypton's advice, its still not changing the item source and I'm not getting any errors in my execution log:
/**
* @NApiVersion 2.x
* @NScriptType ClientScript
* @NModuleScope SameAccount
*/
define(['N/currentRecord', 'N/log', 'N/record'],
/**
* @param{currentRecord} currentRecord
* @param{log} log
* @param{record} record
*/
function(currentRecord, log, record) {
/**
* Function to be executed after sublist is inserted, removed, or edited.
*
* @param {Object} scriptContext
* @param {Record} scriptContext.currentRecord - Current form record
* @param {string} scriptContext.sublistId - Sublist name
*
* @since 2015.2
*/
function sublistChanged(scriptContext) {
const sublistVal = scriptContext.sublistId;
if (sublistVal === 'item') {
const curRec = scriptContext.currentRecord;
curRec.selectLine({
sublistId : 'item',
line : 0
});
packOut = curRec.getCurrentSublistValue({
sublistId : 'item',
fieldId : 'custcol_is_packout'
})
if(packOut == true) {
curRec.setCurrentSublistValue({
sublistId : 'item',
fieldId : 'itemsource',
value : 'Stock'
});
}
}
}
return {
sublistChanged: sublistChanged
};
});
Update:
Ok, so I managed to get the client script to work when manually editing the line (UI context) however the scheduled workflow doesn't appear to trigger the script. I'm not sure if I'm using the wrong function (currently using sublistChanged) or if this actually does need to be a User Event Script. Here is my client script:
/**
* @NApiVersion 2.x
* @NScriptType ClientScript
* @NModuleScope SameAccount
*/
define(['N/currentRecord', 'N/log', 'N/record'],
/**
* @param{currentRecord} currentRecord
* @param{log} log
* @param{record} record
*/
function(currentRecord, log, record) {
/**
* Function to be executed after sublist is inserted, removed, or edited.
*
* @param {Object} scriptContext
* @param {Record} scriptContext.currentRecord - Current form record
* @param {string} scriptContext.sublistId - Sublist name
*
* @since 2015.2
*/
function sublistChanged(scriptContext) {
const sublistVal = scriptContext.sublistId;
if (sublistVal == 'item') {
const curRec = scriptContext.currentRecord;
curRec.selectLine({
sublistId : 'item',
line : 0
});
const packOut = curRec.getSublistValue({
sublistId : 'item',
fieldId : 'custcol_is_packout',
line : 0
});
if(packOut == true) {
curRec.setCurrentSublistValue({
sublistId : 'item',
fieldId : 'itemsource',
value : 'STOCK'
});
curRec.commitLine({
sublistId : 'item'
});
}
}
}
return {
sublistChanged: sublistChanged
};
});
Update:
I've got this working as both a client side script and user event script upon manual user edit of the sublist (context = UI), however I'm still unable to get this to work upon workflow edit (context = scheduled workflow)... Heres my working user event script:
/**
* @NApiVersion 2.1
* @NScriptType UserEventScript
*/
define(['N/log', 'N/record'],
/**
* @param{log} log
* @param{record} record
*/
(log, record) => {
/**
* Defines the function definition that is executed after record is submitted.
* @param {Object} scriptContext
* @param {Record} scriptContext.newRecord - New record
* @param {Record} scriptContext.oldRecord - Old record
* @param {string} scriptContext.type - Trigger type; use values from the context.UserEventType enum
* @since 2015.2
*/
const afterSubmit = (scriptContext) => {
const curRec = scriptContext.newRecord;
const recId = curRec.id;
const recType = curRec.type;
const curWorkOrd = record.load({
type : recType,
id : recId,
isDynamic : true
});
curWorkOrd.selectLine({
sublistId : 'item',
line : 0
});
const packOut = curWorkOrd.getSublistValue({
sublistId : 'item',
fieldId : 'custcol_is_packout',
line : 0
});
if(packOut == true) {
curWorkOrd.setCurrentSublistValue({
sublistId : 'item',
fieldId : 'itemsource',
value : 'STOCK'
});
curWorkOrd.commitLine({
sublistId : 'item'
});
curWorkOrd.save();
}
}
return {afterSubmit}
});
Update:
I've created a workflow action script that isn't erroring, however its not updating the item source field, so kind of useless... Not sure if this is because I'm missing something or if maybe what I'm trying to do is not possible, but it seems like it should be possible so I'm a bit discouraged, heres that workflow action script code:
/**
* @NApiVersion 2.1
* @NScriptType WorkflowActionScript
*/
define(['N/action', 'N/workflow'],
/**
* @param{action} action
* @param{workflow} workflow
*/
(action, workflow) => {
/**
* Defines the WorkflowAction script trigger point.
* @param {Object} scriptContext
* @param {Record} scriptContext.newRecord - New record
* @param {Record} scriptContext.oldRecord - Old record
* @param {string} scriptContext.workflowId - Internal ID of workflow which triggered this action
* @param {string} scriptContext.type - Event type
* @param {Form} scriptContext.form - Current form that the script uses to interact with the record
* @since 2016.1
*/
const onAction = (scriptContext) => {
const curRec = scriptContext.newRecord;
curRec.selectLine({
sublistId : 'item',
line : 0
});
curRec.setCurrentSublistValue({
sublistId : 'item',
fieldId : 'itemsource',
value : 'STOCK'
});
}
return {onAction};
});
Final Update:
I managed to get the workflow action script to work by adding a single line to my above workflow script (commitLine), I'm going to accept Kryptons answer because he put me on the right track (Thank you!).
To answer some of my short-comings for anyone who might be giving this a try in the future:
The script deployment needs to be in a released status when testing the workflow.
The "All Roles" checkbox needs to be checked on the deployment under the Audience subtab.
If the script errors (caught in execution log), the workflow history won't update (I assume because the state isn't ending?).
Using log.debug({}); helped me make sure I wasn't working with null data and I just removed it after checking. (probably not best practice haha)
And now here is the working code:
/**
* @NApiVersion 2.1
* @NScriptType WorkflowActionScript
*/
define(['N/action', 'N/workflow'],
/**
* @param{action} action
* @param{workflow} workflow
*/
(action, workflow) => {
/**
* Defines the WorkflowAction script trigger point.
* @param {Object} scriptContext
* @param {Record} scriptContext.newRecord - New record
* @param {Record} scriptContext.oldRecord - Old record
* @param {string} scriptContext.workflowId - Internal ID of workflow which triggered this action
* @param {string} scriptContext.type - Event type
* @param {Form} scriptContext.form - Current form that the script uses to interact with the record
* @since 2016.1
*/
const onAction = (scriptContext) => {
const curRec = scriptContext.newRecord;
curRec.selectLine({
sublistId : 'item',
line : 0
});
curRec.setCurrentSublistValue({
sublistId : 'item',
fieldId : 'itemsource',
value : 'STOCK'
});
curRec.commitLine({
sublistId : 'item'
});
}
return {onAction};
});
There are a few issues with your script.
const curRec = scriptContext.currentRecord;
There is no currentRecord
passed in the User Event beforeSubmit()
context object. There is newRecord
, oldRecord
and type
. Probably what you want here is const curRec = scriptContext.newRecord;
if (scriptContext.sublistId == 'item') {
Again, there is no sublistId
property in the beforeSubmit
context. This appears to come from a client script. Used here, it will either give an error, or simply always evaluate to false, meaning the code within the if
block never runs.
const lineList = curRec.getCurrentSublistValue({
When using the "Current" versions of sublist APIs, you must first select the line using Record.selectLine()
(or curRec.selectLine()
in your case), make the change and then commit the line using Record.commitLine()
. However, even that may not work here, because I understand that the records passed in User Event contexts are in Standard or Deferred Dynamic mode, whereas the "Current" APIs are for working on Dynamic mode records. Therefore you should use the standard APIs, like getSublistValue()
instead of getCurrentSublistValue()
.
curRec.setCurrentSublistValue({
Same issue as above.
I'm handling the event type (edit) and context (workflow) on the script deployment in NetSuite so I didn't add anything to filter for that in my code.
This means that the script will only run when a workflow edits a record of the type the script is deployed on. So it may not run when a user edits it in the UI - is this really what you intend?