USER EVENT TO POPULATE THE ITEM PRICING SUBLIST VALUES BASED ON THE CUSTOM SUBLIST

/**
 * @NApiVersion 2.1
 * @NScriptType UserEventScript
 */
/* *MARUN-164 Custom Pricing management and synchronization**
*
*
* **********************************************************************************************
*
* Author: Jobin and Jismi IT Services
*
* Date Created : 25 November 2024
* Created By: Akshay B Nair, Jobin and Jismi IT Services
* Production movement: 
*
* Description : to populate the custom pricing in the standard Item pricing list
*
* REVISION HISTORY
* 
*
*
***********************************************************************************************/
/**
 * @NApiVersion 2.1
 * @NScriptType UserEventScript
 */


define(['N/record', 'N/log', 'N/ui/serverWidget', 'N/search'], (record, log, serverWidget, search) => {


    function getItemList(subsidiary) {


        try {


            let itemArray = []
            let itemSearchObj = search.create({
                type: "item",
                filters:
                    [
                        ["type", "anyof", "InvtPart", "NonInvtPart", "OthCharge", "Service"],
                        "AND",
                        ["subsidiary", "is", subsidiary],
                        "AND",
                        ["isinactive", "is", "F"],
                        "AND",
                        ["subtype", "anyof", "Resale", "Sale", "@NONE@"]
                    ],
                columns:
                    [
                        search.createColumn({ name: "itemid", label: "Name" }),
                        search.createColumn({ name: "internalid", label: "Internal ID" }),
                        search.createColumn({ name: "displayname", label: "Display Name" }),
                        search.createColumn({ name: "salesdescription", label: "Description" }),
                        search.createColumn({ name: "type", label: "Type" }),
                        search.createColumn({ name: "baseprice", label: "Base Price" }),


                    ]
            });
            let searchResultCount = itemSearchObj.runPaged().count;
            log.debug("itemSearchObj result count", searchResultCount);


            itemSearchObj.run().each(function (result) {
                itemArray.push({
                    itemId: result.getValue({ name: "internalid", label: "Internal ID" }),
                    itemName: result.getValue({ name: "itemid", label: "Name" })
                })
                // .run().each has a limit of 4,000 results
                return true;
            });
            return itemArray


        }
        catch (e) {
            log.error('error @GetItemList', e)
        }
    }


    function getNewCustomLineData(customerRecord, sublistId, lineCount) {
        try {
            let newCustomPricingRecords = [];
            for (let i = 0; i < lineCount; i++) {
                // Get the values from each line in the custom pricing sublist 
                let currency = customerRecord.getSublistValue({
                    sublistId: sublistId,
                    fieldId: 'custrecord_jj_pricelevel_currency', // Replace with actual field ID 
                    line: i
                });


                let priceLevel = customerRecord.getSublistValue({
                    sublistId: sublistId,
                    fieldId: 'custrecord_jj_pricelevel_pricelevel', // Replace with actual field ID 
                    line: i
                });


                let item = customerRecord.getSublistValue({
                    sublistId: sublistId,
                    fieldId: 'custrecord_jj_pricelevel_item', // Replace with actual field ID 
                    line: i
                });


                let unitPrice = customerRecord.getSublistValue({
                    sublistId: sublistId,
                    fieldId: 'custrecord_jj_pricelevel_unit_price', // Replace with actual field ID 
                    line: i
                });


                // Perform your custom logic here for each custom pricing record 
                log.debug('Custom Pricing Record', 'Currency: ' + currency + ', Price Level: ' + priceLevel + ', Item: ' + item + ', Unit Price: ' + unitPrice);
                let lineData = {
                    lineId: item + '_' + currency, // Unique identifier based on line number (1-indexed)
                    currency: currency,
                    priceLevel: priceLevel,
                    item: item,
                    unitPrice: unitPrice
                };


                // Add the object to the array
                newCustomPricingRecords.push(lineData)
            }
            return newCustomPricingRecords;
        }
        catch (e) {
            log.error('error @getNewCustomLineData', e)


        }
    }


    // Loop through the custom pricing records and perform logic 
    function getOldCustomLineData(oldRecord, sublistId, oldLineCount) {
        try {
            let oldCustomPricingRecords = [];
            for (let i = 0; i < oldLineCount; i++) {
                // Get the values from each line in the custom pricing sublist 
                let currency = oldRecord.getSublistValue({
                    sublistId: sublistId,
                    fieldId: 'custrecord_jj_pricelevel_currency', // Replace with actual field ID 
                    line: i
                });


                let priceLevel = oldRecord.getSublistValue({
                    sublistId: sublistId,
                    fieldId: 'custrecord_jj_pricelevel_pricelevel', // Replace with actual field ID 
                    line: i
                });


                let item = oldRecord.getSublistValue({
                    sublistId: sublistId,
                    fieldId: 'custrecord_jj_pricelevel_item', // Replace with actual field ID 
                    line: i
                });


                let unitPrice = oldRecord.getSublistValue({
                    sublistId: sublistId,
                    fieldId: 'custrecord_jj_pricelevel_unit_price', // Replace with actual field ID 
                    line: i
                });


                // Perform your custom logic here for each custom pricing record 
                log.debug('Custom Pricing Record Old', 'Currency: ' + currency + ', Price Level: ' + priceLevel + ', Item: ' + item + ', Unit Price: ' + unitPrice);
                let oldlineData = {
                    lineId: item + '_' + currency,
                    currency: currency,
                    priceLevel: priceLevel,
                    item: item,
                    unitPrice: unitPrice
                };
                oldCustomPricingRecords.push(oldlineData)
            }
            return oldCustomPricingRecords;


            // Example of validation or processing logic 


        }
        catch (e) {
            log.error('error@getOldCustomLineData', e)


        }
    }
    function getItemPricingLines(customerRecord) {
        try {
            let itemsublistId = 'itempricing'
            let itemPricinglineCount = customerRecord.getLineCount({
                sublistId: itemsublistId
            })
            let itemPricingRecords = [];


            // Loop through the custom pricing records and perform logic 
            for (let i = 0; i < itemPricinglineCount; i++) {
                // Get the values from each line in the custom pricing sublist 
                let currency = customerRecord.getSublistValue({
                    sublistId: itemsublistId,
                    fieldId: 'currency', // Replace with actual field ID 
                    line: i
                });


                let priceLevel = customerRecord.getSublistValue({
                    sublistId: itemsublistId,
                    fieldId: 'level', // Replace with actual field ID 
                    line: i
                });


                let item = customerRecord.getSublistValue({
                    sublistId: itemsublistId,
                    fieldId: 'item', // Replace with actual field ID 
                    line: i
                });


                let unitPrice = customerRecord.getSublistValue({
                    sublistId: itemsublistId,
                    fieldId: 'price', // Replace with actual field ID 
                    line: i
                });


                // Perform your custom logic here for each custom pricing record 
                log.debug('Item Pricing Record ', 'Currency: ' + currency + ', Price Level: ' + priceLevel + ', Item: ' + item + ', Unit Price: ' + unitPrice);
                let lineData = {
                    lineIndex: i,
                    lineId: item + '_' + currency, // Unique identifier based on line number (1-indexed)
                    currency: currency,
                    priceLevel: priceLevel,
                    item: item,
                    unitPrice: unitPrice
                };
                itemPricingRecords.push(lineData)


                // Example of validation or processing logic 
            }
            return itemPricingRecords;
        }
        catch (e) {
            log.error('error @getLineData', e)


        }
    }


    function getcomparedCustomData(getNewCustomLineDetails, getOldCustomLineDetails, getItemPricingDetails) {
        try {
            // Identify new lines (lineIds present in `getNewCustomLineDetails` but not in `getOldCustomLineDetails`)
            let newLines = getNewCustomLineDetails.filter(newLine =>
                !getOldCustomLineDetails.some(oldLine => oldLine.lineId === newLine.lineId)
            );


            log.debug('New Lines:', newLines);


            // Copy of `getItemPricingDetails` to be updated
            let updatedItemPricingDetails = [...getItemPricingDetails];


            // Iterate over new lines and check for updates
            newLines.forEach(newLine => {
                // Check if the `lineId` exists in `getItemPricingDetails`
                let existingLineIndex = updatedItemPricingDetails.findIndex(
                    existingLine => existingLine.lineId === newLine.lineId
                );


                if (existingLineIndex > -1) {
                    // If `lineId` exists, compare unit prices
                    let existingLine = updatedItemPricingDetails[existingLineIndex];
                    if (existingLine.unitPrice !== newLine.unitPrice) {
                        log.debug(`Updating unit price for lineId: ${newLine.lineId}`, {
                            oldUnitPrice: existingLine.unitPrice,
                            newUnitPrice: newLine.unitPrice,
                        });
                        // Update the unit price in the existing line
                        updatedItemPricingDetails[existingLineIndex].unitPrice = newLine.unitPrice;
                    }
                } else {
                    // If `lineId` does not exist, add it as a new line
                    let newLineToAdd = {
                        lineIndex: updatedItemPricingDetails.length, // Set index to the next available index
                        lineId: newLine.lineId,
                        currency: newLine.currency,
                        priceLevel: '-1', // Custom price level
                        item: newLine.item,
                        unitPrice: newLine.unitPrice,
                    };
                    updatedItemPricingDetails.push(newLineToAdd);
                }
            });


            return updatedItemPricingDetails;
        } catch (e) {
            log.error('Error @getcomparedCustomData:', e);
            // Return an empty array in case of error
        }
    }
    function toGetRemovalItemId(getOldCustomLineDetails, getNewCustomLineDetails, getItemPricingDetails) {
        try {
            let removedLines = getOldCustomLineDetails.filter(oldLine =>
                !getNewCustomLineDetails.some(newLine => newLine.lineId === oldLine.lineId)
            );
            log.debug('Removed Lines:', removedLines);
            let removalLines = {};
            removedLines.forEach(removedLine => {
                let matchingLine = getItemPricingDetails.find(item => item.lineId === removedLine.lineId);
                if (matchingLine) {
                    removalLines[removedLine.lineId] = matchingLine; // Store the matching line object in the `removalLines` object
                }
            });
            log.debug('removalLines inside', removalLines)
            return removalLines
        }
        catch (e) {
            log.error('error @toGetRemovalItemId')


        }
    }


    function togetCustomExistingItem(newCustomLineDetails) {
        try {
            // Initialize duplicate flag
            let isError = false;
            let uniqueLineIds = new Set();


            // Check for duplicates within newCustomLineDetails
            newCustomLineDetails.forEach((newLine) => {
                if (uniqueLineIds.has(newLine.lineId)) {
                    isError = true;
                    log.error('Duplicate Detected in newCustomLineDetails', `Line ID ${newLine.lineId} is duplicated within newCustomLineDetails.`);
                } else {
                    uniqueLineIds.add(newLine.lineId);
                }
            });


            return isError;
        } catch (e) {
            log.error('Error @togetCustomExistingItem', e);
            return false
        }
    }
    function toSetVirtualField(customerRecord) {
        try {
            let sublistId = 'recmachcustrecord_jj_pricelevel_customer'; // Sublist ID
            let lineCount = customerRecord.getLineCount({ sublistId });
            let virtualLineData = [];


            for (let i = 0; i < lineCount; i++) {
                // Get the virtual field value (custom item)
                let customItemValue = customerRecord.getSublistValue({
                    sublistId,
                    fieldId: 'custpage_custom_items', // Virtual field ID
                    line: i
                });


                // Log the custom field value for debugging
                log.debug(`Line ${i}: Custom Item Value`, customItemValue);


                // Set the retrieved custom item value to the 'custrecord_jj_pricelevel_item' field
                if (customItemValue) {
                    customerRecord.setSublistValue({
                        sublistId,
                        fieldId: 'custrecord_jj_pricelevel_item', // Field to set
                        line: i,
                        value: customItemValue
                    });


                    // Collect data for debugging
                    virtualLineData.push({
                        line: i,
                        customItem: customItemValue,
                        updatedField: 'custrecord_jj_pricelevel_item'
                    });
                }
            }


            // Log all updated virtual line data
            log.debug('Virtual Line Data Updated', virtualLineData);
        } catch (e) {
            log.error('Error @toSetVirtualField', e);
        }
    }


    function beforeLoad(scriptContext) {
        try {
            if (scriptContext.type === scriptContext.UserEventType.CREATE || scriptContext.type === scriptContext.UserEventType.EDIT) {
                let recordObj = scriptContext.newRecord;


                let form = scriptContext.form;
                let itemPricingSublist = form.getSublist({
                    id: 'recmachcustrecord_jj_pricelevel_customer'
                })
                let standardField = itemPricingSublist.getField({
                    id: 'custrecord_jj_pricelevel_item'
                });
                standardField.updateDisplayType({
                    displayType: serverWidget.FieldDisplayType.HIDDEN
                });


                let customItemField = itemPricingSublist.addField({
                    id: 'custpage_custom_items',
                    type: serverWidget.FieldType.SELECT,
                    label: 'Item'
                })
                itemPricingSublist.insertField({
                    field: customItemField,
                    nextfield: 'custrecord_jj_pricelevel_pricelevel'
                });
                customItemField.isMandatory = true;
                let subsidiary = recordObj.getValue({
                    fieldId: 'subsidiary'
                })
                if (subsidiary) {
                    log.debug('subsidiary', subsidiary)
                    // Ensure the custom field appears after the `custrecord_jj_pricelevel_pricelevel`
                    let itemDetailList = getItemList(subsidiary);
                    //log.debug('itemDetailList', itemDetailList)
                    customItemField.addSelectOption({ value: '', text: '' }); // Default option
                    itemDetailList.forEach((item) => {
                        customItemField.addSelectOption({
                            value: item.itemId,
                            text: item.itemName
                        });
                    });
                }
                else {
                    log.debug('the subsidiary is not available in customer creation')
                }
                let lineCount = recordObj.getLineCount({ sublistId: 'recmachcustrecord_jj_pricelevel_customer' });
                for (let i = 0; i < lineCount; i++) {
                    let existingItem = recordObj.getSublistValue({
                        sublistId: 'recmachcustrecord_jj_pricelevel_customer',
                        fieldId: 'custrecord_jj_pricelevel_item', // Field ID for the existing item
                        line: i
                    })


                    // Set the custom field value based on the existing item
                    itemPricingSublist.setSublistValue({
                        id: 'custpage_custom_items',
                        line: i,
                        value: existingItem || '' // Default to blank if no existing item
                    });


                }
            }
            // Only add the field in edit mode
            if (scriptContext.type === scriptContext.UserEventType.VIEW || scriptContext.type === scriptContext.UserEventType.EDIT) {
                let hideFld = scriptContext.form.addField({
                    id: 'custpage_hide_buttons',
                    label: 'not shown - hidden',
                    type: serverWidget.FieldType.INLINEHTML
                });
                let scr = 'jQuery("#newrecrecmachcustrecord_jj_pricelevel_customer").hide(); jQuery("#newrec626").hide();';
                hideFld.defaultValue = `<script>jQuery(function($){require([], function(){${scr};})})</script>`;
            }
        } catch (e) {
            log.error('error@beforeLoad', e);
        }
    }


    /**
     * beforeSubmit script to handle custom pricing and item pricing logic.
     */
    function beforeSubmit(scriptContext) {
        let isError = false;
        let errorMsg = 'The item must be unique';


        try {
            // Define error message and initialize variables


            // Validate scriptContext and ensure newRecord exists
            let customerRecord = scriptContext.newRecord;
            let oldRecord = scriptContext.oldRecord || {}; // Handle null oldRecord gracefully


            let customPricingSublistId = 'recmachcustrecord_jj_pricelevel_customer'; // Replace with actual sublist ID
            let itemPricingSublistId = 'itempricing'; // Sublist ID for item pricing
            // Get the number of custom pricing records
            let newLineCount = customerRecord.getLineCount({ sublistId: customPricingSublistId });
            let oldLineCount = oldRecord.getLineCount
                ? oldRecord.getLineCount({ sublistId: customPricingSublistId })
                : 0; // Default to 0 if oldRecord is missing


            log.debug('Custom Pricing Record Count', { newLineCount, oldLineCount });


            // Process custom pricing lines
            toSetVirtualField(customerRecord);
            let newCustomLineDetails = getNewCustomLineData(customerRecord, customPricingSublistId, newLineCount);
            let oldCustomLineDetails = getOldCustomLineData(oldRecord, customPricingSublistId, oldLineCount);
            let itemPricingDetails = getItemPricingLines(customerRecord);


            log.debug('New Custom Line Details', newCustomLineDetails);
            log.debug('Old Custom Line Details', oldCustomLineDetails);
            log.debug('Item Pricing Details', itemPricingDetails);


            // Check for errors in custom data
            isError = togetCustomExistingItem(newCustomLineDetails);


            // Identify lines to remove
            let removalItemIdDetails = toGetRemovalItemId(oldCustomLineDetails, newCustomLineDetails, itemPricingDetails);
            let removalLineIds = Object.keys(removalItemIdDetails);


            log.debug('Removal Item ID Details', removalItemIdDetails);
            log.debug('Removal Line IDs', removalLineIds);


            // Remove matching lines from the item pricing sublist
            let itemPricingLineCount = itemPricingDetails.length;
            for (let i = itemPricingLineCount - 1; i >= 0; i--) {
                let lineId = itemPricingDetails[i].lineId;
                if (removalLineIds.includes(lineId)) {
                    log.debug('Removing Line', { lineIndex: i, lineId });
                    customerRecord.removeLine({ sublistId: itemPricingSublistId, line: i });
                }
            }


            // Compare and update or add new lines
            let updatedItemPricingDetails = getcomparedCustomData(
                newCustomLineDetails,
                oldCustomLineDetails,
                itemPricingDetails
            );


            log.debug('Updated Item Pricing Details', updatedItemPricingDetails);


            newCustomLineDetails.forEach((detail) => {
                let existingLineIndex = itemPricingDetails.findIndex(
                    (line) => line.lineId === detail.lineId
                );


                if (existingLineIndex > -1) {
                    // Update existing line if the unit price has changed
                    let existingLine = itemPricingDetails[existingLineIndex];
                    if (existingLine.unitPrice !== detail.unitPrice) {
                        log.debug(`Updating existing line with lineId: ${detail.lineId}`, {
                            oldUnitPrice: existingLine.unitPrice,
                            newUnitPrice: detail.unitPrice,
                        });


                        customerRecord.setSublistValue({
                            sublistId: itemPricingSublistId,
                            fieldId: 'price', // Replace with actual field ID for unit price
                            line: existingLineIndex,
                            value: detail.unitPrice,
                        });
                    }
                } else {
                    // Add a new line if the lineId does not exist
                    let lineIndex = customerRecord.getLineCount({ sublistId: itemPricingSublistId });
                    log.debug('Adding New Line', { lineIndex, detail });


                    customerRecord.setSublistValue({
                        sublistId: itemPricingSublistId,
                        fieldId: 'item', // Replace with actual field ID for item
                        line: lineIndex,
                        value: detail.item,
                    });


                    customerRecord.setSublistValue({
                        sublistId: itemPricingSublistId,
                        fieldId: 'level', // Replace with actual field ID for price level
                        line: lineIndex,
                        value: '-1', // Custom price level
                    });


                    customerRecord.setSublistValue({
                        sublistId: itemPricingSublistId,
                        fieldId: 'currency', // Replace with actual field ID for currency
                        line: lineIndex,
                        value: detail.currency,
                    });


                    customerRecord.setSublistValue({
                        sublistId: itemPricingSublistId,
                        fieldId: 'price', // Replace with actual field ID for unit price
                        line: lineIndex,
                        value: detail.unitPrice,
                    });
                }
            });
        } catch (e) {
            log.error('Error @beforeSubmit', e);


        }
        if (isError === true) {
            throw errorMsg
        }



    }


    return {
        beforeLoad: beforeLoad,
        beforeSubmit: beforeSubmit,
    };
});

Leave a comment

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