USPS tracking status and UPS API tracking Status

Jira Code: OSI-89 Fedex

The script sync shipment status for UPS, USPS, Fedex in ItemFulfillment using API so as to find Aging/Inactive shipments. We are fetching the tracking details using API and determining whether the shipment has been started or not. If it is not yet started we can conclude that the shipment is inactive and we can update that correspondingly in NetSuite.

/**
 * @NApiVersion 2.x
 * @NScriptType ScheduledScript
 * @NModuleScope SameAccount
 */
/************************************************************************************************
 * * OneSource IML | OSI - 89 | Fedex Tracking STATUS | Aging FedEx Shipments *
 * **********************************************************************************************
 *
 * Author: Jobin & Jismi IT Services LLP
 *
 * Date Created : 13-May-2019
 *
 
 ***********************************************************************************************/
define(['N/xml', 'N/url', 'N/email', 'N/https', 'N/record', 'N/runtime', 'N/search', 'N/task', 'N/config'],
    /**
     * @param {xml} xml
     * @param {url} url
     * @param {email} email
     * @param {https} https
     * @param {record} record
     * @param {runtime} runtime
     * @param {search} search
     * @param {task} task
     * @param {config} config
     */
    function(xml, url, email, https, record, runtime, search, task, config) {
        "use strict";

        var fetchTrackingInfo = null,
            trackingStatus = null,
            agingItemFulFillments = [],
            noTrackingInformation = [];


        //To check whether a value exists in parameter
        function checkForParameter(parameter, parameterName) {
            if (parameter !== null && parameter !== undefined && parameter !== false && parameter !== "null" && parameter !== "undefined" && parameter !== "false" && parameter !== "" && parameter !== " ")
                return true;
            if (parameterName)
                log.debug("Empty Value found", "Empty Value for parameter " + parameterName);
            return false;
        }

        //To assign a default value if the it is empty
        function assignDefaultValue(value, defaultValue) {
            if (checkForParameter(value)) return value;
            return defaultValue;
        }

        //Common Try-Catch function
        function applyTryCatch(DATA_OBJ, NAME) {
            function tryCatch(myfunction, key) {
                return function() {
                    try {
                        return myfunction.apply(this, arguments);
                    } catch (e) {
                        log.error("error in " + key, e);
                        return false;
                    }
                };
            }
            for (var key in DATA_OBJ) {
                if (typeof DATA_OBJ[key] === "function") {
                    DATA_OBJ[key] = tryCatch(DATA_OBJ[key], NAME + "." + key);
                }
            }
        }



        //Encapsulates Scheduler Functions
        var scheduler = {
            currentScript: undefined,
            run: function(key) {
                return ({
                    initialise: function() {
                        return scheduler.initialise();
                    },
                    id: function() {
                        return scheduler.getScriptId();
                    },
                    deploymentId: function() {
                        return scheduler.getDeploymentId();
                    },
                    remainingUsage: function() {
                        return scheduler.getRemainingUsage();
                    },
                    parameter: function(args) {
                        return scheduler.getParameter(args);
                    },
                    reschedule: function(args) {
                        return scheduler.submitTask(args);
                    }
                })[key](arguments);
            },
            initialise: function() {
                this.currentScript = runtime.getCurrentScript();
            },
            getScriptId: function() {
                return this.currentScript.id;
            },
            getDeploymentId: function() {
                return this.currentScript.deploymentId;
            },
            getRemainingUsage: function() {
                return Number(runtime.getCurrentScript().getRemainingUsage());
            },
            getParameter: function(args) {
                if (args[1])
                    return assignDefaultValue(this.currentScript.getParameter({
                        name: args[1].toString().toLowerCase().trim()
                    }), false);
                return false;
            },
            submitTask: function(args) {
                return task.create({
                    taskType: task.TaskType.SCHEDULED_SCRIPT,
                    scriptId: assignDefaultValue(args[1] ? args[1] : this.run("id"), this.run("id")),
                    deploymentId: assignDefaultValue(args[2] ? args[2] : this.run("deploymentId"), this.run("deploymentId")),
                    params: (function() {
                        var tempObj = {};
                        if (args[3])
                            for (var key in args[3])
                                tempObj[key] = args[3][key];
                        return tempObj;
                    })()
                }).submit();
            }
        };
        applyTryCatch(scheduler, "scheduler");

        //FedEx REST API Call
        var FedExAPIObj = {
            getCredentials: function() {
                return {
                    'URL': ''//'https://ws.fedex.com:443/web-services',
                    'Key': ''//'pJUyd7QEbdrihqVj',
                    'Password': ''//'aciIkFq8jSbIyRUFWHuJfKFFf',
                    'ShippingAccountNumber': ''//'361846400',
                    'WebServicesMeterNumber': ''//'113414546'
                };
            },
            fetchTrackingInfo: function(TRACKING_NUMBER, ShipmentAccountNumber, ShipDateRangeBegin, ShipDateRangeEnd) {
                var authObj = FedExAPIObj.getCredentials();
                var XML_BODY;
                if (checkForParameter(ShipDateRangeBegin) && checkForParameter(ShipDateRangeEnd))
                    XML_BODY = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v16="http://fedex.com/ws/track/v16"> <soapenv:Header /> <soapenv:Body> <TrackRequest xmlns="http://fedex.com/ws/track/v3"> <WebAuthenticationDetail> <UserCredential> <Key>' + authObj.Key + '</Key> <Password>' + authObj.Password + '</Password> </UserCredential> </WebAuthenticationDetail> <ClientDetail> <AccountNumber>' + authObj.ShippingAccountNumber + '</AccountNumber> <MeterNumber>' + authObj.WebServicesMeterNumber + '</MeterNumber> </ClientDetail> <TransactionDetail> <CustomerTransactionId>ActiveShipping</CustomerTransactionId> </TransactionDetail> <Version> <ServiceId>trck</ServiceId> <Major>3</Major> <Intermediate>0</Intermediate> <Minor>0</Minor> </Version> <PackageIdentifier> <Value>' + TRACKING_NUMBER + '</Value> <Type>TRACKING_NUMBER_OR_DOORTAG</Type> </PackageIdentifier> <ShipDateRangeBegin>' + ShipDateRangeBegin + '</ShipDateRangeBegin> <ShipDateRangeEnd>' + ShipDateRangeEnd + '</ShipDateRangeEnd> <ShipmentAccountNumber>' + ShipmentAccountNumber + '</ShipmentAccountNumber> <IncludeDetailedScans>1</IncludeDetailedScans> </TrackRequest> </soapenv:Body> </soapenv:Envelope>';
                else
                    XML_BODY = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v16="http://fedex.com/ws/track/v16"> <soapenv:Header /> <soapenv:Body> <TrackRequest xmlns="http://fedex.com/ws/track/v3"> <WebAuthenticationDetail> <UserCredential> <Key>' + authObj.Key + '</Key> <Password>' + authObj.Password + '</Password> </UserCredential> </WebAuthenticationDetail> <ClientDetail> <AccountNumber>' + authObj.ShippingAccountNumber + '</AccountNumber> <MeterNumber>' + authObj.WebServicesMeterNumber + '</MeterNumber> </ClientDetail> <TransactionDetail> <CustomerTransactionId>ActiveShipping</CustomerTransactionId> </TransactionDetail> <Version> <ServiceId>trck</ServiceId> <Major>3</Major> <Intermediate>0</Intermediate> <Minor>0</Minor> </Version> <PackageIdentifier> <Value>' + TRACKING_NUMBER + '</Value> <Type>TRACKING_NUMBER_OR_DOORTAG</Type> </PackageIdentifier> <ShipmentAccountNumber>' + ShipmentAccountNumber + '</ShipmentAccountNumber> <IncludeDetailedScans>1</IncludeDetailedScans> </TrackRequest> </soapenv:Body> </soapenv:Envelope>';
                var response = https.post({
                    url: authObj.URL,
                    headers: {
                        'content-type': 'application/xml',
                        'accept': 'application/xml'
                    },
                    body: XML_BODY
                });
                if (response.code == 200)
                    return response.body;
                else
                    return false;
            }
        };
        applyTryCatch(FedExAPIObj, "FedExAPIObj");


        //ups REST API Call
        var USPSAPIObj = {
            getCredentialsUsps: function(TRACKING_NUMBER) {
                return {
                    'URL': 'https://secure.shippingapis.com/ShippingAPI.dll?API=TrackV2&XML=<TrackRequest USERID="443ONESO6301"><TrackID ID="' + TRACKING_NUMBER + '"></TrackID></TrackRequest>'
                };
            },
            fetchTrackingInfoUsps: function(TRACKING_NUMBER) {
                var authObj = USPSAPIObj.getCredentialsUsps(TRACKING_NUMBER);
                var XML_BODY;
                var response = https.get({
                    url: authObj.URL,
                    headers: {
                        'content-type': 'application/xml',
                        'accept': 'application/xml'
                    }
                });
                if (response.code == 200)
                    return response.body;
                else
                    return false;
            }
        };
        applyTryCatch(USPSAPIObj, "USPSAPIObj");


        //FedEx REST API Call
        var UPSAPIObj = {
            getCredentialsUps: function() {
                return {
                    'URL': ''//'https://onlinetools.ups.com/ups.app/xml/Track'
                };
            },
            fetchTrackingInfoUps: function(TRACKING_NUMBER, ShipmentAccountNumber) {
                var authObj = USPSAPIObj.getCredentialsUps();
                var XML_BODY;
                if (TRACKING_NUMBER) {
                    XML_BODY = '<?xml version="1.0"?> <AccessRequest xml:lang="en-US"> <AccessLicenseNumber>1D63183B54F001C8</AccessLicenseNumber> <UserId>jcromanski</UserId> <Password>yamishmish</Password> </AccessRequest> <?xml version="1.0"?> <TrackRequest xml:lang="en-US"> <Request> <RequestAction>Track</RequestAction> <RequestOption>activity</RequestOption> </Request> <TrackingNumber>' + TRACKING_NUMBER + '</TrackingNumber> </TrackRequest>'
                }
                var response = https.post({
                    url: authObj.URL,
                    headers: {
                        'content-type': 'application/xml',
                        'accept': 'application/xml'
                    },
                    body: XML_BODY
                });
                if (response.code == 200)
                    return response.body;
                else
                    return false;
            }
        };
        applyTryCatch(UPSAPIObj, "UPSAPIObj");

        //dataSets from Saved Search and formating Saved Search results
        var dataSets = {
            fetchSavedSearchColumn: function(savedSearchObj, priorityKey) {
                var columns = savedSearchObj.columns;
                var columnsData = {},
                    columnName = '';

                columns.forEach(function(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;
                    }

                    columnsData[columnName] = result;
                });
                return columnsData;
            },
            formatSingleResult: function(searchResult, columns) {
                var responseObj = {};
                for (var column in columns)
                    responseObj[column] = assignDefaultValue(searchResult.getValue(columns[column]), "");
                return responseObj;
            },
            feDexItemFulfillment: function() {
                var fetchIF = search.load({
                    id: 'customsearch_osi82_aging_fedex_shipments' //OSI-82 Aging FedEx Shipments - DO NOT DELETE
                });
                return {
                    columns: dataSets.fetchSavedSearchColumn(fetchIF, 'label'),
                    searchObj: fetchIF
                };
            },
            upsItemFulfillment: function() {
                var fetchIF = search.load({
                    id: 'customsearch_osi89_aging_ups_shipments_2' //OSI-82 Aging ups Shipments - DO NOT DELETE
                });
                return {
                    columns: dataSets.fetchSavedSearchColumn(fetchIF, 'label'),
                    searchObj: fetchIF
                };
            },
            uspsItemFulfillment: function() {
                var fetchIF = search.load({
                    id: 'customsearch_osi89_aging_usps_shipment_2' //OSI-82 Aging usps Shipments - DO NOT DELETE
                });
                return {
                    columns: dataSets.fetchSavedSearchColumn(fetchIF, 'label'),
                    searchObj: fetchIF
                };
            },
        };
        applyTryCatch(dataSets, "dataSets");


        //Main or Root Function of Scheduled Script 
        var main = {
            isSandBox: function() {
                var companyInfo = config.load({
                    type: config.Type.COMPANY_INFORMATION
                });
                var ns_companyid = companyInfo.getValue({
                    fieldId: 'companyid'
                });
                ns_companyid = ns_companyid.toString().trim().toLowerCase();

                if (ns_companyid.indexOf('sb') > -1)
                    return true;
                return false;
            },
            hasEnoughUsage: function() {
                if (scheduler.run("remainingUsage") < 150) { //Rescheduling Condition
                    scheduler.run("reschedule");
                    log.debug('*** RESCHEDULE ***', '*** SCHEDULED SCRIPT RESCHEDULES ***');
                    return false;
                }
                return true;
            },
            NS_XML_PARSER: function(XML_DATA, XML_TAG) {
                var xmlDocument = xml.Parser.fromString({
                    text: XML_DATA
                });
                var xmlParseArray = xmlDocument.getElementsByTagName({
                    tagName: XML_TAG
                });
                return xmlParseArray;
            },
            generateReferenceToRecord: function(INTERNAL_ID, TRAN_ID) {
                if (!INTERNAL_ID || !TRAN_ID)
                    return null;

                return '<strong><a href="' + url.resolveRecord({
                    recordType: record.Type.ITEM_FULFILLMENT,
                    recordId: INTERNAL_ID,
                    isEditMode: false
                }) + '">#' + TRAN_ID + '</a></strong>';

            },
            fedexDetails: function(scriptContext) {

                //Fetch and Item Fulfillment
                var itemFulfillmentSearch = dataSets.feDexItemFulfillment();
                log.debug('itemFulfillmentSearch', itemFulfillmentSearch);

                itemFulfillmentSearch.searchObj.run().each(function(eachResult) {
                    if (main.hasEnoughUsage()) {
                        try {
                            fetchTrackingInfo = trackingStatus = null;

                            eachResult = dataSets.formatSingleResult(eachResult, itemFulfillmentSearch.columns);
                            log.debug('eachResult itemFulfillment', eachResult);

                            //Request FedEx for Tracking Information
                            fetchTrackingInfo = FedExAPIObj.fetchTrackingInfo((eachResult.TrackingNumber).toString().trim().split(" ")[0], eachResult.ShipmentAccountNumber);
                            log.debug('eachResult fetchTrackingInfo', fetchTrackingInfo);

                            //Fetch 'StausCode' from FedEx Response
                            if (fetchTrackingInfo)
                                trackingStatus = main.NS_XML_PARSER(fetchTrackingInfo, 'StatusCode');
                            log.debug('trackingStatus', trackingStatus);

                            if (checkForParameter(trackingStatus)) //If there is 'StausCode', update itemFulfillment record
                                if (checkForParameter(trackingStatus[0]))
                                    if (checkForParameter(trackingStatus[0].textContent)) {
                                        if (trackingStatus[trackingStatus.length - 1].textContent == 'OC' || (trackingStatus[trackingStatus.length - 1].textContent).toString().trim().toLowerCase() == 'oc') //If there is aging FedEx Shipments
                                            agingItemFulFillments.push(main.generateReferenceToRecord(eachResult.internalid, eachResult.PackageIdentifier));

                                        record.submitFields({
                                            type: record.Type.ITEM_FULFILLMENT,
                                            id: eachResult.internalid,
                                            values: {
                                                custbody_tracking_status: (trackingStatus[trackingStatus.length - 1].textContent).toString().trim() //Tracking Status
                                            },
                                            options: {
                                                enableSourcing: false,
                                                ignoreMandatoryFields: true
                                            }
                                        });
                                        return true;
                                    }
                        } catch (erIF) {
                            log.debug('erIF', erIF);
                        }
                        noTrackingInformation.push(main.generateReferenceToRecord(eachResult.internalid, eachResult.PackageIdentifier));

                        return true;
                    }
                    return false;
                });


            },
            upsDetails: function(scriptContext) {

                //Fetch and Item Fulfillment
                var upsitemFulfillmentSearch = dataSets.upsItemFulfillment();
                log.debug('upsitemFulfillmentSearch', upsitemFulfillmentSearch);

                upsitemFulfillmentSearch.searchObj.run().each(function(eachResult) {

                    if (main.hasEnoughUsage()) {
                        try {

                            fetchTrackingInfo = trackingStatus = null;
                            var currentStatus = null;
                            var description = null;

                            eachResult = dataSets.formatSingleResult(eachResult, upsitemFulfillmentSearch.columns);
                            log.debug('eachResult ups', eachResult);

                            //Request ups for Tracking Information
                            fetchTrackingInfo = UPSAPIObj.fetchTrackingInfoUps((eachResult.TrackingNumber).toString().trim().split(" ")[0], eachResult.ShipmentAccountNumber);

                            log.debug('fetchTrackingInfo ups', fetchTrackingInfo);

                            //Fetch 'StausCode' from FedEx Response
                            if (fetchTrackingInfo) {
                                trackingStatus = main.NS_XML_PARSER(fetchTrackingInfo, 'StatusCode');
                                //trackingStatusDes = main.NS_XML_PARSER(fetchTrackingInfo, 'StatusType');
                            }


                            log.debug('trackingStatus ups', trackingStatus);
                            if (checkForParameter(trackingStatus)) {

                                if ((assignDefaultValue(trackingStatus.length)) == 0) {
                                    currentStatus = 'OC';

                                } else if ((assignDefaultValue(trackingStatus.length)) == 1) {

                                    if ((trackingStatus[0].textContent) != 'MP')
                                        currentStatus = 'OC';
                                    else
                                        currentStatus = 'MP';

                                } else if ((assignDefaultValue(trackingStatus.length)) >= 1) {
                                    currentStatus = trackingStatus[0].textContent;
                                    // description = trackingStatusDes[0].textContent;
                                }

                            } else
                                currentStatus = 'OC';

                            if (currentStatus) {

                                record.submitFields({
                                    type: record.Type.ITEM_FULFILLMENT,
                                    id: eachResult.internalid,
                                    values: {
                                        custbody_tracking_status: currentStatus.toString().trim() //Tracking Status
                                    },
                                    options: {
                                        enableSourcing: false,
                                        ignoreMandatoryFields: true
                                    }
                                });
                                return true;
                            }


                        } catch (erIF) {
                            log.debug('erIF', erIF);
                        }
                        //noTrackingInformation.push(main.generateReferenceToRecord(eachResult.internalid, eachResult.PackageIdentifier));

                        return true;
                    }
                    return false;
                });

            },
            uspsDetails: function(scriptContext) {

                //Fetch and Item Fulfillment
                var uspsitemFulfillmentSearch = dataSets.uspsItemFulfillment();
                log.debug('uspsitemFulfillmentSearch', uspsitemFulfillmentSearch);

                uspsitemFulfillmentSearch.searchObj.run().each(function(eachResult) {

                    if (main.hasEnoughUsage()) {
                        try {

                            fetchTrackingInfo = trackingStatus = null;
                            var currentStatus = null;

                            eachResult = dataSets.formatSingleResult(eachResult, uspsitemFulfillmentSearch.columns);
                            log.debug('eachResult usps', eachResult);

                            //Request usps for Tracking Information
                            fetchTrackingInfo = USPSAPIObj.fetchTrackingInfoUsps((eachResult.TrackingNumber).toString().trim().split(" ")[0], eachResult.ShipmentAccountNumber);

                            log.debug('fetchTrackingInfo usps', fetchTrackingInfo);

                            //Fetch 'StausCode' from FedEx Response
                            if (fetchTrackingInfo) {
                                trackingStatus = main.NS_XML_PARSER(fetchTrackingInfo, 'TrackDetail');
                            }

                            log.debug('trackingStatus usps', trackingStatus);


                            if (checkForParameter(trackingStatus)) {

                                if ((assignDefaultValue(trackingStatus.length)) == 0) {
                                    currentStatus = 'OC';

                                } else if ((assignDefaultValue(trackingStatus.length)) == 1) {

                                    trackSta = (trackingStatus[0].textContent).split(",", 2);
                                    if ((trackSta[0] == "Shipping Label Created") && (trackSta[1] == "USPS Awaiting Item"))
                                        currentStatus = 'OC';


                                } else if ((assignDefaultValue(trackingStatus.length)) >= 1) {
                                    currentSt = (trackingStatus[0].textContent).split(",", 1);
                                    currentStatus = currentSt[0];
                                    // description = trackingStatusDes[0].textContent;
                                }

                            } else
                                currentStatus = 'OC';

                            if (currentStatus) {

                                log.debug('currentStatus', currentStatus);

                                record.submitFields({
                                    type: record.Type.ITEM_FULFILLMENT,
                                    id: eachResult.internalid,
                                    values: {
                                        custbody_tracking_status: currentStatus.toString().trim() //Tracking Status
                                    },
                                    options: {
                                        enableSourcing: false,
                                        ignoreMandatoryFields: true
                                    }
                                });
                                return true;
                            }


                        } catch (erIF) {
                            log.debug('erIF', erIF);
                        }
                        // noTrackingInformation.push(main.generateReferenceToRecord(eachResult.internalid, eachResult.PackageIdentifier));

                        return true;
                    }
                    return false;
                });

            },

            execute: function(scriptContext) {
                if (main.isSandBox()) //If current executing environment is SandBox, then disregard the entire process
                    return false;

                log.debug('*** START ***', '*** SCHEDULED SCRIPT STARTS ***');

                //Initialize Scheduler Functions
                scheduler.run("initialise");

                // main.fedexDetails();
                main.upsDetails();
                main.uspsDetails();


                log.debug('*** END ***', '*** SCHEDULED SCRIPT ENDS ***');
                return false;
            }
        };
        applyTryCatch(main, "main");

        return main;
    });

Leave a comment

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