Auto-Ship: Link Prescription to Auto-ship and Sales Order (Real Time)

Script handles linking prescription to line records/Auto-Ship (custom record) both with/without SO reference upon approval of prescription record(custom record); Similarly to Sales Order item Lines.

/**
 * @NApiVersion 2.x
 * @NScriptType UserEventScript
 * @NModuleScope SameAccount
 */

define(['N/record', 'N/search', 'N/url', 'N/https'],

    /**
     * @param {record} record
     */
    function (record, search, url, https) {

        /**
         * Function definition to be triggered before record is loaded.
         * @param {Object} context
         * @param {Record} context.newRecord - New record
         * @param {Record} context.oldRecord - Old record
         * @param {string} context.type - Trigger type
         * @Since 2015.2
         */

        const _AUTOSHIP_LINE_RECORD = "customrecord_vv_autoship_record";
        const _PRESCRIPTION_RECORD = "customrecord_vv_prescription";
        const _SHIPMENT_ITEM_RECORD = "customrecord_vv_shipment_item";

        const SCRIPTID_CREATE_SHIP = 'customscript_vv_sl_create_shipment';
        const DEPLOYID_CREATE_SHIP = 'customdeploy_vv_sl_create_shipment';

        /* SHIPMENT ITEM RECORD RECORD FIELDS */
        const _SPI_SO_LINE_KEY = "custrecord_vv_ship_item_line_key"
        const _SPI_SO_PARENT_SHIPMENT = "custrecord_vv_shipment";
        /* SHIPMENT ITEM RECORD RECORD FIELDS  */

        /* SO RECORD FIELDS */
        const PENDING_PRESCRIPTION = 1;
        const _SO_ITEM_TYPE = "itemtype";
        const _SO_LINE_UNIQUE_KEY = "lineuniquekey";
        const _SO_COMMITINVENTORY = "commitinventory"
        const _SO_PRESCRIPTION = "custcol_vv_so_prescription";
        const _SO_DATE_PRESC_LINKED = "custcol_vv_ue_date_linked";
        const _SO_IS_CLOSED = "isclosed";
        const _SO_IS_RX_ITEM = "custcol_vv_is_rx_item";
        const _SO_RX_HOLD = 'custbody_rxhold';
        /* SO RECORD FIELDS */

        /* AUTOSHIP CUSTOM RECORD FIELDS */
        const _AS_ITEM = "custrecord_vv_autoship_item"
        const _AS_SO_REFERENCE = "custrecord_vv_autoship_soref"
        const _AS_PET = "custrecord_vv_autoship_pet"
        const _AS_PRESCRIPTION = "custrecord_vv_autoship_prescription"
        const _AS_LINE_UNIQUE_KEY = "custrecord_vv_autoship_line_unique_key";
        const _AS_CUSTOMER_SRC = "custrecord_vv_autoship_customer_src";
        /* CUSTOM RECORD FIELDS */

        /* PRESCRIPTION RECORD FIELDS AND PRESCRIPTION ITEM RECORD FIELDS OBJ */
        const _APPROVED = "2";
        const _PR_STATUS = "custrecord_vv_prescription_status";
        const _PRESCRIPTION = {
            itemName: "custrecord_vv_item_name",
            prId: "custrecord_vv_prescription_id",
            refillQty: "custrecord_vv_refill_quantity",
            autoshipQty: "custrecord_vv_autoship_quantity",
            pet: "custrecord_vv_pet",
            customer: "custrecord_vv_customer"
        }

        /* PRESCRIPTION AND PRESCRIPTION ITEM RECORD FIELDS OBJ */

        function afterSubmit(context) {
            try {
                if (context.type === context.UserEventType.EDIT || context.type === context.UserEventType.XEDIT) {
                    var strOldRxStatus = context.oldRecord.getValue({fieldId: _PR_STATUS})
                    var recPrescription = record.load({type: _PRESCRIPTION_RECORD, id: context.newRecord.id});
                    var strNewRxStatus = recPrescription.getValue({fieldId: _PR_STATUS});

                    if (strOldRxStatus !== strNewRxStatus && strNewRxStatus === _APPROVED) {
                        var objPrescriptionData = searchItemsUnderPrescription(recPrescription.id);
                        log.debug("objPrescriptionData", JSON.stringify(objPrescriptionData))

                        //need to validate if there are items on this as we will omit the item if refillquantity = 0;
                        var prDataObjItems = objPrescriptionData.items

                        if (prDataObjItems.length) {

                            var objAutoShip = searchAutoShipLinesWithoutPrescription(prDataObjItems, objPrescriptionData.customer, objPrescriptionData.pet);
                            log.debug("objAutoShip", objAutoShip)

                            var prDataObjItemsQtyMap = objPrescriptionData.itemsqtymap

                            if (Object.keys(objAutoShip).length && prDataObjItemsQtyMap.length) {

                                var arrAutoShipPrescriptionMap = [];
                                var objSalesOrderMap = {};

                                for (var key in objAutoShip) {
                                    var strAutoShipLineId = key;
                                    var strItem = objAutoShip[key].item;
                                    var strSalesOrderId = objAutoShip[key].salesorder;
                                    var strLineUniqueKey = objAutoShip[key].lineuniquekey;
                                    var flQuantity = parseFloat(objAutoShip[key].quantity);

                                    var numObjIndex = findAttributeIndex(prDataObjItemsQtyMap, "item", strItem);
                                    var strRefillQty = prDataObjItemsQtyMap[numObjIndex].refillquantity

                                    if (numObjIndex >= 0 && strRefillQty >= flQuantity) {
                                        strRefillQty -= flQuantity

                                        arrAutoShipPrescriptionMap.push(strAutoShipLineId);

                                        if (strSalesOrderId) {
                                            if (!objSalesOrderMap.hasOwnProperty(strSalesOrderId)) {
                                                objSalesOrderMap[strSalesOrderId] = [];
                                            }

                                            objSalesOrderMap[strSalesOrderId].push(strLineUniqueKey);
                                        }
                                    }
                                }
                                log.debug("arrAutoShipPrescriptionMap", arrAutoShipPrescriptionMap)

                                for (var itr = 0; itr < arrAutoShipPrescriptionMap.length; itr++) {
                                    try {
                                        record.submitFields({
                                            type: _AUTOSHIP_LINE_RECORD,
                                            id: arrAutoShipPrescriptionMap[itr],
                                            values: {custrecord_vv_autoship_prescription: recPrescription.id},
                                            options: {ignoreMandatoryFields: true}
                                        })
                                    } catch (e) {
                                        record.submitFields({
                                            type: _AUTOSHIP_LINE_RECORD,
                                            id: arrAutoShipPrescriptionMap[itr],
                                            values: {custrecord_vv_autoship_prescription: recPrescription.id},
                                            options: {ignoreMandatoryFields: true}
                                        })
                                    }
                                }
                                log.debug("objSalesOrderMap", JSON.stringify(objSalesOrderMap))

                                var updateShipmentRecordsArr = [];
                                if (Object.keys(objSalesOrderMap).length) {
                                    for (var key in objSalesOrderMap) {
                                        try {
                                            var strNewSOId = null
                                            var noPrescription = false;
                                            var recSalesOrder = record.load({
                                                type: record.Type.SALES_ORDER,
                                                id: key
                                            });
                                            var lineCount = recSalesOrder.getLineCount({sublistId: 'item'})
                                            var objSalesOrderMapVal = objSalesOrderMap[key]
                                            for (var ctr = 0; ctr < objSalesOrderMapVal.length; ctr++) {
                                                var intLine = recSalesOrder.findSublistLineWithValue({
                                                    sublistId: "item",
                                                    fieldId: _SO_LINE_UNIQUE_KEY,
                                                    value: objSalesOrderMapVal[ctr]
                                                });
                                                if (intLine >= 0) {
                                                    recSalesOrder.setSublistValue({
                                                        sublistId: "item",
                                                        fieldId: _SO_PRESCRIPTION,
                                                        line: intLine,
                                                        value: recPrescription.id
                                                    });
                                                    recSalesOrder.setSublistValue({
                                                        sublistId: "item",
                                                        fieldId: _SO_DATE_PRESC_LINKED,
                                                        line: intLine,
                                                        value: new Date()
                                                    });
                                                    recSalesOrder.setSublistValue({
                                                        sublistId: "item",
                                                        fieldId: _SO_COMMITINVENTORY,
                                                        line: intLine,
                                                        value: 1
                                                    });

                                                    updateShipmentRecordsArr.push(objSalesOrderMapVal[ctr]);
                                                }
                                            }
                                            for (var i = 0; i < lineCount; i++) {
                                                var itemtype = recSalesOrder.getSublistValue({
                                                    sublistId: 'item',
                                                    fieldId: _SO_ITEM_TYPE,
                                                    line: i
                                                });
                                                var boolRXItem = recSalesOrder.getSublistValue({
                                                    sublistId: "item",
                                                    fieldId: _SO_IS_RX_ITEM,
                                                    line: i
                                                });
                                                var commit = recSalesOrder.getSublistValue({
                                                    sublistId: 'item',
                                                    fieldId: _SO_COMMITINVENTORY,
                                                    line: i
                                                });
                                                var isLineClosed = recSalesOrder.getSublistValue({
                                                    sublistId: 'item',
                                                    fieldId: _SO_IS_CLOSED,
                                                    line: i
                                                });
                                                var prescription = recSalesOrder.getSublistValue({
                                                    sublistId: "item",
                                                    fieldId: _SO_PRESCRIPTION,
                                                    line: i
                                                });

                                                if (itemtype === 'InvtPart') {
                                                    if (
                                                        (boolRXItem === true || boolRXItem === 'T')
                                                        && (prescription === null || prescription === '')
                                                        && commit === '1'
                                                        && (isLineClosed === false || isLineClosed === 'F')
                                                    ) {
                                                        noPrescription = true;
                                                    }
                                                }
                                            }
                                            log.debug("No Prescription", noPrescription)
                                            if (noPrescription) {

                                                recSalesOrder.setValue({
                                                    fieldId: _SO_RX_HOLD,
                                                    value: PENDING_PRESCRIPTION,
                                                });
                                                log.debug('RX HOLD is set to', PENDING_PRESCRIPTION);
                                            } else {
                                                recSalesOrder.setValue({
                                                    fieldId: _SO_RX_HOLD,
                                                    value: "",
                                                });
                                            }
                                            strNewSOId = recSalesOrder.save({
                                                enableSourcing: false,
                                                ignoreMandatoryFields: true
                                            });
                                            log.debug("SO SAVED - " + strNewSOId)
                                        } catch (e) {
                                            log.error("ERROR SAVING SO - " + recSalesOrder.id, e)
                                        }
                                    }
                                }

                                // Added 5/14/21 Update for Prescription Holds
                                if (updateShipmentRecordsArr.length > 0) {
                                    updateShipmentRecords(updateShipmentRecordsArr, "test");
                                }
                            }
                        }
                    }
                }
            } catch (err) {
                log.error("ERR", err)
            }
        }

        function updateShipmentRecords(soLineKeysArr, soId) {
            log.debug("updateShipmentRecords ENTRY", soLineKeysArr)
            var searchFiltersArr = [];
            var shipmentRecArr = [];
            var shipmentRecObj = {};
            for (var x = 0; x < soLineKeysArr.length; x++) {
                searchFiltersArr.push([_SPI_SO_LINE_KEY, "is", soLineKeysArr[x]]);
                if (x < soLineKeysArr.length - 1) {
                    searchFiltersArr.push("OR");
                }
            }

            var shipmentRecordBySOLine = search.create({
                type: _SHIPMENT_ITEM_RECORD,
                filters: searchFiltersArr,
                columns:
                    [
                        search.createColumn({
                            name: _SPI_SO_PARENT_SHIPMENT,
                            summary: "GROUP",
                            label: "Parent Shipment"
                        })
                    ]
            });

            shipmentRecordBySOLine.run().each(function (result) {
                var parentShipment = result.getValue({
                    name: _SPI_SO_PARENT_SHIPMENT,
                    summary: "GROUP",
                })

                shipmentRecArr.push(parentShipment);
                shipmentRecObj[parentShipment] = soId;
                return true;
            });

            if (shipmentRecArr.length > 0) {
                log.debug("Pass to SL Create Shipment (clearSyncFields)", shipmentRecArr);

                var urlSuitelet = url.resolveScript({
                    scriptId: SCRIPTID_CREATE_SHIP,
                    deploymentId: DEPLOYID_CREATE_SHIP,
                    returnExternalUrl: true,
                    params: {
                        custpage_presc_hold_update: true,
                        custpage_presc_hold_obj: JSON.stringify(shipmentRecObj)

                    }
                });
                var response = https.get({
                    url: urlSuitelet
                });
            }
        }

        function searchItemsUnderPrescription(strPrescriptionId) {
            var objSearchItems = search.create({
                type: _PRESCRIPTION_RECORD,
                filters: [
                    ["internalid", "anyof", strPrescriptionId]
                ],
                columns: [
                    search.createColumn({
                        name: _PRESCRIPTION.customer,
                        summary: "GROUP",
                        label: "Customer"
                    }),
                    search.createColumn({
                        name: _PRESCRIPTION.itemName,
                        join: _PRESCRIPTION.prId,
                        summary: "GROUP",
                        label: "Item Name"
                    }),
                    search.createColumn({
                        name: _PRESCRIPTION.refillQty,
                        join: _PRESCRIPTION.prId,
                        summary: "SUM",
                        label: "Quantity"
                    }),
                    search.createColumn({
                        name: _PRESCRIPTION.pet,
                        summary: "GROUP",
                        label: "Quantity"
                    })
                ]
            });

            var obj = {};
            obj["prescriptionid"] = strPrescriptionId;
            obj["items"] = []
            obj["itemsqtymap"] = [];
            objSearchItems.run().each(function (res) {
                var numRefillQty = res.getValue({
                    name: _PRESCRIPTION.refillQty,
                    join: _PRESCRIPTION.prId,
                    summary: "SUM"
                })
                var strItemName = res.getValue({
                    name: _PRESCRIPTION.itemName,
                    join: _PRESCRIPTION.prId,
                    summary: "GROUP"
                })
                var strCustomer = res.getValue({name: _PRESCRIPTION.customer, summary: "GROUP"})
                var strPet = res.getValue({name: _PRESCRIPTION.pet, summary: "GROUP"})

                obj["itemsqtymap"].push({
                    refillquantity: numRefillQty !== "" ? parseFloat(numRefillQty) : 0,
                    item: strItemName
                })
                obj["items"].push(strItemName)
                obj["customer"] = strCustomer
                obj["pet"] = strPet
                return true;
            });

            //we also look into inactive records as it might've been applied to a previous autoship
            var objAutoShipLineSearch = search.create({
                type: _AUTOSHIP_LINE_RECORD,
                filters: [
                    [_AS_PRESCRIPTION, "anyof", obj.prescriptionid],
                    "AND",
                    [_AS_ITEM, "anyof", obj.items]
                ],
                columns: [
                    search.createColumn({name: _PRESCRIPTION.autoshipQty, summary: "SUM"}),
                    search.createColumn({name: _AS_ITEM, summary: "GROUP"})
                ]
            });

            objAutoShipLineSearch.run().each(function (res) {
                var strItem = res.getValue({name: _AS_ITEM, summary: "GROUP"});
                var flQuantity = res.getValue({name: _PRESCRIPTION.autoshipQty, summary: "SUM"});
                var numObjIndex = findAttributeIndex(obj["itemsqtymap"], "item", strItem);
                if (numObjIndex >= 0) {
                    obj["itemsqtymap"][numObjIndex].refillquantity -= parseFloat(flQuantity);
                    if (obj["itemsqtymap"][numObjIndex].refillquantity <= 0) {

                        //remove item to lessen search results when looking for items autoship lines w/o prescription
                        var itemIndex = obj["items"].indexOf(strItem);
                        if (itemIndex >= 0) {
                            obj["items"].splice(itemIndex, 1)
                        }

                        //remove the mapping since we can no longer use this for autoship lines w/o prescription
                        obj["itemsqtymap"].splice(numObjIndex, 1);
                    }
                }
                return true;
            });

            return obj;
        }

        //only get autoship line record that contains a sales order so that future autoship orders are not considered
        //prescription are assigned differently for future autoship
        function searchAutoShipLinesWithoutPrescription(arrItems, strCustomerId, strPet) {
            var objSearchAutoShipLines = search.create({
                type: _AUTOSHIP_LINE_RECORD,
                filters: [
                    [_AS_PRESCRIPTION, "anyof", "@NONE@"],
                    "AND",
                    [_AS_ITEM, "anyof", arrItems],
                    "AND",
                    [_AS_CUSTOMER_SRC, "anyof", strCustomerId],
                    "AND",
                    [_AS_PET, "anyof", strPet],
                    "AND",
                    ["isinactive", "is", "F"]
                ],
                columns: [
                    search.createColumn({name: "internalid", label: "Internal ID"}),
                    search.createColumn({name: _AS_LINE_UNIQUE_KEY, label: "Line Unique Key"}),
                    search.createColumn({name: _AS_SO_REFERENCE, label: "SO#"}),
                    search.createColumn({name: _AS_ITEM, label: "Item"}),
                    search.createColumn({name: _PRESCRIPTION.autoshipQty, label: "Qty"})
                ]
            });

            var obj = {};
            objSearchAutoShipLines.run().each(function (res) {

                obj[res.getValue({name: "internalid"})] = {
                    item: res.getValue({name: _AS_ITEM}),
                    quantity: res.getValue({name: _PRESCRIPTION.autoshipQty}),
                    lineuniquekey: res.getValue({name: _AS_LINE_UNIQUE_KEY}),
                    salesorder: res.getValue({name: _AS_SO_REFERENCE}),
                };

                return true;
            });

            return obj;
        }


        function findAttributeIndex(array, attr, value) {
            for (var i = 0; i < array.length; i += 1) {
                if (array[i][attr] === value) {
                    return i;
                }
            }
            return -1;
        }

        return {
            afterSubmit: afterSubmit
        }
    }
);

Leave a comment

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