Scenario:
The client wanted to develop a functionality that updates the assembly item components whenever the items are updated in Work order for this assembly item.
Solution:
/**
* @NApiVersion 2.x
* @NScriptType UserEventScript
* @NModuleScope SameAccount
*/
/*************************************************************************************************
* Script to update assembly item components when work order item lines are updated.
* ************************************************************************************************
* APCN-440
*
* Date: 16 - January - 2023
*
* Author: Jobin & Jismi IT Services LLP
*
***************************************************************************************************/
define(['N/file', 'N/url', 'N/search', 'N/runtime', 'N/record', 'N/https', 'N/ui/serverWidget', 'N/email'],
function (file, url, search, runtime, record, https, serverWidget, email) {
var main = {
afterSubmit: function (scriptContext) {
log.debug("***Execution Started***")
if (scriptContext.type == "create" || "edit") {
log.debug("scriptContext.newRecord", scriptContext.newRecord)
var id = scriptContext.newRecord.id
var workOrderCount = main.isWoNotBuilt(id)
if (workOrderCount && workOrderCount > 0) {
var woRec = scriptContext.newRecord
var woRecOld = scriptContext.oldRecord
var assembly = woRec.getValue({fieldId: 'assemblyitem'})
var builtQty = woRec.getValue({fieldId: 'quantity'})
var assemblyComponents = main.getAssemblyComponents(assembly)
log.debug("assemblyComponents", assemblyComponents)
if (assemblyComponents.length > 0) {
//get the WO item sublist in newRecord and oldRecord contexts
var woItems = main.getWoItemSublistArrays(woRec, woRecOld, assembly, builtQty, assemblyComponents)
}
}
}
},
/**
* Funtion for fetching the details of assembly item components
* @param assembly
* @returns {*[]|[*[], {}]}
*/
getAssemblyComponents: function (assembly) {
try {
var itemSearchObj = search.create({
type: "item",
filters:
[
["type", "anyof", "Assembly"],
"AND",
["internalid", "anyof", assembly]
],
columns:
[
search.createColumn({
name: "internalid",
join: "memberItem",
label: "Internal ID"
}),
search.createColumn({name: "memberquantity", label: "Member Quantity"})
]
});
var compObj = {}, returnArray = [], item
var searchResultCount = itemSearchObj.runPaged().count;
log.debug("itemSearchObj result count", searchResultCount);
if (searchResultCount > 0) {
itemSearchObj.run().each(function (result) {
item = result.getValue({
name: "internalid",
join: "memberItem",
label: "Internal ID"
})
compObj[item] = result.getValue({name: "memberquantity", label: "Member Quantity"})
returnArray.push(item)
return true;
});
return [returnArray, compObj];
} else
return []
} catch (e) {
log.debug("Error@ getAssemblyComponents", e.message)
return []
}
},
/**
* Function that fetches the WO item lines and calls the function for updating assembly item components
* @param newRec
* @param oldRec
* @param assembly
* @param builtQty
* @param assemblyComponents
*/
getWoItemSublistArrays: function (newRec, oldRec, assembly, builtQty, assemblyComponents) {
var woDoc = newRec.id
var lineCount_new = newRec.getLineCount({sublistId: 'item'})
var itemArray_new = [], objNew = {}
for (var j = 0; j < lineCount_new; j++) {
var item = newRec.getSublistValue({sublistId: 'item', fieldId: 'item', line: j})
var qty = newRec.getSublistValue({sublistId: 'item', fieldId: 'quantity', line: j})
objNew[item] = qty
itemArray_new.push(item)
}
var insertArray = [], insertObjArr = [], deleteArray = [], updateArray = []
//insertion scenario
insertArray = main.filterArray(itemArray_new, assemblyComponents[0])
//remove the inactive and items other than inventort, noninventory, other charge, service and assembly items
for (var k = 0; k < insertArray.length; k++) {
var itemData = search.lookupFields({
type: 'item',
id: insertArray[k],
columns: ['recordtype', 'isinactive']
});
var itemType = itemData.recordtype
var isInactive = itemData.isinactive
log.debug('itemType', itemType)
if ((itemType == 'inventoryitem' || itemType == 'noninventoryitem' || itemType == 'otherchargeitem' || itemType == 'serviceitem' || itemType == 'assemblyitem') && !isInactive) {
if (objNew[insertArray[k]]) {
var obj = {}
obj[insertArray[k]] = objNew[insertArray[k]]
insertObjArr.push(obj)
//insertArray[k] = obj
}
}
}
deleteArray = main.filterArray(assemblyComponents[0], itemArray_new)
updateArray = main.getUpdatedQuantityArray(assemblyComponents[1], objNew, builtQty)
log.debug("insertArray", insertObjArr)
log.debug("deleteArray", deleteArray)
log.debug("updateArray", updateArray)
//update the assembly item
main.updateAssemblyComponents(insertObjArr, deleteArray, updateArray, assembly, builtQty, woDoc)
},
filterArray: function (ar1, ar2) {
var elmts = ar1.filter(
function (i) {
return this.indexOf(i) < 0;
},
ar2
);
return elmts
},
/**
* Function that inserts/updates/deletes assembly item components as per the work order update.
* @param insertArray
* @param deleteArray
* @param updateArray
* @param assembly
* @param builtQty
* @param woDoc
* @returns {*|number}
*/
updateAssemblyComponents: function (insertArray, deleteArray, updateArray, assembly, builtQty, woDoc) {
//load the assembly item record
if (insertArray.length > 0 || deleteArray.length > 0 || Object.keys(updateArray).length > 0) {
var assemblyItem = record.load({
type: record.Type.ASSEMBLY_ITEM,
id: assembly,
isDynamic: true
})
var memberLineCount = assemblyItem.getLineCount({sublistId: 'member'})
//delete component
for (var d = 0; d < deleteArray.length; d++) {
var deleteLine = assemblyItem.findSublistLineWithValue({
sublistId: 'member',
fieldId: 'item',
value: deleteArray[d]
});
log.debug("delete line", deleteLine)
assemblyItem.removeLine({
sublistId: 'member',
line: deleteLine,
ignoreRecalc: true
});
}
//update component
for (var key in updateArray) {
var updateLine = assemblyItem.findSublistLineWithValue({
sublistId: 'member',
fieldId: 'item',
value: key
});
log.debug("updateLine", updateLine)
var selectLine = assemblyItem.selectLine({
sublistId: 'member',
line: updateLine
})
assemblyItem.setCurrentSublistValue({
sublistId: 'member',
fieldId: 'quantity',
value: updateArray[key],
ignoreFieldChange: true
});
assemblyItem.commitLine({
sublistId: 'member'
});
}
//insert component
memberLineCount = assemblyItem.getLineCount({sublistId: 'member'})
for (var k = 0; k < insertArray.length; k++) {
// var insertElement = Object.keys(insertArray)
// log.debug("insert condition", insertElement)
var insertElement_key = Object.keys(insertArray[k])[0]
var insertElement_value = insertArray[k][insertElement_key]
var newQty = insertElement_value / builtQty
var insertLine = assemblyItem.selectNewLine({
sublistId: 'member'
})
assemblyItem.setCurrentSublistValue({
sublistId: 'member',
fieldId: 'item',
value: insertElement_key
})
assemblyItem.setCurrentSublistValue({
sublistId: 'member',
fieldId: 'quantity',
value: Number(newQty.toFixed(2))
})
assemblyItem.commitLine({
sublistId: 'member'
});
}
assemblyItem.setValue({fieldId: 'custitem_jj_related_wo', value: woDoc})
var assemblyRec = assemblyItem.save({ignoreMandatoryFields: true, enableSourcing: true})
return assemblyRec;
}
},
/**
* Function that returns the updated item lines in work order
* @param objOld
* @param objNew
* @param qty
* @returns {{}}
*/
getUpdatedQuantityArray: function (objOld, objNew, qty) {
log.debug('objOld in function', objOld)
log.debug('objNew in function', objNew)
var returnArray = [], obj = {}
for (var key in objNew) {
objNew[key] = (objNew[key] / qty).toFixed(2)
if (objOld[key] && (Number(objNew[key]) != Number(objOld[key]))) {
obj[key] = objNew[key]
}
}
return obj;
},
/**
* Function to check whether the work order is in status released/in process with built qty 0
* @param woRec
* @returns {number}
*/
isWoNotBuilt: function (woRec) {
try {
var workorderSearchObj = search.create({
type: "workorder",
filters:
[
["type", "anyof", "WorkOrd"],
"AND",
["built", "equalto", "0"],
"AND",
["status", "anyof", "WorkOrd:B", "WorkOrd:D"],
"AND",
["internalid", "anyof", woRec],
"AND",
["cogs", "is", "F"],
"AND",
["shipping", "is", "F"],
"AND",
["taxline", "is", "F"],
"AND",
["account", "anyof", "333"]
],
columns:
[
search.createColumn({name: "tranid", label: "Document Number"}),
]
});
var searchResultCount = workorderSearchObj.runPaged().count;
log.debug("workorderSearchObj result count", searchResultCount);
return searchResultCount;
} catch (e) {
log.debug("Error @ isWoNotBuilt", e.message)
return false
}
}
}
return main;
});