SES Tag Integration

define(['N/error', 'N/file', 'N/https', 'N/search', 'N/url', 'N/runtime'],
    /**
     * @param{error} error
     * @param{file} file
     * @param{http} https
     * @param{search} search
     * @param{url} url
     * @param {runtime} runtime
     */
    (error, file, https, search, url, runtime) => {
        "use strict";

        let pageSize = 1000;
        /**
         * Different stores IDs from Vusion manager
         */
        const STORE_IDS = {
            "CONCORD": "airporthomeappliance_us.concord1505",
            "DUBLIN": "airporthomeappliance_us.dublin6842",
            "EMERYVILLE": "airporthomeappliance_us.emeryville5815",
            "HAYWARD": "airporthomeappliance_us.hayward3525",
            "REDWOODCITY": "airporthomeappliance_us.redwoodcity2424",
            "ROSEVILLE": "airporthomeappliance_us.roseville1251",
            "SANJOSE": "airporthomeappliance_us.sanjose966",
            "SANRAFAEL": "airporthomeappliance_us.sanrafael777",
        };
        /**
         * Inventory location IDs
         */
        const INVENTORY_LOCATIONS = {
            "PRODUCT_DISTRIBUTION_CENTER": "26"
        };
        /**
         * The status of items that needs to be send
         */
        const ITEM_STATUS = {
            "A": "1",
            "B": "2",
            "O": "5"
        };
        /**
         * function to post csv file
         * @param file
         * @returns {*}
         * Returns response of API call
         */
        function accessDetails(fileContent) {
            try {
                let responseArray = [];
                let headers = [];
                headers['Content-Type'] = "application/octet-stream";
                headers['Ocp-Apim-Subscription-Key'] = "a607c5f78d3748269797004007728360";
                if (checkForParameter(fileContent)) {
                    for (let key in STORE_IDS) {
                        log.debug("key", STORE_IDS[key])
                        let response = https.post({
                            url: `https://api-us.vusion.io/vcloud/v1/stores/${STORE_IDS[key]}/items/files/Inventory_Item_Details.csv`,
                            headers: headers,
                            body: fileContent
                        });
                        log.debug("response", response)
                        responseArray.push(response)
                    }
                }
                return responseArray
            } catch (e) {
                log.error("error@accessDetails", e);
                return [];
            }
        }
        /**
         * To check whether a value exists in parameter
         * @param parameter
         * @param parameterName
         * @returns {boolean}
         */
        function checkForParameter(parameter, parameterName) {
            if (parameter !== "" && parameter !== null && parameter !== undefined && parameter !== false && parameter !== "null" && parameter !== "undefined" && parameter !== " " && parameter !== 'false') {
                return true;
            } else {
                if (parameterName)
                    log.debug('Empty Value found', 'Empty Value for parameter ' + parameterName);
                return false;
            }
        }
        /**
         * to fetch and format the single saved search result. ie, Search result of a single row containing both text and value for each columns.
         * to format the contents as required
         * @param searchResult
         * @param columns
         * @returns {{}}
         * Returns response object
         */
        function formatSingleSavedSearchResult(searchResult, columns) {
            let responseObj = {};
            for (let column in columns) {
                if ((column == "Sales Description") || (column == "Name")) {
                    let resVal = searchResult.getValue(columns[column]).replace(/,/g, "|");// Replaced comma (,) with (|) to avoid column seperation
                    let resValTrim = resVal.trim();
                    responseObj[column] = resValTrim.replace(/[nr]+/g, " ");
                } else if ((column == "Brand") || (column == "Item Status")) {
                    responseObj[column] = searchResult.getText(columns[column]).replace(/,/g, "|");// Replaced comma (,) with (|) to avoid column seperation
                } else if (column == "MSRP") {
                    responseObj[column] = searchResult.getValue(columns[column]).replace(/,/g, "");// Replaced comma (,) with empty for amount to avoid column seperation
                } else {
                    responseObj[column] = searchResult.getValue(columns[column]);
                }
            }
            return responseObj;
        }
        /**
         * @description to iterate over and initiate format of each saved search result
         * @param {Object} param
         * @param {SearchObj} param.searchObj
         * @param {void|Object.<String,SearchObj.columns>} param.columns
         * @param {number} param.PAGE_INDEX
         * @param {number} param.PAGE_SIZE
         * @returns {[]|Object[]}
         */
        function iterateSavedSearch(searchObj, columns, PAGE_INDEX, PAGE_SIZE) {
            if (!checkForParameter(searchObj))
                return false;
            if (!checkForParameter(columns))
                columns = fetchSavedSearchColumn(searchObj);

            let response = [];
            let searchPageRanges;
            try {
                searchPageRanges = searchObj.runPaged({
                    pageSize: Number.isInteger(Number(PAGE_SIZE)) ? parseInt(Number(PAGE_SIZE)) : 500 //Default Page Size
                });
            } catch (err) {
                return Number.isInteger(PAGE_INDEX) ? {
                    pageInfo: {
                        pageLength: 1,
                        pageIndex: 1,
                        isLastPage: true
                    },
                    lines: []
                } : [];
            }
            if (searchPageRanges.pageRanges.length < 1)
                return Number.isInteger(PAGE_INDEX) ? {
                    pageInfo: {
                        pageLength: 1,
                        pageIndex: 1,
                        isLastPage: true
                    },
                    lines: []
                } : [];

            let pageRangeLength = searchPageRanges.pageRanges.length;
            //log.debug('pageRangeLength', pageRangeLength);

            //To make sure the pageIndex has minimum value of one and maximum value of pageRangeLength
            const pageIndexRangeRectifier = function (value, pageRange) {
                //log.debug("value pagrng", value + ' ' + pageRange)
                if (!Number.isInteger(Number(value)))
                    return 1;
                if ((Number(value) - 1) <= 0)
                    return 1;
                if ((Number(value) - 1) >= Number(pageRange))
                    return Number(pageRange);
                return Number(value);
            };

            if (Number.isInteger(PAGE_INDEX))
                searchPageRanges.fetch({
                    index: pageIndexRangeRectifier(PAGE_INDEX, pageRangeLength) - 1
                }).data.forEach(function (result) {
                    response.push(formatSingleSavedSearchResult(result, columns, true));
                });
            else
                for (let pageIndex = 0; pageIndex < pageRangeLength; pageIndex++)
                    searchPageRanges.fetch({
                        index: pageIndex
                    }).data.forEach(function (result) {
                        response.push(formatSingleSavedSearchResult(result, columns));
                    });

            return Number.isInteger(PAGE_INDEX) ? {
                pageInfo: {
                    pageLength: pageRangeLength,
                    pageIndex: Number(pageIndexRangeRectifier(PAGE_INDEX, pageRangeLength)),
                    isLastPage: Number(pageIndexRangeRectifier(PAGE_INDEX, pageRangeLength)) >= Number(pageRangeLength) ? true : false
                },
                lines: response
            } : response;
        }

        /**
         * @description to format Saved Search column to key-value pair where each key represents each columns in Saved Search
         * @param {Search} savedSearchObj
         * @param {void|String} priorityKey
         * @returns {Object.<String,SearchObj.columns>}
         */
        function fetchSavedSearchColumn(savedSearchObj, priorityKey) {
            let columns = savedSearchObj.columns;
            let columnsData = {}, columnName = '';
            columns.forEach((result, counter) => {
                columnName = '';
                if (result[priorityKey]) {
                    columnName += result[priorityKey];
                } else {
                    if (result.summary)
                        columnName += result.summary + '__';
                    if (result.formula)
                        columnName += result.formula + '__';
                    if (result.join)
                        columnName += result.join + '__';
                    columnName += result.name + '__' + counter?.toString();
                }
                columnsData[columnName] = result;
            });
            return columnsData;
        }

        /**
         * function to create item saved search
         * @returns {*[]}
         * Returns saved search result after iteration
         */
        function itemSavedSearch() {
            try {
                let arrFinal = [];
                let inventoryitemSearchObj = search.create({
                    type: "inventoryitem",
                    filters:
                        [
                            ["type", "anyof", "InvtPart"],
                            "AND",
                            ["totalquantityonhand", "greaterthan", "0"],
                            "AND",
                            ["isinactive", "is", "F"],
                            "AND",
                            ["inventorylocation", "anyof", INVENTORY_LOCATIONS.PRODUCT_DISTRIBUTION_CENTER],
                            "AND",
                            ["custitem_aha_item_status", "anyof", Object.values(ITEM_STATUS)]
                        ],
                    columns:
                        [
                            search.createColumn({
                                name: "itemid",
                                sort: search.Sort.ASC,
                                label: "Name"
                            }),
                            search.createColumn({ name: "custitem_jj_strdigtt_ahap2213", label: "Sales Description" }),
                            search.createColumn({ name: "custitem_aha_sales_price", label: "Sales Price" }),
                            search.createColumn({ name: "custitem42", label: "Sales Margin %" }),
                            search.createColumn({ name: "locationquantityavailable", label: "Available" }),
                            search.createColumn({ name: "totalquantityonhand", label: "Total Quantity On Hand" }),
                            search.createColumn({ name: "cseg_aha_brand", label: "Brand" }),
                            search.createColumn({ name: "custitem39_2", label: "Rebate Available" }),
                            search.createColumn({ name: "custitem_aha_item_status", label: "Item Status" }),
                            search.createColumn({ name: "custitem_msrp", label: "MSRP" }),
                            search.createColumn({ name: "custitem37", label: "PTS" }),
                            search.createColumn({
                                name: "formulatext",
                                formula: "{custitem1}",
                                label: "Website URL"
                            }),
                            search.createColumn({ name: "custitem28", label: "Depth (IN)" }),
                            search.createColumn({ name: "custitem29", label: "Width (IN)" }),
                            search.createColumn({ name: "custitem30", label: "Height (IN)" })
                        ]
                });
                let searchResultCount = inventoryitemSearchObj.runPaged().count;
                let searchPageCount = Number.isInteger(Number(searchResultCount)) ? Number(Math.ceil(searchResultCount / pageSize)) : 0;
                for (let i = 1; i <= searchPageCount; i++) {
                    let arrResult = iterateSavedSearch(inventoryitemSearchObj, fetchSavedSearchColumn(inventoryitemSearchObj, 'label'), i, pageSize).lines
                    arrFinal = arrFinal.concat(arrResult);
                    //log.debug('arrResult', arrResult.length)
                }
                return arrFinal;
            } catch (e) {
                log.error("error@itemSavedSearch", e);
                return []
            }
        }
        /**
         * function to create open box saved search
         */
        const openBoxItemSearch = () => {
            try {
                let arrFinal = [];
                let customrecord_jj_open_box_item_log1108SearchObj = search.create({
                    type: "customrecord_jj_open_box_item_log1108",
                    filters:
                        [
                            ["custrecord_jj_open_box_display", "isnotempty", ""],
                            "AND",
                            ["isinactive", "is", "F"]
                        ],
                    columns:
                        [
                            search.createColumn({ name: "custrecord_jj_open_box_display", label: "Name" }),
                            // search.createColumn({ name: "custrecord_jj_descrip_openboxlog1149", label: "Sales Description" }),
                            search.createColumn({
                                name: "custitem_jj_strdigtt_ahap2213",
                                join: "CUSTRECORD_JJ_ITEM_NAME_OPENBOXLOG1149",
                                label: "Sales Description"
                             }),
                            search.createColumn({ name: "custrecord_jj_sales_price_openboxlog1149", label: "Sales Price" }),
                            search.createColumn({
                                name: "formulatext",
                                formula: "'N/A'",
                                label: "Sales Margin %"
                            }),
                            search.createColumn({
                                name: "formulatext",
                                formula: "'1'",
                                label: "Available"
                            }),
                            search.createColumn({
                                name: "formulatext",
                                formula: "'1'",
                                label: "Total Quantity On Hand"
                            }),
                            search.createColumn({ name: "custrecord_jj_brand_openboxlog_1149", label: "Brand" }),
                            search.createColumn({
                                name: "formulatext",
                                formula: "'FALSE'",
                                label: "Rebate Available"
                            }),
                            search.createColumn({ name: "custrecord_jj_status_openboxlog1149", label: "Item Status" }),
                            search.createColumn({
                                name: "custitem_msrp",
                                join: "CUSTRECORD_JJ_ITEM_NAME_OPENBOXLOG1149",
                                label: "MSRP"
                            }),
                            search.createColumn({
                                name: "formulatext",
                                formula: "'FALSE'",
                                label: "PTS"
                            }),
                            search.createColumn({
                                name: "formulatext",
                                formula: "{CUSTRECORD_JJ_ITEM_NAME_OPENBOXLOG1149.custitem1}",
                                label: "Website URL"
                            }),
                            search.createColumn({
                                name: "custitem_jj_website_depth_in_ahap1235",
                                join: "CUSTRECORD_JJ_ITEM_NAME_OPENBOXLOG1149",
                                label: "Depth (IN)"
                            }),
                            search.createColumn({
                                name: "custitem_jj_website_width_ahap1235",
                                join: "CUSTRECORD_JJ_ITEM_NAME_OPENBOXLOG1149",
                                label: "Width (IN)"
                            }),
                            search.createColumn({
                                name: "custitem_jj_website_height_ahap1235",
                                join: "CUSTRECORD_JJ_ITEM_NAME_OPENBOXLOG1149",
                                label: "Height (IN)"
                            }),
                        ]
                });
                let searchResultCount = customrecord_jj_open_box_item_log1108SearchObj.runPaged().count;
                log.debug("customrecord_jj_open_box_item_log1108SearchObj result count", searchResultCount);
                let searchPageCount = Number.isInteger(Number(searchResultCount)) ? Number(Math.ceil(searchResultCount / pageSize)) : 0;
                for (let i = 1; i <= searchPageCount; i++) {
                    let arrResult = iterateSavedSearch(customrecord_jj_open_box_item_log1108SearchObj, fetchSavedSearchColumn(customrecord_jj_open_box_item_log1108SearchObj, 'label'), i, pageSize).lines
                    arrFinal = arrFinal.concat(arrResult);
                    //log.debug('arrResult', arrResult.length)
                }
                return arrFinal;
            } catch (err) {
                log.error("error@openBoxItemSearch", err)
            }
        }
        /**
         * function to create CSV content
         * @param {*} arrayContent 
         * @returns 
         */
        const createCSV = (arrayContent) => {
            try {
                let csvContent = "Name" + ',' + "Sales Description" + ',' + "Sales Price" + ',' + "Sales Margin %" + ',' + "Available" + ',' + "Total Quantity On Hand" + ',' + "Brand" + ',' + "Rebate Available" + ',' + "Item Status" + ',' + "MSRP" + ',' + "PTS" + ',' + "Website URL" + "," + "Depth (IN)" + "," + "Width (IN)" + "," + "Height (IN)n";
                for (let i = 0; i < arrayContent.length; i++) {
                    for (let key of Object.keys(arrayContent[i])) {
                        csvContent += arrayContent[i][key];
                        if (key != "Height (IN)") {
                            csvContent += ','
                        }
                    }
                    csvContent += 'n'
                }
                return csvContent;
            } catch (err) {
                log.error("error@createCSV", err);
                return [];
            }
        }

        /**
         * Defines the function that is executed at the beginning of the map/reduce process and generates the input data.
         * @param {Object} inputContext
         * @param {boolean} inputContext.isRestarted - Indicates whether the current invocation of this function is the first
         *     invocation (if true, the current invocation is not the first invocation and this function has been restarted)
         * @param {Object} inputContext.ObjectRef - Object that references the input data
         * @typedef {Object} ObjectRef
         * @property {string|number} ObjectRef.id - Internal ID of the record instance that contains the input data
         * @property {string} ObjectRef.type - Type of the record instance that contains the input data
         * @returns {Array|Object|Search|ObjectRef|File|Query} The input data to use in the map/reduce process
         * @since 2015.2
         */

        const getInputData = (inputContext) => {
            try {
                if (runtime.envType == runtime.EnvType.PRODUCTION) {// checking the environment
                    let invSavedSearch = itemSavedSearch();
                    // log.debug(invSavedSearch.length + ' invSavedSearch', invSavedSearch);
                    let openBoxDetails = openBoxItemSearch();
                    // log.debug("openBoxDetails", openBoxDetails);
                    let sendData = invSavedSearch.concat(openBoxDetails);
                    let csvContent = createCSV(sendData);
                    // log.debug('csvContent', csvContent);
                    let response = accessDetails(csvContent);
                    log.debug('response', response);
                    return response;
                }
            } catch (e) {
                log.error("error@getInputData", e)
            }
        }

        /**
         * Defines the function that is executed when the reduce entry point is triggered. This entry point is triggered
         * automatically when the associated map stage is complete. This function is applied to each group in the provided context.
         * @param {Object} reduceContext - Data collection containing the groups to process in the reduce stage. This parameter is
         *     provided automatically based on the results of the map stage.
         * @param {Iterator} reduceContext.errors - Serialized errors that were thrown during previous attempts to execute the
         *     reduce function on the current group
         * @param {number} reduceContext.executionNo - Number of times the reduce function has been executed on the current group
         * @param {boolean} reduceContext.isRestarted - Indicates whether the current invocation of this function is the first
         *     invocation (if true, the current invocation is not the first invocation and this function has been restarted)
         * @param {string} reduceContext.key - Key to be processed during the reduce stage
         * @param {List<String>} reduceContext.values - All values associated with a unique key that was passed to the reduce stage
         *     for processing
         * @since 2015.2
         */
        const reduce = (reduceContext) => {
            try {
                let reducedValue = reduceContext.values[0];
            } catch (e) {
                log.error("error@reduce", e)
            }
        }
        return { getInputData, reduce }

    });

Leave a comment

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