Fetching Pipelines and Stages from HubSpot and setting up custom record in NetSuite

Requirement:

There can be several pipelines in hubspot account and there can be multiple stages in each of these pipelines. The requirement here is to fetch all the pipelines and their stages from HubSpot and create a custom record setup for these pipelines and stages in Netsuite. The custom records for stages will be created as child records of a parent pipeline record.

Solution:

/**
 * @NApiVersion 2.1
 * @NScriptType MapReduceScript
 */
/**
 * Script Description
 * This Map Reduce to fetch pipelines and their stages from netsuite and create a custom record setup in NetSuite
 *
 /*******************************************************************************
 * VCPP-43 HubSpot Integration
 * *******************************************************************************
 * $Author: Jobin & Jismi IT Services LLP $
 *
 * Date: 17-06-2022
 * DESCRIPTION

 *
 ******************************************************************************/
define(['N/http', 'N/https', 'N/record', 'N/runtime', 'N/search', 'N/url', './Hubspot Integration-Library.js'],
    /**
     * @param{http} http
     * @param{https} https
     * @param{record} record
     * @param{runtime} runtime
     * @param{search} search
     * @param{url} url
     */
    (http, https, record, runtime, search, url, hubspotLibrary) => {

        let library = hubspotLibrary.Library;
        let apiKey = 'f5e7d06f-8261-4837-b716-926476f8ce3a';

        /**
         * function that checks if a custom record entry already exists or not in netsuite
         * @param uniqueID
         * @param type
         * @returns {boolean|*}
         */
        function searchPipeline_StageRecord(uniqueID, type) {
            try {
                var customrecord_SearchObj = search.create({
                    type: type,
                    filters:
                        [
                            ["externalid", "is", uniqueID]
                        ],
                    columns:
                        [
                            search.createColumn({name: "internalid", label: "Internal ID"})
                        ]
                });
                var internalID;
                var searchResultCount = customrecord_SearchObj.runPaged().count;
                log.debug("customrecord_jj_deal_pipelineSearchObj result count", searchResultCount);
                if (searchResultCount > 0) {
                    customrecord_SearchObj.run().each(function (result) {
                        internalID = result.getValue({name: "internalid", label: "Internal ID"})
                        return false;
                    });
                    return internalID;
                }
                else
                    return false;
            } catch (e) {
                log.error("error@searchPipelineRecord", e)
                return false;
            }
        }

        const getInputData = (inputContext) => {
            try {
                //fetch the pipelines from hubspot
                let url = library.HUBSPOT_API_REQUESTS.GET_PIPELINES;
                url += apiKey;
                let httpMethod = 'GET'

                let Response = library.getRequestResults(url, "", httpMethod)
                log.debug("Response", Response)
                return Response;

            } catch (e) {
                log.error("Error@getInputData", e)
            }
        }

        const reduce = (reduceContext) => {
            try {
                let pipeline, stage;
                let pipelineData = JSON.parse(reduceContext.values)
                let label = pipelineData.label;
                let id = pipelineData.id;
                let uniqueID = id;

                //check if the pipeline already exists in netsuite
                let exist = searchPipeline_StageRecord(uniqueID, "customrecord_jj_deal_pipeline");


                if (!exist) {
                    //create a custom record entry for pipeline
                    let pipelineRec = record.create({
                        type: 'customrecord_jj_deal_pipeline',
                        isDynamic: true,
                    });
                    pipelineRec.setValue({fieldId: "name", value: label})
                    pipelineRec.setValue({fieldId: "custrecord_jj_deal_label", value: label})
                    pipelineRec.setValue({fieldId: "custrecord_jj_pipeline_id", value: id})
                    pipelineRec.setValue({fieldId: "externalid", value: uniqueID})
                    pipeline = pipelineRec.save({
                        enableSourcing: true,
                        ignoreMandatoryFields: true
                    });

                }
                else
                    pipeline = exist;

                //fetching stages of the pipeline
                let stages = pipelineData.stages;
                for (let i =0; i<stages.length; i++){
                    let stageLabel = stages[i].label;
                    let stageId = stages[i].id;
                    let stageUniqueId = stageId+"_"+pipeline;

                    //check if the stage already exists in netsuite
                    let existStage = searchPipeline_StageRecord(stageUniqueId, "customrecord_jj_deal_stage");
                    if (!existStage){
                        //create a custom record entry for deal stage
                        let stageRec = record.create({
                            type: 'customrecord_jj_deal_stage',
                            isDynamic: true,
                        });
                        stageRec.setValue({fieldId: "name", value: stageLabel})
                        stageRec.setValue({fieldId: "custrecord_jj_stage_label", value: stageLabel})
                        stageRec.setValue({fieldId: "custrecord_jj_stage_id", value: stageId})
                        stageRec.setValue({fieldId: "custrecord_jj_pipeline", value: pipeline})
                        stageRec.setValue({fieldId: "externalid", value: stageUniqueId})
                        stage = stageRec.save({
                            enableSourcing: true,
                            ignoreMandatoryFields: true
                        });
                    }
                }

            } catch (e) {
                log.error("Error@reduce", e)
            }

        }

        const summarize = (summaryContext) => {

        }

        return {getInputData, reduce, summarize}

    });

