How to create a single quote if customer requests multiple items in the same API call.

/**
 * @NApiVersion 2.1
 * @NScriptType MapReduceScript
 */
/************************************************************************************************
 * * Map reduce  Script For Creating Quote from Website Data
 *
 *
 * **********************************************************************************************
 * BLLF-413: Update- Quote Creation from Website API data
 *
 * Author: Jobin and Jismi IT Services
 *
 * Date Created :24 -May-2023
 *
 * Created By: Linu Paul, Jobin and Jismi IT Services
 *
 * Description : Map reduce script To create Quote from Website Data
 *
 * REVISION HISTORY
 *
 *
 ***********************************************************************************************/
define(['N/https', 'N/record', 'N/search'],
    /**
     * @param{https} https
     * @param{record} record
     * @param{search} search
     */
    (https, record, search) => {
        "use strict"
        /**
          * 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 {
                let request = https.get({
                    url: 'https://api.blueleafconnect.com/blueleaf/sandbox/quotes',
                    headers: {
                        'Authorization': 'Bearer rdoOdjnTPOkShpSJOix0fMQv8diOHdH2',
                        'Content-Type': 'application/json',
                        'Accept': 'application/json',
                    }
                });
                let Quote_Details = JSON.parse(request.body);
                return Quote_Details;
            }
            catch (e) {
                log.debug(e.message);
            }
        }

        /** Defines the function that is executed to search whether the quote id is already existed.
         * 
         * @param {number} quoteId - the Id of quote to check the existence
         * 
         * */


        let request_response = [];
        function search_Estimate(quoteId) {
            let estimateSearchObj = search.create({
                type: "estimate",
                filters:
                    [
                        ["type", "anyof", "Estimate"],
                        "AND",
                        ["otherrefnum", "equalto", quoteId]
                    ],
                columns:
                    [
                        search.createColumn({ name: "entity", label: "Name" }),
                        search.createColumn({
                            name: "internalid",
                            join: "customerMain",
                            label: "Internal ID"
                        }),
                        search.createColumn({
                            name: "internalid",
                            join: "item",
                            label: "Internal ID"
                        }),
                        search.createColumn({ name: "otherrefnum", label: "PO/Check Number" })
                    ]
            }).run().getRange({ start: 0, end: 1 });
            return estimateSearchObj;
        }

        /**
         * Defines the function that is executed when the map entry point is triggered. This entry point is triggered automatically
         * when the associated getInputData stage is complete. This function is applied to each key-value pair in the provided
         * context.
         * @param {Object} mapContext - Data collection containing the key-value pairs to process in the map stage. This parameter
         *     is provided automatically based on the results of the getInputData stage.
         * @param {Iterator} mapContext.errors - Serialized errors that were thrown during previous attempts to execute the map
         *     function on the current key-value pair
         * @param {number} mapContext.executionNo - Number of times the map function has been executed on the current key-value
         *     pair
         * @param {boolean} mapContext.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} mapContext.key - Key to be processed during the map stage
         * @param {string} mapContext.value - Value to be processed during the map stage
         * @since 2015.2
         */
        let customer_Search;
        const map = (mapContext) => {

            try {
                let quoteInfor = JSON.parse(mapContext.value);
                let customerId = quoteInfor['account_number'];
                let itemId = quoteInfor["variant_code"];
                let quotId = quoteInfor["id"];

                customer_Search = search.create({ //search for existence of customer
                    type: search.Type.CUSTOMER,
                    columns: ['entityid'],
                    filters: [['entityid', 'is', customerId],"and",["isinactive","is","F"]]
                }).run().getRange({ start: 0, end: 1 });

                let item_search = search.create({ //search for existence of Item
                    type: search.Type.ITEM,
                    columns: ['internalid'],
                    filters: [['itemid', 'is', itemId],"and",["isinactive","is","F"]]
                }).run().getRange({ start: 0, end: 1 });

                let iserror = false;
                let errormessage = "";

                if (customer_Search.length == 0) { // if customer not present
                    iserror = true;
                    errormessage = "Invalid Customer Id " + customerId;
                    log.debug("message", errormessage);
                }

                if (item_search.length == 0) { // if Item not present
                    iserror = true;
                    errormessage = "Invalid item Id " + itemId;
                    log.debug("message", errormessage);
                }

                let cusId;
                let detail = [];
                if (!iserror) {
                    detail.push(item_search[0].id);
                    detail.push(quotId);
                    mapContext.write({
                        key: customer_Search[0].id,
                        value: detail
                    });

                    let custom_record_search = search.create({
                        type: "customrecord_jjquotecreationstatus",
                        filters: ["name", "is", quotId],
                        columns: ["custrecord_jjerrormessage"]
                    }).run().getRange({ start: 0, end: 1 });
                    

                    if (custom_record_search.length > 0) {
                        let current_customRecord = record.load({
                            type: "customrecord_jjquotecreationstatus",
                            id: custom_record_search[0].id
                        });
                        current_customRecord.setValue({ fieldId: "custrecord_jjresolved", value: true });
                        current_customRecord.save({
                            ignoreMandatoryFields: true
                        });
                    }

                }

                if (iserror) {
                    let custom_record_search = search.create({
                        type: "customrecord_jjquotecreationstatus",
                        filters: ["name", "is", quotId],
                        columns: ["custrecord_jjerrormessage"]
                    }).run().getRange({ start: 0, end: 1 });

                    if (custom_record_search.length > 0) {
                        let current_customRecord = record.load({
                            type: "customrecord_jjquotecreationstatus",
                            id: custom_record_search[0].id
                        });
                        current_customRecord.setValue({ fieldId: "custrecord_jjerrormessage", value: errormessage });
                        current_customRecord.save({
                            ignoreMandatoryFields: true
                        })

                    }
                    else {
                        let customRecord = record.create({
                            type: 'customrecord_jjquotecreationstatus'
                        });
                        customRecord.setValue({ fieldId: "name", value: quotId });
                        customRecord.setValue({ fieldId: "custrecord_jjid", value: quotId });
                        customRecord.setValue({ fieldId: "custrecord_jjerrormessage", value: errormessage });
                        customRecord.save({
                            ignoreMandatoryFields: true
                        });
                    }
                }

            }
            catch (err) {
                log.error("error@mapfunction", err);
                return err.message;
            }
        }

        /**
         * 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
         */
        let idQuote = []
        const reduce = (reduceContext) => {
            try {
                let i,j;
                let reduceKey = reduceContext.key;
                let reduceValue = reduceContext.values;

                for (i = 0; i < reduceValue.length; i++) {
                    let parseValue = JSON.parse(reduceContext.values[i]);
                    for (j = 0; j < parseValue.length; j++) {
                        if (j == 1) {  
                            idQuote.push(parseValue[j])
                        }
                    }
                }

                let alreadyexists = false;

                let estimateSearchObj = search_Estimate(idQuote[0]);// Check for Id existence
                if (estimateSearchObj.length > 0) {
                    alreadyexists = true;
                    let errormessage = "Quote already Generated for ID " + idQuote[0];
                    log.debug("message", errormessage);
                }

                if (!alreadyexists) {
                    let QuoteRecord = record.create({
                        type: record.Type.ESTIMATE,
                        isDynamic: true
                    });

                    QuoteRecord.setValue({
                        fieldId: 'entity',
                        value: reduceKey
                    });

                    for (i = 0; i < reduceValue.length; i++) {
                        let parseValue = JSON.parse(reduceContext.values[i]);

                        for (j = 0; j < parseValue.length; j++) {
                            if (j == 0) {

                                QuoteRecord.selectNewLine({ //add a line to a sublist
                                    sublistId: 'item'      //specify which sublist
                                });

                                QuoteRecord.setCurrentSublistValue({   //set item field
                                    sublistId: 'item',
                                    fieldId: 'item',
                                    value: parseValue[j]
                                });
                                QuoteRecord.commitLine({  //writes the line entry into the loaded record
                                    sublistId: 'item'
                                });

                            }

                        }
                    }

                    QuoteRecord.setValue({
                        fieldId: 'otherrefnum',
                        value: idQuote[0]
                    });
                    let newQuote = QuoteRecord.save({    //writes record back to database
                        ignoreMandatoryFields: true
                    });

                    let quote_record_info = {
                        'request_id': idQuote[0],
                        'status': 'ACCEPTED'
                    };
                    request_response.push(quote_record_info);

                }
                idQuote = [];
                reduceContext.write({
                    key: request_response,
                    value: request_response
                });

            }
            catch (err) {
                log.error("error@reducefunction", err);
                return err.message;
            }

        }


        /**
         * Defines the function that is executed when the summarize entry point is triggered. This entry point is triggered
         * automatically when the associated reduce stage is complete. This function is applied to the entire result set.
         * @param {Object} summaryContext - Statistics about the execution of a map/reduce script
         * @param {number} summaryContext.concurrency - Maximum concurrency number when executing parallel tasks for the map/reduce
         *     script
         * @param {Date} summaryContext.dateCreated - The date and time when the map/reduce script began running
         * @param {boolean} summaryContext.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 {Iterator} summaryContext.output - Serialized keys and values that were saved as output during the reduce stage
         * @param {number} summaryContext.seconds - Total seconds elapsed when running the map/reduce script
         * @param {number} summaryContext.usage - Total number of governance usage units consumed when running the map/reduce
         *     script
         * @param {number} summaryContext.yields - Total number of yields when running the map/reduce script
         * @param {Object} summaryContext.inputSummary - Statistics about the input stage
         * @param {Object} summaryContext.mapSummary - Statistics about the map stage
         * @param {Object} summaryContext.reduceSummary - Statistics about the reduce stage
         * @since 2015.2
         */
        const summarize = (summaryContext) => {
            try {

                summaryContext.output.iterator().each(function (key, values) {
                    let keyDta = JSON.parse(key);
                    if (keyDta.length > 0) {
                        log.debug("response date", keyDta);
                        let response = https.post({
                            url: 'https://api.blueleafconnect.com/blueleaf/sandbox/quotes',
                            body: keyDta,
                            headers: {
                                'Authorization': 'Bearer rdoOdjnTPOkShpSJOix0fMQv8diOHdH2',
                                'Content-Type': 'application/json',
                                'Accept': 'application/json'
                            }
                        });
                        

                    }
                    else {
                        log.debug("No Quote created")
                    }
                    return true;

                });

            }
            catch (err) {
                log.error("error@summarizefunction", err);
                return err.message;
            }


        }
        return { getInputData, map, reduce, summarize }

    });

Leave a comment

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