Updating Assembly Item Components From Work Order

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;

    });

Leave a comment

Your email address will not be published. Required fields are marked *