Library:

/************************************************************************************************
 * * Hubspot - Netsuite Integration **
 *  Library
 *
 * **********************************************************************************************
 *
 * Author: Jobin And Jismi
 *
 * Date Created : 16.06.2022
 *
 * Created By:  Jobin And Jismi
 *
 ***********************************************************************************************/
define(['N/config','N/runtime', 'N/record', 'N/search', 'N/format', 'N/error', 'N/encode', 'N/https', 'N/email'],

    function (config,runtime, record, search, format, error, encode, https, email) {
        var Library;
        (function () {

            var scriptContext;

            function setContext(context) {
                scriptContext = context;
            }

            var HUBSPOT_API_REQUESTS = {

                /*DEALS*/
                POST_DEALS: "https://api.hubapi.com/crm/v3/objects/deals/search?archived=false",
                GET_DEAL_ASSOCIATIONS_ITEM: "https://api.hubapi.com/crm/v3/objects/deals/{dealId}/associations/line_items?archived=false",
                GET_DEAL_ASSOCIATIONS_COMPANY: "https://api.hubapi.com/crm/v3/objects/deals/{dealId}/associations/companies?archived=false",
                UPDATE_DEAL_STAGE: "https://api.hubapi.com/crm/v3/objects/deals/{dealId}?archived=false",
                UPDATE_DEAL_PROPERTY: "https://api.hubapi.com/deals/v1/deal/{dealId}",

               /*ITEM_LINE*/
                GET_LINE_ITEM: "https://api.hubapi.com/crm/v3/objects/line_items/{line_item}?properties=hs_product_id&properties=hs_sku&properties=name&properties=quantity&properties=amount&properties=price&properties=description&archived=false",
                POST_LINE_ITEM: "https://api.hubapi.com/crm/v3/objects/line_items?archived=false",

                /*COMPANY*/
                GET_COMPANY: "https://api.hubapi.com/crm/v3/objects/companies/{companyid}?properties=netsuite_customer_id&properties=state&properties=city&properties=phone&properties=email&properties=name&properties=address&properties=zip&properties=country&archived=false",
                POST_COMPANY: "https://api.hubapi.com/crm/v3/objects/companies?archived=false",

                /*PIPELINE*/
                GET_PIPELINES: "https://api.hubapi.com/crm/v3/pipelines/deals",

                /*API_LIMIT*/
                GET_APILIMIT: "https://api.hubapi.com/integrations/v1/limit/daily"
            }

            try {
                Library = new HubspotLibrary();
            } catch (e) {
                log.error("error MagentoLibrary", e.message);
            }


            /**
             * Class to encapsulate Clutch Library functionality.
             */
            function HubspotLibrary() {
                this.setContext = setContext;
                this.HUBSPOT_API_REQUESTS = HUBSPOT_API_REQUESTS ;
                this.getRequestResults = getRequestResults;
                this.getRequesHeaders = getRequestHeaders;
            }

            /**
             * Get all the results from a Clutch request.
             *
             * @scope Private
             * @param {String} url - The URL to request and get the results from.
             * @param {Object} parameters - The parameters for the request.
             * @param {Object} headers - The headers for the request.
             * @param {String} httpMethod - The method for the request.
             * @return {Any} Results of request.
             */
            function getRequestResults(url, parameters, httpMethod) {
                var isMoreResults = false;
                var response = null;
                var responseBody = null;
                var headers = getRequestHeaders()
                log.debug("header", headers)

                var results = [];

                try {
                    do {
                        // reset definition of whether there are more results.
                        isMoreResults = false;

                        var requestObj = {
                            "method": httpMethod,
                            "url": url,
                            "headers": headers
                        }


                        if (parameters)
                            requestObj['body'] = parameters;
                        log.debug("requestObj", requestObj);

                        // request Clutch.
                        response = https.request(requestObj);
                        log.debug('response', response)

                        // get the body of request.
                        responseBody = response.body;

                        // convert body to JSON.
                        if (responseBody && typeof responseBody === "string" && (responseBody.charAt(0) == "{" || responseBody.charAt(0) == "[")) {
                            responseBody = JSON.parse(responseBody);
                        }


                        // if request was successful.
                        if (response.code === 200 || response.code === 204 || response.code === 201) {
                            // if pagination was returned.
                            if (responseBody && responseBody.results) {
                                // add results to existing.
                                results = results.concat(responseBody.results);
                                log.debug('results',results)
                                // get url for next request.
                            }
                            // if errors were returned.
                            else if (responseBody && responseBody.errors && responseBody.errors[0]) {
                                throw error.create({
                                    name: 'UNEXPECTED_ERROR',
                                    message: responseBody.errors[0].join("<br>")
                                });

                            } else {
                                results = responseBody;
                            }
                        } else if (response.code === 400) {
                            throw error.create({
                                name: response.code.toString() + "_BAD_REQUEST",
                                message: responseBody.detail,
                            });

                        } else if (response.code === 401) {
                            throw error.create({
                                name: response.code.toString() + "_UNAUTHORISED_REQUEST",
                                message: responseBody.detail
                            });

                        } else if (response.code === 404) {
                            throw error.create({
                                name: response.code.toString() + "_NOT_FOUND",
                                message: "An unexpected error occurred."
                            });

                        }

                        else if (response.code === 500) {

                            if (responseBody && responseBody.detail) {
                                throw error.create({
                                    name: response.code.toString() + "_INTERNAL_SERVER_ERROR",
                                    message: responseBody.detail
                                });

                            } else {
                                throw error.create({
                                    name: response.code.toString() + "_INTERNAL_SERVER_ERROR",
                                    message: "An unexpected error occurred."
                                });

                            }
                        } else {
                            var response_data = JSON.parse(response.body)

                            if (response.body && response_data["errors"]) {
                                throw error.create({
                                    name: "Clutch error",
                                    message: response_data["errors"]
                                });

                            }
                            else if (response.body && response.body.detail) {
                                throw error.create({
                                    name: response.code.toString() + "_ERROR",
                                    message: response.body.detail
                                });

                            } else {
                                throw error.create({
                                    name: response.code.toString() + "_ERROR",
                                    message: "An unexpected error occurred.",
                                });

                            }
                        }
                    }
                    while (url && isMoreResults); // while a url is provided and there are more results to get.
                } catch (e) {
                    log.error('getRequestClutchResults', e)

                    // throw e;
                    results = e;
                }

                return [results, response.code];
            }


            /**
             * Get headers for Clutch request.
             *
             * @scope Private
             * Basic headers need to added for the request creation
             */
            function getRequestHeaders() {
                var headers = {};

                try {
                    headers = { "Authorization": "Bearer pat-na1-********-****-****-****-************", "Content-Type": "application/json", "Accept":"application/json" }
                } catch (e) {
                    Log.error("Error@getRequestHeaders", e);
                }
                return headers;
            }

        })();
        return {
            Library: Library
        }
    });

Leave a comment

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