Order Receipt Update – NetSuite Integration

Jira Code : BTN-609

Fetch JSON file in AWS bucket and create Sales Order on NetSuite using the data available in JSON file. Whenever an Invoice is generated against that Sales Order, sync back the JSON file to another AWS Bucket

/**
 * @NApiVersion 2.x
 * @NScriptType ScheduledScript
 * @NModuleScope SameAccount
 */
/**
 * Script Description
 * This scheduled script will periodically -
 *  - Fecth all PurchaseOrder Object Metada from Bucket
 *  - Fetch complete details of Single Object (response is JSON file) from AWS S3 bucket using the Metadata details from previous step
 *  - Check whether there is existing JSON file in NS File Cabinet 
 *  - If there is existing JSON file in NS File Cabinet,then push that PurchaseOrder from AWS S3 Bucket 'archive/PurchaseOrder',after that delete it from  from AWS S3 Bucket 
 *  - If there is no existing JSON file in NS File Cabinet,then create Sales Order 
 * Created on 22-Feb-2018 by  Manu Antony Vadassery
 */
/**
 * Script Details 
 * Script { name : BTN-169 JJ Order Receipt Integration , id : customscript_btn_169_jj_order_receipt_in}
 * Deployment { title : BTN-169 JJ Order Receipt Integration , id : customdeploy_btn_169_jj_order_receipt_in}
 */
/*******************************************************************************
 * * Balaji Trading Network | BTN-169 *
 * **************************************************************************
 * 
 * 
 * Author: Manu Antony Vadassery , Jobin & Jismi IT Services LLP
 * 
 * REVISION HISTORY
 * 
 * 
 ******************************************************************************/
define(['N/http', 'N/https', 'N/record', 'N/runtime', 'N/search', 'N/file', 'N/task', 'N/config'],
    /**
     * @param {http} http
     * @param {https} https
     * @param {record} record
     * @param {runtime} runtime
     * @param {search} search
     * @param {file} file
     * @param {task} task
     * @param {config} config
     */
    function (http, https, record, runtime, search, file, task, config) {

        /**
         * Definition of the Scheduled script trigger point.
         *
         * @param {Object} scriptContext
         * @param {string} scriptContext.type - The context in which the script is executed. It is one of the values from the scriptContext.InvocationType enum.
         * @Since 2015.2
         */

        /* to return Static Information for AWS Auth */
        function getAWSAuthObj() {
            var currentDate = new Date();
            var dateStampISOConverted = currentDate.toISOString();
            while (dateStampISOConverted.indexOf('-') > (-1)) {
                dateStampISOConverted = dateStampISOConverted.replace("-", "");
            }
            while (dateStampISOConverted.indexOf(':') > (-1)) {
                dateStampISOConverted = dateStampISOConverted.replace(":", "");
            }
            dateStampISOConverted = dateStampISOConverted.split(".")[0] + "Z";
            var dateOnly = (currentDate.toISOString()).split("T")[0];
            while (dateOnly.search('-') > (-1)) {
                dateOnly = dateOnly.replace("-", "");
            }
            var staticAWSDetilsObj = {
                "aws_access_key_id": "AKIAJPNEYLXDMI7QIY3Q",
                "aws_secret_access_key": "JnkTDJN0APkeoXEVab7eAwlbAGFQ5cBgzf2cvUmB",
                "bucket": "mycoolcell-balaji",
                "POFolder": "PurchaseOrder",
                "IRFolder": "ItemReceipt",
                "region": "us-west-2",
                "serviceName": "s3",
                "currentDate": currentDate,
                "parseDate": Date.parse(currentDate),
                "dateStampISO": currentDate.toISOString(),
                "dateStampUTC": currentDate.toUTCString(),
                "dateString": currentDate.toString(),
                "dateStampISOConverted": dateStampISOConverted,
                "dateOnly": dateOnly,
                amzDate: dateStampISOConverted,
                authDate: dateOnly
            };
            return staticAWSDetilsObj;
        }

        /* to return signatureKey */
        function getSignatureKey(key, dateStamp, regionName, serviceName) {
            var kDate = CryptoJS.HmacSHA256(dateStamp, "AWS4" + key);
            var kRegion = CryptoJS.HmacSHA256(regionName, kDate);
            var kService = CryptoJS.HmacSHA256(serviceName, kRegion);
            var kSigning = CryptoJS.HmacSHA256("aws4_request", kService);
            return kSigning;
        }

        /* to return metadata of all object in a Bucket */
        function fetchAllObject(prefixName) {
            try {
                var staticObj = getAWSAuthObj();
                /*
                CanonicalRequest :
                        HTTPRequestMethod
                        CanonicalURI
                        CanonicalQueryString
                        CanonicalHeaders
                        SignedHeaders
                        HexEncode(Hash(RequestPayload))
                 */
                /* CanonicalRequest */
                var payload = "";
                var CanonicalRequest = "GET" + "\n" + //HTTPRequestMethod
                    encodeURI("/") + "\n" + //CanonicalURI
                    encodeURI("list-type") + "=" + encodeURI("2") + "&" + //CanonicalQueryString
                    encodeURI("max-keys") + "=" + encodeURI("1000") + "&" + //CanonicalQueryString
                    encodeURI("prefix") + "=" + encodeURI(prefixName) + //CanonicalQueryString
                    "\n" + //CanonicalQueryString
                    "host:mycoolcell-balaji.s3.amazonaws.com" + "\n" + //CanonicalHeaders
                    "x-amz-content-sha256:" + CryptoJS.enc.Hex.stringify(CryptoJS.SHA256(payload)).toLowerCase() + "\n" + //CanonicalHeaders
                    "x-amz-date:" + staticObj.amzDate + "\n" + //CanonicalHeaders
                    "\n" + //CanonicalHeaders
                    "host;x-amz-content-sha256;x-amz-date" + "\n" + //SignedHeaders
                    CryptoJS.enc.Hex.stringify(CryptoJS.SHA256(payload)).toLowerCase(); //HashedPayload;
                CanonicalRequest = CryptoJS.enc.Hex.stringify(CryptoJS.SHA256(CanonicalRequest));

                /*
                    String to sign :
                            Algorithm
                            RequestDate
                            CredentialScope
                            HashedCanonicalRequest
                 */
                /* stringToSign */
                var stringToSign = "AWS4-HMAC-SHA256" + "\n" + //Algorithm
                    staticObj.amzDate + "\n" + //RequestDate
                    staticObj.authDate + "/" + staticObj.region + "/" + staticObj.serviceName + "/aws4_request" + "\n" + //CredentialScope
                    CanonicalRequest; //HashedCanonicalRequest
                //logme("null payload hashed",'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855');

                /*  signingKey  */
                var signingKey = getSignatureKey(staticObj.aws_secret_access_key, staticObj.dateOnly, staticObj.region, staticObj.serviceName);

                /*  signature   */
                var signature = CryptoJS.HmacSHA256(stringToSign, signingKey);
                signature = CryptoJS.enc.Hex.stringify(signature);

                /*
                    signature = CryptoJS.enc.Base64.stringify(signature);
                    while (signature.indexOf('+') > (-1)) {
                        signature = signature.replace("+", "%2B");
                    }
                    while (signature.indexOf('/') > (-1)) {
                        signature = signature.replace("/", "%2F");
                    }
                    while (signature.indexOf('=') > (-1)) {
                        signature = signature.replace("=", "%3D");
                    }
                 */

                /* authHeader */
                var authHeader = "AWS4-HMAC-SHA256" +
                    " Credential=" + staticObj.aws_access_key_id + "/" + staticObj.authDate + "/" + staticObj.region + "/" + staticObj.serviceName + "/aws4_request," +
                    " SignedHeaders=host;x-amz-content-sha256;x-amz-date," +
                    " Signature=" + signature;

                /* request */
                var response = http.get({
                    url: "http://mycoolcell-balaji.s3.amazonaws.com/?list-type=2&max-keys=1000&prefix=" + prefixName,
                    headers: {
                        'Authorization': authHeader,
                        'host': 'mycoolcell-balaji.s3.amazonaws.com',
                        'x-amz-content-sha256': CryptoJS.enc.Hex.stringify(CryptoJS.SHA256(payload)).toLowerCase(),
                        'x-amz-date': staticObj.amzDate
                    }
                });

                /* response.body */
                var XMLdata = (response.body).toString();

                //to split data between <Key> and </Key> and store it in Array
                var XMLArray = new Array();
                var pos = 0;
                XMLArray = XMLdata.split('<Key>');
                while (pos < XMLArray.length) {
                    if (XMLArray[pos].split('</Key>')[0]) {
                        XMLArray[pos] = XMLArray[pos].split('</Key>')[0];
                    }
                    pos++;
                }

                //to remove array with no 'PO***' number
                pos = 0;
                while (pos < 2) {
                    if (XMLdata[0].search('PO') < 0) {
                        XMLArray.remove(0);
                    }
                    pos++;
                }

                //To create an Object with Key as 'PO**' number and value as 'PO**' path
                var XMLcontent, XMLkey;
                var XMLObject = new Object();
                pos = 0;
                while (pos < XMLArray.length) {
                    XMLkey = (XMLArray[pos].split(prefixName + '/')[1].split('.json')[0]) || (XMLArray[pos].split(prefixName + '/')[1].split('.JSON')[0]);
                    XMLcontent = XMLArray[pos];
                    XMLObject[XMLkey] = XMLcontent;
                    pos++;
                }

                return XMLObject;
            } catch (err) {
                handleTryCatchError(err, 'function fetchAllObject(' + prefixName + ')');
                return false;
            }
        }

        /* to return complete data of specific object in a Bucket */
        function fetchAnObject(pathKey) {
            try {
                var staticObj = getAWSAuthObj();

                /* CanonicalRequest */
                var payload = "";
                var CanonicalRequest = "GET" + "\n" + //HTTPRequestMethod
                    encodeURI("/" + pathKey) + "\n" + //CanonicalURI
                    "\n" + //CanonicalQueryString
                    "host:mycoolcell-balaji.s3.amazonaws.com" + "\n" + //CanonicalHeaders
                    "x-amz-content-sha256:" + CryptoJS.enc.Hex.stringify(CryptoJS.SHA256(payload)).toLowerCase() + "\n" + //CanonicalHeaders
                    "x-amz-date:" + staticObj.amzDate + "\n" + //CanonicalHeaders
                    "\n" + //CanonicalHeaders
                    "host;x-amz-content-sha256;x-amz-date" + "\n" + //SignedHeaders
                    CryptoJS.enc.Hex.stringify(CryptoJS.SHA256(payload)).toLowerCase(); //HashedPayload;
                CanonicalRequest = CryptoJS.enc.Hex.stringify(CryptoJS.SHA256(CanonicalRequest));

                /* stringToSign */
                var stringToSign = "AWS4-HMAC-SHA256" + "\n" +
                    staticObj.amzDate + "\n" +
                    staticObj.authDate + "/" + staticObj.region + "/" + staticObj.serviceName + "/aws4_request" + "\n" +
                    CanonicalRequest;

                /*  signingKey  */
                var signingKey = getSignatureKey(staticObj.aws_secret_access_key, staticObj.dateOnly, staticObj.region, staticObj.serviceName);

                /*  signature   */
                var signature = CryptoJS.HmacSHA256(stringToSign, signingKey);
                signature = CryptoJS.enc.Hex.stringify(signature);

                /* authHeader */
                var authHeader = "AWS4-HMAC-SHA256" +
                    " Credential=" + staticObj.aws_access_key_id + "/" + staticObj.authDate + "/" + staticObj.region + "/" + staticObj.serviceName + "/aws4_request," +
                    " SignedHeaders=host;x-amz-content-sha256;x-amz-date," +
                    " Signature=" + signature;

                /* request */
                var response = http.get({
                    url: "http://mycoolcell-balaji.s3.amazonaws.com/" + pathKey,
                    headers: {
                        'Authorization': authHeader,
                        'host': 'mycoolcell-balaji.s3.amazonaws.com',
                        'x-amz-content-sha256': CryptoJS.enc.Hex.stringify(CryptoJS.SHA256(payload)).toLowerCase(),
                        'x-amz-date': staticObj.amzDate
                    }
                });

                /* response.body */
                var JSONdata = (response.body);

                return JSONdata;

            } catch (err) {
                handleTryCatchError(err, 'function fetchAnObject(' + pathKey + ')');
                return false;
            }
        }

        /* to delete a specific object in a Bucket */
        function deleteAnObject(pathKey) {
            try {
                var staticObj = getAWSAuthObj();

                /* CanonicalRequest */
                var payload = "";
                var CanonicalRequest = "DELETE" + "\n" + //HTTPRequestMethod
                    encodeURI("/" + pathKey) + "\n" + //CanonicalURI
                    "\n" + //CanonicalQueryString
                    "host:mycoolcell-balaji.s3.amazonaws.com" + "\n" + //CanonicalHeaders
                    "x-amz-content-sha256:" + CryptoJS.enc.Hex.stringify(CryptoJS.SHA256(payload)).toLowerCase() + "\n" + //CanonicalHeaders
                    "x-amz-date:" + staticObj.amzDate + "\n" + //CanonicalHeaders
                    "\n" + //CanonicalHeaders
                    "host;x-amz-content-sha256;x-amz-date" + "\n" + //SignedHeaders
                    CryptoJS.enc.Hex.stringify(CryptoJS.SHA256(payload)).toLowerCase(); //HashedPayload;
                CanonicalRequest = CryptoJS.enc.Hex.stringify(CryptoJS.SHA256(CanonicalRequest));

                /* stringToSign */
                var stringToSign = "AWS4-HMAC-SHA256" + "\n" +
                    staticObj.amzDate + "\n" +
                    staticObj.authDate + "/" + staticObj.region + "/" + staticObj.serviceName + "/aws4_request" + "\n" +
                    CanonicalRequest;

                /*  signingKey  */
                var signingKey = getSignatureKey(staticObj.aws_secret_access_key, staticObj.dateOnly, staticObj.region, staticObj.serviceName);

                /*  signature   */
                var signature = CryptoJS.HmacSHA256(stringToSign, signingKey);
                signature = CryptoJS.enc.Hex.stringify(signature);

                /* authHeader */
                var authHeader = "AWS4-HMAC-SHA256" +
                    " Credential=" + staticObj.aws_access_key_id + "/" + staticObj.authDate + "/" + staticObj.region + "/" + staticObj.serviceName + "/aws4_request," +
                    " SignedHeaders=host;x-amz-content-sha256;x-amz-date," +
                    " Signature=" + signature;

                /* request */
                var response = http.delete({
                    url: "http://mycoolcell-balaji.s3.amazonaws.com/" + pathKey,
                    headers: {
                        'Authorization': authHeader,
                        'host': 'mycoolcell-balaji.s3.amazonaws.com',
                        'x-amz-content-sha256': CryptoJS.enc.Hex.stringify(CryptoJS.SHA256(payload)).toLowerCase(),
                        'x-amz-date': staticObj.amzDate
                    }
                });

                /* response.code */
                var responseCode = (response.code);

                return responseCode;

            } catch (err) {
                handleTryCatchError(err, 'function deleteAnObject(' + pathKey + ')');
                return false;
            }
        }

        /* to upload a specific object into a Bucket */
        function uploadAnObject(fileObj, pathKey) {
            try {
                var staticObj = getAWSAuthObj();

                /* CanonicalRequest */
                var payload = fileObj.getContents();
                var CanonicalRequest = "PUT" + "\n" + //HTTPRequestMethod
                    encodeURI("/" + pathKey) + "\n" + //CanonicalURI
                    "\n" + //CanonicalQueryString
                    "content-length:" + fileObj.size + "\n" + //CanonicalHeaders
                    "content-type:application/json" + "\n" + //CanonicalHeaders
                    "expect:100-continue" + "\n" + //CanonicalHeaders
                    "host:mycoolcell-balaji.s3.amazonaws.com" + "\n" + //CanonicalHeaders
                    "x-amz-content-sha256:" + CryptoJS.enc.Hex.stringify(CryptoJS.SHA256(payload)).toLowerCase() + "\n" + //CanonicalHeaders
                    "x-amz-date:" + staticObj.amzDate + "\n" + //CanonicalHeaders
                    "\n" + //CanonicalHeaders
                    "content-length;content-type;expect;host;x-amz-content-sha256;x-amz-date" + "\n" + //SignedHeaders
                    CryptoJS.enc.Hex.stringify(CryptoJS.SHA256(payload)).toLowerCase(); //HashedPayload;
                CanonicalRequest = CryptoJS.enc.Hex.stringify(CryptoJS.SHA256(CanonicalRequest));

                /* stringToSign */
                var stringToSign = "AWS4-HMAC-SHA256" + "\n" +
                    staticObj.amzDate + "\n" +
                    staticObj.authDate + "/" + staticObj.region + "/" + staticObj.serviceName + "/aws4_request" + "\n" +
                    CanonicalRequest;

                /*  signingKey  */
                var signingKey = getSignatureKey(staticObj.aws_secret_access_key, staticObj.dateOnly, staticObj.region, staticObj.serviceName);

                /*  signature   */
                var signature = CryptoJS.HmacSHA256(stringToSign, signingKey);
                signature = CryptoJS.enc.Hex.stringify(signature);

                /* authHeader */
                var authHeader = "AWS4-HMAC-SHA256" +
                    " Credential=" + staticObj.aws_access_key_id + "/" + staticObj.authDate + "/" + staticObj.region + "/" + staticObj.serviceName + "/aws4_request," +
                    " SignedHeaders=content-length;content-type;expect;host;x-amz-content-sha256;x-amz-date," +
                    " Signature=" + signature;

                /* request */
                var response = http.put({
                    url: "http://mycoolcell-balaji.s3.amazonaws.com/" + pathKey,
                    headers: {
                        'Authorization': authHeader,
                        'Content-Length': fileObj.size,
                        'Content-Type': 'application/json',
                        'Expect': '100-continue',
                        'host': 'mycoolcell-balaji.s3.amazonaws.com',
                        'x-amz-content-sha256': CryptoJS.enc.Hex.stringify(CryptoJS.SHA256(payload)).toLowerCase(),
                        'x-amz-date': staticObj.amzDate
                    },
                    body: fileObj.getContents()
                });

                /* response.code */
                var responseCode = (response.code);

                return responseCode;

            } catch (err) {
                handleTryCatchError(err, 'function uploadAnObject(' + pathKey + ')');
                return false;
            }
        }

        /* to create sales order using data in object fetched from Bucket */
        function createSalesOrder(singlePO_Obj, objFileName) {
            try {
                //Create Sales Order
                var salesObjRecord = record.transform({
                    fromType: record.Type.CUSTOMER,
                    fromId: 6946, //2791 MyCoolCell
                    toType: record.Type.SALES_ORDER,
                    isDynamic: true,
                });
                salesObjRecord.setValue({
                    fieldId: 'customform',
                    value: 132 // 132 - Balaji Sales Order
                });
                salesObjRecord.setValue({
                    fieldId: 'custbody_bw_ordertype',
                    value: 1, // 1 : BW
                    ignoreFieldChange: false
                });
                salesObjRecord.setValue({
                    fieldId: 'custbody_btn_169_jj_source_mcc', // Custom Field(Source MCC AWS S3 Bucket)
                    value: true,
                    ignoreFieldChange: false
                });
                salesObjRecord.setValue({
                    fieldId: 'department',
                    value: 32, //32 : BalajiWireless.com
                    ignoreFieldChange: false
                });

                //to fetch Sales Item details using External Item ID
                var salesItemArray = fecthAllSalesItem(singlePO_Obj.Items);
                for (var i = 0; i < salesItemArray.length; i++) {
                    try {
                        salesObjRecord.selectNewLine({
                            sublistId: 'item'
                        });
                        salesObjRecord.setCurrentSublistValue({
                            sublistId: 'item',
                            fieldId: 'item',
                            value: salesItemArray[i].Internal_ID,
                            ignoreFieldChange: false
                        });
                        salesObjRecord.setCurrentSublistValue({
                            sublistId: 'item',
                            fieldId: 'quantity',
                            value: parseInt(salesItemArray[i].Qty),
                            ignoreFieldChange: false
                        });
                        salesObjRecord.commitLine({
                            sublistId: 'item'
                        });
                    } catch (err) {
                        logme('Invalid Item ID ', err.message);
                        continue;
                    }
                }
                salesObjRecord.setValue({
                    fieldId: 'paymentmethod',
                    value: '', //Null value
                    ignoreFieldChange: false
                });
                salesObjRecord.setValue({
                    fieldId: 'shipmethod',
                    value: 64641, //"64641":"Pickup",
                    ignoreFieldChange: false
                });
                salesObjRecord.setValue({
                    fieldId: 'otherrefnum', // PO field
                    value: (singlePO_Obj.RefNo).toString(),
                    ignoreFieldChange: false
                });
                var salesRecordID = salesObjRecord.save({
                    enableSourcing: true,
                    ignoreMandatoryFields: false
                });
                salesObjRecord = record.load({
                    type: record.Type.SALES_ORDER,
                    id: salesRecordID,
                    isDynamic: false,
                });
                var tranID = salesObjRecord.getValue({
                    fieldId: 'tranid'
                });

                singlePO_Obj.Items = salesItemArray;
                var BalajiWireless = new Object();
                BalajiWireless.SalesInternalID = salesRecordID.toString();
                BalajiWireless.SalesTranID = tranID.toString();
                singlePO_Obj.BalajiWireless = BalajiWireless;

                singlePO_Obj = JSON.stringify(singlePO_Obj);

                //Save the Modified JSON file in File Cabinet
                var fileObj = file.create({
                    name: objFileName,
                    fileType: file.Type.JSON,
                    contents: singlePO_Obj,
                    encoding: file.Encoding.UTF8,
                    isInactive: true,
                    folder: 19944 //MCC AWS S3 Bucket
                });
                fileObj.save();

                return salesRecordID;

            } catch (err) {
                handleTryCatchError(err, 'function createSalesOrder(singlePO_Obj)');
                return false;
            }
        }

        /* to return sales Item details using External Item ID */
        function fecthAllSalesItem(salesItemObj) {
            try {
                var resultArray = new Array();
                var resultObj = new Object();
                var customFilter = ["externalid", "anyof"];
                var itemToQuantityMap = new Object();
                var itemToBarcodeMap = new Object();

                for (var i = 0; i < salesItemObj.length; i++) {
                    customFilter.push(salesItemObj[i].Item_No);
                    itemToQuantityMap[salesItemObj[i].Item_No] = salesItemObj[i].Qty;
                    itemToBarcodeMap[salesItemObj[i].Item_No] = salesItemObj[i].Barcode;
                }
                var salesItemSearch = search.create({
                    type: "inventoryitem",
                    filters: [
                        ["type", "anyof", "InvtPart"],
                        "AND",
                        customFilter
                    ],
                    columns: [
                        "internalid",
                        "externalid"
                    ]
                }).run().each(function (result) {
                    resultObj.Item_No = result.getValue({
                        name: "externalid"
                    });
                    resultObj.Internal_ID = result.getValue({
                        name: "internalid"
                    });
                    resultObj.Qty = itemToQuantityMap[resultObj.Item_No];
                    resultObj.Barcode = itemToBarcodeMap[resultObj.Item_No];

                    resultArray.push(resultObj);
                    resultObj = undefined;
                    resultObj = new Object();
                    return true;
                });

                return resultArray;
            } catch (err) {
                handleTryCatchError(err, 'function fecthAllSalesItem(salesItemObj)');
                return false;
            }
        }

        function executeAWStoNSAPI(scriptContext) {
            //to know whether production or sandbox
            var companyInfo = config.load({
                type: config.Type.COMPANY_INFORMATION
            });
            var ns_companyid = companyInfo.getValue({
                fieldId: 'companyid'
            });

            log.debug('ns_companyid = ', ns_companyid);
            log.debug('ns_companyid ==4215023  ', ns_companyid == 4215023);
            log.debug('ns_companyid !=4215023  ', ns_companyid != 4215023);
            if (ns_companyid != 4215023 || ns_companyid != '4215023')
                return false;

            var currentDate = new Date();
            logme('EXECUTION STARTS', 'EXECUTION BEGINS AT ' + (currentDate.toUTCString()));
            try {
                var remainingUsage = runtime.getCurrentScript().getRemainingUsage();

                // to fetch all object in PurchaseOrder
                var purchaseOrderObj = fetchAllObject('PurchaseOrder');
                logme('purchaseOrderObj', purchaseOrderObj);

                //To create Sales Order
                var loadfileObj, singlePurchaseOrder, salesID, locPath, deletesSinglePurchaseOrder, uploadResponse;
                for (var i = 0; i < (Object.keys(purchaseOrderObj)).length; i++) {
                    if (((purchaseOrderObj[Object.keys(purchaseOrderObj)[i]]).toString()).search('xml') > (-1)) {
                        // neglect XML files
                        continue;
                    }
                    locPath = (purchaseOrderObj[Object.keys(purchaseOrderObj)[i]]).split("PurchaseOrder/")[1];
                    try {
                        //Check for existing Sales Order by searching for JSON file in Files Cabinet
                        loadfileObj = file.load({
                            id: 'MCC AWS S3 Bucket/' + locPath
                        });
                        logme('PO exists', 'exists ' + purchaseOrderObj[Object.keys(purchaseOrderObj)[i]]);
                        try {
                            //To send(Upload) PurchaseOrder as Archive to AWS S3 Bucket,we give loadfileObj and locPath as parameters  
                            uploadResponse = uploadAnObject(loadfileObj, 'archive/PurchaseOrder/' + locPath);
                            logme('PO uploadResponse', uploadResponse);
                            if (uploadResponse) {
                                //After PurchaseOrder is SUCCESSFULLY Uploaded to AWS S3 Bucket
                                if (parseInt(uploadResponse) == 200 || uploadResponse == '200' || uploadResponse == 200) {
                                    try {
                                        // to delete PO from bucket
                                        deletesSinglePurchaseOrder = deleteAnObject(purchaseOrderObj[Object.keys(purchaseOrderObj)[i]]);
                                    } catch (err) {
                                        logme('error deletesSinglePurchaseOrder', 'deleteAnObject(' + purchaseOrderObj[Object.keys(purchaseOrderObj)[i]] + ')');
                                    }
                                }
                            }
                        } catch (errr) {
                            logme('error PO upload as Archive', uploadResponse);
                        }



                    } catch (err) {
                        if (doesSalesOrderExists(Object.keys(purchaseOrderObj)[i])) {
                            //If no JSON file is found in File Cabinet,then Create sales order
                            singlePurchaseOrder = fetchAnObject(purchaseOrderObj[Object.keys(purchaseOrderObj)[i]]);
                            singlePurchaseOrder = JSON.parse(singlePurchaseOrder);
                            salesID = createSalesOrder(singlePurchaseOrder, locPath);
                            if (salesID) {
                                logme('PO new', 'new ' + purchaseOrderObj[Object.keys(purchaseOrderObj)[i]]);
                            } else {
                                logme('PO Failed', 'Sales Order Failed for ' + purchaseOrderObj[Object.keys(purchaseOrderObj)[i]]);
                            }
                        }
                    }
                    remainingUsage = runtime.getCurrentScript().getRemainingUsage();
                    if (parseInt(remainingUsage) < 850) {
                        logme("remainingUsage", remainingUsage);
                        currentDate = new Date();
                        logme('EXECUTION RESCHEDULED', 'EXECUTION RESCHEDULED AT ' + (currentDate.toUTCString()));
                        rescheduleScriptandReturn();
                        break;
                    }
                }

                currentDate = new Date();
                logme('EXECUTION ENDS', 'EXECUTION ENDS AT ' + (currentDate.toUTCString()));

            } catch (err) {
                currentDate = new Date();
                logme('EXECUTION FAILED', 'EXECUTION THROWS ERROR AT ' + (currentDate.toUTCString()));
                handleTryCatchError(err, 'function executeAWStoNSAPI()');
            }
        }
        /*Check Whether the Sales Order already exists*/
        function doesSalesOrderExists(PO_REF_NUM) {
            try {
                var salesorderSearchObj = search.create({
                    type: "salesorder",
                    filters: [
                        ["type", "anyof", "SalesOrd"],
                        "AND",
                        ["memorized", "is", "F"],
                        "AND",
                        ["mainline", "is", "T"],
                        "AND",
                        ["otherrefnum", "equalto", PO_REF_NUM.toString().trim()]
                    ],
                    columns: [
                        search.createColumn({
                            name: "internalid",
                            sort: search.Sort.ASC,
                            label: "Internal ID"
                        }),
                        search.createColumn({
                            name: "trandate",
                            label: "Date"
                        }),
                        search.createColumn({
                            name: "tranid",
                            label: "Document Number"
                        })
                    ]
                }).run().getRange({
                    start: 0,
                    end: 2
                });
                if (salesorderSearchObj.length > 0)
                    return false; //Sales Order already exits, no no need to duplicate
                return true; //Sales Order Doesn't exits

            } catch (err) {
                return true; //Sales Order Doesn't exits
            }
        }

        /*Try to reschedule script*/
        function rescheduleScriptandReturn() {
            try {
                var mrTask = task.create({
                    taskType: task.TaskType.SCHEDULED_SCRIPT,
                    scriptId: "customscript_btn_169_jj_order_receipt_in",
                    deploymentId: "customdeploy_btn_169_jj_order_receipt_in",
                    params: {
                        doSomething: true
                    }
                });
                var scriptTaskId = mrTask.submit();
                logme("rescheduleScriptandReturn_scriptTaskId", scriptTaskId);
            } catch (err) {
                handleTryCatchError(err, 'function rescheduleScriptandReturn()');
                return false;
            }
        }

        /*to check for a parameter*/
        function checkForParameter(parameter, parameterName) {
            if (parameter !== "" && parameter !== null && parameter !== undefined && parameter != "undefined" && parameter != " ") {
                return true;
            } else {
                if (parameterName)
                    logme('No ' + parameterName + ' found', 'No ' + parameterName + ' found');
                return false;
            }
        }

        /*to handle 'try' error in try-catch statement*/
        function handleTryCatchError(error, errorLocation) {
            logme('Error on ' + errorLocation, getError(error));
            logme('Error on ' + errorLocation, error.message);
        }

        return {
            execute: executeAWStoNSAPI
        };

    });


/*******************************************************************************/
// to delete an element from an Array
Array.prototype.remove = function (from, to) {
    var rest = this.slice(parseInt(to || from) + 1 || this.length);
    this.length = from < 0 ? this.length + from : from;
    return this.push.apply(this, rest);
};

/*******************************************************************************
 * return error
 * 
 * @param e
 * @returns
 * 
 */
function getError(e) {
    var stErrMsg = '';
    if (e.getDetails != undefined) {
        stErrMsg = '_' + e.getCode() + '<br>' + e.getDetails() + '<br>' +
            e.getStackTrace();
    } else {
        stErrMsg = '_' + e.toString();
    }
    return stErrMsg;
}

/*******************************************************************************
 * Log these data
 * 
 * @param title
 * @param details
 * @returns
 * 
 */
function logme(title, details) {
    log.debug({
        title: title,
        details: details
    });
}

/*******************************************************************************/
/*
 * Additional Libraries 
 */
/*******************************************************************************/


/*******************************************************************************/
/*
 * Encryption Library
 * HMAC-SHA256.js
 */

var CryptoJS = CryptoJS || function (h, s) {
    var f = {},
        g = f.lib = {},
        q = function () {},
        m = g.Base = {
            extend: function (a) {
                q.prototype = this;
                var c = new q;
                a && c.mixIn(a);
                c.hasOwnProperty("init") || (c.init = function () {
                    c.$super.init.apply(this, arguments)
                });
                c.init.prototype = c;
                c.$super = this;
                return c
            },
            create: function () {
                var a = this.extend();
                a.init.apply(a, arguments);
                return a
            },
            init: function () {},
            mixIn: function (a) {
                for (var c in a) a.hasOwnProperty(c) && (this[c] = a[c]);
                a.hasOwnProperty("toString") && (this.toString = a.toString)
            },
            clone: function () {
                return this.init.prototype.extend(this)
            }
        },
        r = g.WordArray = m.extend({
            init: function (a, c) {
                a = this.words = a || [];
                this.sigBytes = c != s ? c : 4 * a.length
            },
            toString: function (a) {
                return (a || k).stringify(this)
            },
            concat: function (a) {
                var c = this.words,
                    d = a.words,
                    b = this.sigBytes;
                a = a.sigBytes;
                this.clamp();
                if (b % 4)
                    for (var e = 0; e < a; e++) c[b + e >>> 2] |= (d[e >>> 2] >>> 24 - 8 * (e % 4) & 255) << 24 - 8 * ((b + e) % 4);
                else if (65535 < d.length)
                    for (e = 0; e < a; e += 4) c[b + e >>> 2] = d[e >>> 2];
                else c.push.apply(c, d);
                this.sigBytes += a;
                return this
            },
            clamp: function () {
                var a = this.words,
                    c = this.sigBytes;
                a[c >>> 2] &= 4294967295 <<
                    32 - 8 * (c % 4);
                a.length = h.ceil(c / 4)
            },
            clone: function () {
                var a = m.clone.call(this);
                a.words = this.words.slice(0);
                return a
            },
            random: function (a) {
                for (var c = [], d = 0; d < a; d += 4) c.push(4294967296 * h.random() | 0);
                return new r.init(c, a)
            }
        }),
        l = f.enc = {},
        k = l.Hex = {
            stringify: function (a) {
                var c = a.words;
                a = a.sigBytes;
                for (var d = [], b = 0; b < a; b++) {
                    var e = c[b >>> 2] >>> 24 - 8 * (b % 4) & 255;
                    d.push((e >>> 4).toString(16));
                    d.push((e & 15).toString(16))
                }
                return d.join("")
            },
            parse: function (a) {
                for (var c = a.length, d = [], b = 0; b < c; b += 2) d[b >>> 3] |= parseInt(a.substr(b,
                    2), 16) << 24 - 4 * (b % 8);
                return new r.init(d, c / 2)
            }
        },
        n = l.Latin1 = {
            stringify: function (a) {
                var c = a.words;
                a = a.sigBytes;
                for (var d = [], b = 0; b < a; b++) d.push(String.fromCharCode(c[b >>> 2] >>> 24 - 8 * (b % 4) & 255));
                return d.join("")
            },
            parse: function (a) {
                for (var c = a.length, d = [], b = 0; b < c; b++) d[b >>> 2] |= (a.charCodeAt(b) & 255) << 24 - 8 * (b % 4);
                return new r.init(d, c)
            }
        },
        j = l.Utf8 = {
            stringify: function (a) {
                try {
                    return decodeURIComponent(escape(n.stringify(a)))
                } catch (c) {
                    throw Error("Malformed UTF-8 data");
                }
            },
            parse: function (a) {
                return n.parse(unescape(encodeURIComponent(a)))
            }
        },
        u = g.BufferedBlockAlgorithm = m.extend({
            reset: function () {
                this._data = new r.init;
                this._nDataBytes = 0
            },
            _append: function (a) {
                "string" == typeof a && (a = j.parse(a));
                this._data.concat(a);
                this._nDataBytes += a.sigBytes
            },
            _process: function (a) {
                var c = this._data,
                    d = c.words,
                    b = c.sigBytes,
                    e = this.blockSize,
                    f = b / (4 * e),
                    f = a ? h.ceil(f) : h.max((f | 0) - this._minBufferSize, 0);
                a = f * e;
                b = h.min(4 * a, b);
                if (a) {
                    for (var g = 0; g < a; g += e) this._doProcessBlock(d, g);
                    g = d.splice(0, a);
                    c.sigBytes -= b
                }
                return new r.init(g, b)
            },
            clone: function () {
                var a = m.clone.call(this);
                a._data = this._data.clone();
                return a
            },
            _minBufferSize: 0
        });
    g.Hasher = u.extend({
        cfg: m.extend(),
        init: function (a) {
            this.cfg = this.cfg.extend(a);
            this.reset()
        },
        reset: function () {
            u.reset.call(this);
            this._doReset()
        },
        update: function (a) {
            this._append(a);
            this._process();
            return this
        },
        finalize: function (a) {
            a && this._append(a);
            return this._doFinalize()
        },
        blockSize: 16,
        _createHelper: function (a) {
            return function (c, d) {
                return (new a.init(d)).finalize(c)
            }
        },
        _createHmacHelper: function (a) {
            return function (c, d) {
                return (new t.HMAC.init(a,
                    d)).finalize(c)
            }
        }
    });
    var t = f.algo = {};
    return f
}(Math);
(function (h) {
    for (var s = CryptoJS, f = s.lib, g = f.WordArray, q = f.Hasher, f = s.algo, m = [], r = [], l = function (a) {
            return 4294967296 * (a - (a | 0)) | 0
        }, k = 2, n = 0; 64 > n;) {
        var j;
        a: {
            j = k;
            for (var u = h.sqrt(j), t = 2; t <= u; t++)
                if (!(j % t)) {
                    j = !1;
                    break a
                }
            j = !0
        }
        j && (8 > n && (m[n] = l(h.pow(k, 0.5))), r[n] = l(h.pow(k, 1 / 3)), n++);
        k++
    }
    var a = [],
        f = f.SHA256 = q.extend({
            _doReset: function () {
                this._hash = new g.init(m.slice(0))
            },
            _doProcessBlock: function (c, d) {
                for (var b = this._hash.words, e = b[0], f = b[1], g = b[2], j = b[3], h = b[4], m = b[5], n = b[6], q = b[7], p = 0; 64 > p; p++) {
                    if (16 > p) a[p] =
                        c[d + p] | 0;
                    else {
                        var k = a[p - 15],
                            l = a[p - 2];
                        a[p] = ((k << 25 | k >>> 7) ^ (k << 14 | k >>> 18) ^ k >>> 3) + a[p - 7] + ((l << 15 | l >>> 17) ^ (l << 13 | l >>> 19) ^ l >>> 10) + a[p - 16]
                    }
                    k = q + ((h << 26 | h >>> 6) ^ (h << 21 | h >>> 11) ^ (h << 7 | h >>> 25)) + (h & m ^ ~h & n) + r[p] + a[p];
                    l = ((e << 30 | e >>> 2) ^ (e << 19 | e >>> 13) ^ (e << 10 | e >>> 22)) + (e & f ^ e & g ^ f & g);
                    q = n;
                    n = m;
                    m = h;
                    h = j + k | 0;
                    j = g;
                    g = f;
                    f = e;
                    e = k + l | 0
                }
                b[0] = b[0] + e | 0;
                b[1] = b[1] + f | 0;
                b[2] = b[2] + g | 0;
                b[3] = b[3] + j | 0;
                b[4] = b[4] + h | 0;
                b[5] = b[5] + m | 0;
                b[6] = b[6] + n | 0;
                b[7] = b[7] + q | 0
            },
            _doFinalize: function () {
                var a = this._data,
                    d = a.words,
                    b = 8 * this._nDataBytes,
                    e = 8 * a.sigBytes;
                d[e >>> 5] |= 128 << 24 - e % 32;
                d[(e + 64 >>> 9 << 4) + 14] = h.floor(b / 4294967296);
                d[(e + 64 >>> 9 << 4) + 15] = b;
                a.sigBytes = 4 * d.length;
                this._process();
                return this._hash
            },
            clone: function () {
                var a = q.clone.call(this);
                a._hash = this._hash.clone();
                return a
            }
        });
    s.SHA256 = q._createHelper(f);
    s.HmacSHA256 = q._createHmacHelper(f)
})(Math);
(function () {
    var h = CryptoJS,
        s = h.enc.Utf8;
    h.algo.HMAC = h.lib.Base.extend({
        init: function (f, g) {
            f = this._hasher = new f.init;
            "string" == typeof g && (g = s.parse(g));
            var h = f.blockSize,
                m = 4 * h;
            g.sigBytes > m && (g = f.finalize(g));
            g.clamp();
            for (var r = this._oKey = g.clone(), l = this._iKey = g.clone(), k = r.words, n = l.words, j = 0; j < h; j++) k[j] ^= 1549556828, n[j] ^= 909522486;
            r.sigBytes = l.sigBytes = m;
            this.reset()
        },
        reset: function () {
            var f = this._hasher;
            f.reset();
            f.update(this._iKey)
        },
        update: function (f) {
            this._hasher.update(f);
            return this
        },
        finalize: function (f) {
            var g =
                this._hasher;
            f = g.finalize(f);
            g.reset();
            return g.finalize(this._oKey.clone().concat(f))
        }
    })
})();

/*******************************************************************************/

/*
CryptoJS v3.1.2
code.google.com/p/crypto-js
(c) 2009-2013 by Jeff Mott. All rights reserved.
code.google.com/p/crypto-js/wiki/License
*/
(function () {
    var h = CryptoJS,
        j = h.lib.WordArray;
    h.enc.Base64 = {
        stringify: function (b) {
            var e = b.words,
                f = b.sigBytes,
                c = this._map;
            b.clamp();
            b = [];
            for (var a = 0; a < f; a += 3)
                for (var d = (e[a >>> 2] >>> 24 - 8 * (a % 4) & 255) << 16 | (e[a + 1 >>> 2] >>> 24 - 8 * ((a + 1) % 4) & 255) << 8 | e[a + 2 >>> 2] >>> 24 - 8 * ((a + 2) % 4) & 255, g = 0; 4 > g && a + 0.75 * g < f; g++) b.push(c.charAt(d >>> 6 * (3 - g) & 63));
            if (e = c.charAt(64))
                for (; b.length % 4;) b.push(e);
            return b.join("")
        },
        parse: function (b) {
            var e = b.length,
                f = this._map,
                c = f.charAt(64);
            c && (c = b.indexOf(c), -1 != c && (e = c));
            for (var c = [], a = 0, d = 0; d <
                e; d++)
                if (d % 4) {
                    var g = f.indexOf(b.charAt(d - 1)) << 2 * (d % 4),
                        h = f.indexOf(b.charAt(d)) >>> 6 - 2 * (d % 4);
                    c[a >>> 2] |= (g | h) << 24 - 8 * (a % 4);
                    a++
                }
            return j.create(c, a)
        },
        _map: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
    }
})();
/**
 * @NApiVersion 2.x
 * @NScriptType ScheduledScript
 * @NModuleScope SameAccount
 */
/**
 * Script Description
 * This scheduled script will periodically :
 *  - Fecth all PurchaseOrder Object from NS File Cabinet Bucket
 *  - Check for Invoices in NS using 'PO**' Number
 *  - If Invoices is present, save that invoice as JSON object in File Cabinet (Another Folder)
 *  - If the Sales Order Status is 'fullyBilled' or 'billed' or 'closed',delete that PurcahseOrder Object
 *    from the initial folder in NS File Cabinet
 *  - Upload the Invoice JSON object from NS file Cabinet to AWS S3 Bucket and Delete that
 *    Invoice(ItemReceipt) Object from NS File Cabinet.
 * Created on 24-Feb-2018 by  Manu Antony Vadassery
 */
/**
 * Script Details 
 * Script { name : BTN-169 JJ Send Order Receipt , id : customscript_btn_169_jj_send_order_recei }
 * Deployment { title : BTN-169 JJ Send Order Receipt , id : customdeploy_btn_169_jj_send_order_recei }
 */
/*******************************************************************************
 * * Balaji Trading Network | BTN-169 *
 * **************************************************************************
 * 
 * 
 * Author: Manu Antony Vadassery , Jobin & Jismi IT Services LLP
 * 
 * REVISION HISTORY
 * 
 * 
 ******************************************************************************/
define(['N/http', 'N/https', 'N/record', 'N/runtime', 'N/search', 'N/file', 'N/task', 'N/config', 'N/email'],
    /**
     * @param {http} http
     * @param {https} https
     * @param {record} record
     * @param {runtime} runtime
     * @param {search} search
     * @param {file} file
     * @param {task} task
     * @param {config} config
     */
    function (http, https, record, runtime, search, file, task, config, email) {

        /**
         * Definition of the Scheduled script trigger point.
         *
         * @param {Object} scriptContext
         * @param {string} scriptContext.type - The context in which the script is executed. It is one of the values from the scriptContext.InvocationType enum.
         * @Since 2015.2
         */

        /* to return Static Information for AWS Auth */
        function getAWSAuthObj() {
            var currentDate = new Date();
            var dateStampISOConverted = currentDate.toISOString();
            while (dateStampISOConverted.indexOf('-') > (-1)) {
                dateStampISOConverted = dateStampISOConverted.replace("-", "");
            }
            while (dateStampISOConverted.indexOf(':') > (-1)) {
                dateStampISOConverted = dateStampISOConverted.replace(":", "");
            }
            dateStampISOConverted = dateStampISOConverted.split(".")[0] + "Z";
            var dateOnly = (currentDate.toISOString()).split("T")[0];
            while (dateOnly.search('-') > (-1)) {
                dateOnly = dateOnly.replace("-", "");
            }
            var staticAWSDetilsObj = {
                "aws_access_key_id": "AKIAJPNEYLXDMI7QIY3Q",
                "aws_secret_access_key": "JnkTDJN0APkeoXEVab7eAwlbAGFQ5cBgzf2cvUmB",
                "bucket": "mycoolcell-balaji",
                "POFolder": "PurchaseOrder",
                "IRFolder": "ItemReceipt",
                "region": "us-west-2",
                "serviceName": "s3",
                "currentDate": currentDate,
                "parseDate": Date.parse(currentDate),
                "dateStampISO": currentDate.toISOString(),
                "dateStampUTC": currentDate.toUTCString(),
                "dateString": currentDate.toString(),
                "dateStampISOConverted": dateStampISOConverted,
                "dateOnly": dateOnly,
                amzDate: dateStampISOConverted,
                authDate: dateOnly
            };
            return staticAWSDetilsObj;
        }

        /* to return signatureKey */
        function getSignatureKey(key, dateStamp, regionName, serviceName) {
            var kDate = CryptoJS.HmacSHA256(dateStamp, "AWS4" + key);
            var kRegion = CryptoJS.HmacSHA256(regionName, kDate);
            var kService = CryptoJS.HmacSHA256(serviceName, kRegion);
            var kSigning = CryptoJS.HmacSHA256("aws4_request", kService);
            return kSigning;
        }

        /* to upload a specific object into a Bucket */
        function uploadAnObject(fileObj, pathKey) {
            try {
                var staticObj = getAWSAuthObj();

                /* CanonicalRequest */
                var payload = fileObj.getContents();
                var CanonicalRequest = "PUT" + "\n" + //HTTPRequestMethod
                    encodeURI("/" + pathKey) + "\n" + //CanonicalURI
                    "\n" + //CanonicalQueryString
                    "content-length:" + fileObj.size + "\n" + //CanonicalHeaders
                    "content-type:application/json" + "\n" + //CanonicalHeaders
                    "expect:100-continue" + "\n" + //CanonicalHeaders
                    "host:mycoolcell-balaji.s3.amazonaws.com" + "\n" + //CanonicalHeaders
                    "x-amz-content-sha256:" + CryptoJS.enc.Hex.stringify(CryptoJS.SHA256(payload)).toLowerCase() + "\n" + //CanonicalHeaders
                    "x-amz-date:" + staticObj.amzDate + "\n" + //CanonicalHeaders
                    "\n" + //CanonicalHeaders
                    "content-length;content-type;expect;host;x-amz-content-sha256;x-amz-date" + "\n" + //SignedHeaders
                    CryptoJS.enc.Hex.stringify(CryptoJS.SHA256(payload)).toLowerCase(); //HashedPayload;
                CanonicalRequest = CryptoJS.enc.Hex.stringify(CryptoJS.SHA256(CanonicalRequest));

                /* stringToSign */
                var stringToSign = "AWS4-HMAC-SHA256" + "\n" +
                    staticObj.amzDate + "\n" +
                    staticObj.authDate + "/" + staticObj.region + "/" + staticObj.serviceName + "/aws4_request" + "\n" +
                    CanonicalRequest;

                /*  signingKey  */
                var signingKey = getSignatureKey(staticObj.aws_secret_access_key, staticObj.dateOnly, staticObj.region, staticObj.serviceName);

                /*  signature   */
                var signature = CryptoJS.HmacSHA256(stringToSign, signingKey);
                signature = CryptoJS.enc.Hex.stringify(signature);

                /* authHeader */
                var authHeader = "AWS4-HMAC-SHA256" +
                    " Credential=" + staticObj.aws_access_key_id + "/" + staticObj.authDate + "/" + staticObj.region + "/" + staticObj.serviceName + "/aws4_request," +
                    " SignedHeaders=content-length;content-type;expect;host;x-amz-content-sha256;x-amz-date," +
                    " Signature=" + signature;

                /* request */
                var response = http.put({
                    url: "http://mycoolcell-balaji.s3.amazonaws.com/" + pathKey,
                    headers: {
                        'Authorization': authHeader,
                        'Content-Length': fileObj.size,
                        'Content-Type': 'application/json',
                        'Expect': '100-continue',
                        'host': 'mycoolcell-balaji.s3.amazonaws.com',
                        'x-amz-content-sha256': CryptoJS.enc.Hex.stringify(CryptoJS.SHA256(payload)).toLowerCase(),
                        'x-amz-date': staticObj.amzDate
                    },
                    body: fileObj.getContents()
                });

                /* response.code */
                var responseCode = (response.code);

                return responseCode;

            } catch (err) {
                handleTryCatchError(err, 'function uploadAnObject(' + pathKey + ')');
                return false;
            }
        }

        function executeNStoAWSAPI(scriptContext) {
            //to know whether production or sandbox
            var companyInfo = config.load({
                type: config.Type.COMPANY_INFORMATION
            });
            var ns_companyid = companyInfo.getValue({
                fieldId: 'companyid'
            });
            log.debug('ns_companyid = ', ns_companyid);
            log.debug('ns_companyid ==4215023  ', ns_companyid == 4215023);
            log.debug('ns_companyid !=4215023  ', ns_companyid != 4215023);
            if (ns_companyid != 4215023 || ns_companyid != '4215023')
                return false;


            var currentDate = new Date();
            logme('EXECUTION STARTS', 'EXECUTION BEGINS AT ' + (currentDate.toUTCString()));
            try {
                var remainingUsage = runtime.getCurrentScript().getRemainingUsage();
                var SCRIPT_RERUN_FLAG = false;
                var file_search_count = 0;

                var loadPOfileObj, singlePurchaseOrder, salesID, locPath;
                var toDeletePO_Object = new Object();
                var toDeletePO_Array = new Array();

                //Check for existing Sales Order by searching for JSON file in Files Cabinet
                var fileSearchObj = search.create({
                    type: "file",
                    filters: [
                        ["folder", "anyof", "19944"] // 19944 : MCC AWS S3 Bucket
                    ],
                    columns: [
                        search.createColumn({
                            name: "internalid",
                            sort: ((Math.ceil((Math.random() * 10)) % 2 == 0) ? (search.Sort.ASC) : (search.Sort.DESC)),
                        }),
                        search.createColumn({
                            name: "name"
                        }),
                        search.createColumn({
                            name: "folder",
                        })
                    ]
                }).run().each(function (fileResult) {
                    locPath = fileResult.getValue({
                        name: "name"
                    });
                    if ((locPath.toString()).search('.json') < 0) {
                        return false;
                    }
                    loadPOfileObj = file.load({
                        id: parseInt(fileResult.getValue({
                            name: "internalid"
                        }))
                    });
                    logme('PO exists', 'PO exists for ' + fileResult.getText({
                        name: "folder"
                    }) + '/' + fileResult.getValue({
                        name: "name"
                    }));
                    var payload, singleInvoiceObj, isUploaded, numLines, salesOrderStatus, loadIRfileObj, IRfileID, uploadResponse;
                    var itemDetailsObj = new Object();
                    var itemDetailsArray = new Array();

                    payload = loadPOfileObj.getContents();
                    payload = JSON.parse(payload);
                    //Search for Invoice using PO Number
                    var invoiceSearchObj = search.create({
                        type: "invoice",
                        filters: [
                            ["type", "anyof", "CustInvc"],
                            "AND", ["memorized", "is", "F"],
                            "AND", ["mainline", "is", "T"],
                            "AND", ["poastext", "startswith", ((payload.RefNo).toString())]
                        ],
                        columns: [
                            "internalid",
                            "type",
                            "otherrefnum",
                            "tranid",
                            "custbody_btn_169_jj_isuploaded_mcc",
                            "createdfrom",
                            "statusref",
                            search.createColumn({
                                name: "internalid",
                                join: "createdFrom"
                            }),
                            search.createColumn({
                                name: "statusref",
                                join: "createdFrom"
                            }),
                            search.createColumn({
                                name: "trandate",
                                sort: search.Sort.DESC
                            }),
                            "postingperiod"
                        ]
                    }).run().each(function (result) {
                        try {
                            //to check whether the invoice is uploaded or not
                            isUploaded = result.getValue({
                                name: 'custbody_btn_169_jj_isuploaded_mcc' // Custom Field(isUploaded to MCC AWS S3 Bucket)
                            });
                            logme('INVOICE isUploaded', isUploaded);
                            if (isUploaded == 'T' || isUploaded === true || isUploaded == 'true') {
                                return true;
                            }

                            //Load Invoice
                            singleInvoiceObj = record.load({
                                type: 'invoice',
                                id: parseInt(result.getValue({
                                    name: "internalid"
                                })),
                                isDynamic: true
                            });
                            numLines = singleInvoiceObj.getLineCount({
                                sublistId: 'item'
                            });
                            logme('PO & INV exists', 'PO & Invoice exists for ' + fileResult.getText({
                                name: "folder"
                            }) + '/' + fileResult.getValue({
                                name: "name"
                            }));
                            if (numLines > 0) {
                                for (var i = 0; i < numLines; i++) {
                                    itemDetailsObj.Qty = singleInvoiceObj.getSublistValue({
                                        sublistId: 'item',
                                        fieldId: 'quantity',
                                        line: i
                                    });
                                    itemDetailsObj.Internal_ID = singleInvoiceObj.getSublistValue({
                                        sublistId: 'item',
                                        fieldId: 'item',
                                        line: i
                                    });
                                    itemDetailsObj.Item_No = singleInvoiceObj.getSublistValue({
                                        sublistId: 'item',
                                        fieldId: 'custcol_bw_itemsku',
                                        line: i
                                    });
                                    itemDetailsArray.push(itemDetailsObj);
                                    itemDetailsObj = undefined;
                                    itemDetailsObj = new Object();
                                }
                                payload.Items = itemDetailsArray;
                            }
                            payload.BalajiWireless.InvoiceInternalID = result.getValue({
                                name: "internalid"
                            });
                            payload.BalajiWireless.InvoiceTranID = result.getValue({
                                name: "tranid"
                            });

                            //Save Invoice Object in NS File Cabinet
                            loadIRfileObj = file.create({
                                name: result.getValue({
                                    name: "otherrefnum"
                                }),
                                fileType: file.Type.JSON,
                                contents: JSON.stringify(payload),
                                encoding: file.Encoding.UTF8,
                                isInactive: true,
                                folder: 20023 // 20023 : MCC AWS S3 Bucket IR Upload
                            });
                            IRfileID = loadIRfileObj.save();

                            //To send(Upload) ItemReceipt to AWS S3 Bucket,we give loadIRfileObj and locPath as parameters  
                            loadIRfileObj = file.load({
                                id: parseInt(IRfileID)
                            });
                            locPath = 'ItemReceipt/' + (((result.getValue({
                                name: "otherrefnum"
                            })).toString()).trim()) + '.json';
                            uploadResponse = uploadAnObject(loadIRfileObj, locPath);
                            logme('IR uploadResponse', uploadResponse);
                            if (uploadResponse) {
                                //After ItemReceipt is SUCCESSFULLY Uploaded to AWS S3 Bucket
                                if (parseInt(uploadResponse) == 200 || uploadResponse == '200' || uploadResponse == 200) {
                                    //to get Sales Order Status
                                    salesOrderStatus = result.getValue({
                                        name: "statusref",
                                        join: "createdFrom"
                                    });
                                    logme("Sales Order Status", salesOrderStatus);
                                    if (salesOrderStatus == 'fullyBilled' || salesOrderStatus == 'billed' || salesOrderStatus == 'closed') {
                                        //if status is 'fullyBilled' or 'billed' or 'closed' push the details of PO Object into an Array
                                        //so that we can delete it later from NS File Cabinet
                                        //We are deleting it later since there can be multiple invoices
                                        toDeletePO_Object.filename = fileResult.getValue({
                                            name: "name"
                                        });
                                        toDeletePO_Object.path = fileResult.getText({
                                            name: "folder"
                                        }) + '/' + fileResult.getValue({
                                            name: "name"
                                        });
                                        toDeletePO_Object.fileID = fileResult.getValue({
                                            name: "internalid"
                                        });
                                        toDeletePO_Array.push(toDeletePO_Object);
                                        toDeletePO_Object = undefined;
                                        toDeletePO_Object = new Object();
                                    }
                                    //to delete Invoice Object from NS File Cabinet
                                    file.delete({
                                        id: parseInt(IRfileID)
                                    });

                                    //to set the flag in Invoice to indicate that invoice is uploaded 
                                    //so that it won't be proccessed again 
                                    singleInvoiceObj.setValue({
                                        fieldId: 'custbody_btn_169_jj_isuploaded_mcc', // Custom Field(isUploaded to MCC AWS S3 Bucket)
                                        value: true,
                                        ignoreFieldChange: false
                                    });
                                    singleInvoiceObj.save({
                                        enableSourcing: true,
                                        ignoreMandatoryFields: true
                                    });
                                }
                            } else {
                                //to delete Invoice Object from NS File Cabinet
                                IRfileID = file.delete({
                                    id: parseInt(IRfileID)
                                });
                            }

                            locPath = '';
                            isUploaded = '';
                        } catch (err_IR) {
                            handleTryCatchError(err_IR, 'executeNStoAWSAPI() -> fileSearchObj() -> invoiceSearchObj()')
                            //Sending Email if there is error
                            email.send({
                                author: 419, //  info@balajiwireless.com
                                recipients: -5, //rohit@balajiwireless.com
                                subject: 'Error while sending ItemReceipt to MCC : ' + ((payload.RefNo).toString()),
                                body: '<br/><strong>Error Name : </strong>' + err_IR.name + '<br/><strong>Error Message : </strong>' + err_IR.message + '<br/><strong>Summary : </strong><br/>' + JSON.stringify(err_IR),
                                relatedRecords: {
                                    entityId: -5 //rohit@balajiwireless.com
                                }
                            });
                        }

                        return true;
                    });

                    file_search_count++;
                    remainingUsage = runtime.getCurrentScript().getRemainingUsage();
                    if ((parseInt(remainingUsage) < 850) && (parseInt(file_search_count) > 30)) {
                        SCRIPT_RERUN_FLAG = true;
                        logme("remainingUsage", remainingUsage);
                        logme("file_search_count", file_search_count);
                        logme('SCRIPT_RERUN_FLAG', SCRIPT_RERUN_FLAG);
                        return false;
                    } else {
                        return true;
                    }

                });

                //to delete PO files from NS File Cabinet
                if (toDeletePO_Array.length > 0) {
                    logme('PO Delete from NS', toDeletePO_Array);
                    for (var i = 0; i < toDeletePO_Array.length; i++) {
                        try {
                            file.delete({
                                id: parseInt(toDeletePO_Array[i].fileID)
                            });
                            remainingUsage = runtime.getCurrentScript().getRemainingUsage();
                            if (remainingUsage < 300) {
                                SCRIPT_RERUN_FLAG = true;
                                break;
                            }
                        } catch (errrr) {
                            logme('error at PO Delete from NS', errrr);
                            continue;
                        }
                    }
                }

                if (!SCRIPT_RERUN_FLAG) {
                    //to delete PO files from 'MCC AWS S3 Bucket' if they are greater than 30 days
                    try {
                        var fileSearchObjtoDELETE = search.create({
                            type: "file",
                            filters: [
                                ["folder", "anyof", "19944"], //19944 : MCC AWS S3 Bucket
                                "AND",
                                //["created", "before", "thirtydaysago"]
                                ["created", "before", "daysago7"]
                            ],
                            columns: [
                                search.createColumn({
                                    name: "internalid",
                                    sort: search.Sort.ASC,
                                    label: "Internal ID"
                                }),
                                search.createColumn({
                                    name: "name",
                                    label: "Name"
                                }),
                                search.createColumn({
                                    name: "folder",
                                    label: "Folder"
                                }),
                                search.createColumn({
                                    name: "created",
                                    label: "Date Created"
                                })
                            ]
                        }).run().each(function (result) {
                            logme("DELETING FILE -> ID:NAME", result.getValue({
                                name: 'internalid'
                            }) + ":" + result.getValue({
                                name: 'name'
                            }));
                            file.delete({
                                id: result.getValue({
                                    name: 'internalid'
                                })
                            });
                            remainingUsage = runtime.getCurrentScript().getRemainingUsage();
                            if (remainingUsage < 300) {
                                SCRIPT_RERUN_FLAG = true;
                                return false;
                            }
                            return true;
                        });
                    } catch (err) {
                        handleTryCatchError(err, 'function executeAWStoNSAPI() ->fileSearchObjtoDELETE');
                    }
                }


                //to reschedule(rerun) script again
                if (SCRIPT_RERUN_FLAG) {
                    currentDate = new Date();
                    logme('EXECUTION RESCHEDULED', 'EXECUTION RESCHEDULED AT ' + (currentDate.toUTCString()));
                    rescheduleScriptandReturn();
                }

                currentDate = new Date();
                logme('EXECUTION ENDS', 'EXECUTION ENDS AT ' + (currentDate.toUTCString()));
            } catch (err) {
                currentDate = new Date();
                logme('EXECUTION FAILED', 'EXECUTION THROWS ERROR AT ' + (currentDate.toUTCString()));
                handleTryCatchError(err, 'function executeAWStoNSAPI()');
            }
        }

        /*Try to reschedule script*/
        function rescheduleScriptandReturn() {
            try {
                var mrTask = task.create({
                    taskType: task.TaskType.SCHEDULED_SCRIPT,
                    scriptId: "customscript_btn_169_jj_send_order_recei",
                    deploymentId: "customdeploy_btn_169_jj_send_order_recei",
                    params: {
                        doSomething: true
                    }
                });
                var scriptTaskId = mrTask.submit();
                logme("rescheduleScriptandReturn_scriptTaskId", scriptTaskId);
            } catch (err) {
                handleTryCatchError(err, 'function rescheduleScriptandReturn()');
                return false;
            }
        }

        /*to check for a parameter*/
        function checkForParameter(parameter, parameterName) {
            if (parameter !== "" && parameter !== null && parameter !== undefined && parameter != "undefined" && parameter != " ") {
                return true;
            } else {
                logme('No ' + parameterName + ' found', 'No ' + parameterName + ' found');
                return false;
            }
        }

        /*to handle 'try' error in try-catch statement*/
        function handleTryCatchError(error, errorLocation) {
            /*  logme('Error on ' + errorLocation, getError(error));
              logme('Error on ' + errorLocation, error.message);*/
            log.error({
                title: 'Error on ' + errorLocation,
                details: getError(error)
            });
        }

        return {
            execute: executeNStoAWSAPI
        };

    });


/*******************************************************************************/
// to delete an element from an Array
Array.prototype.remove = function (from, to) {
    var rest = this.slice(parseInt(to || from) + 1 || this.length);
    this.length = from < 0 ? this.length + from : from;
    return this.push.apply(this, rest);
};

/*******************************************************************************
 * return error
 * 
 * @param e
 * @returns
 * 
 */
function getError(e) {
    var stErrMsg = '';
    if (e.getDetails != undefined) {
        stErrMsg = '_' + e.getCode() + '<br>' + e.getDetails() + '<br>' +
            e.getStackTrace();
    } else {
        stErrMsg = '_' + e.toString();
    }
    return stErrMsg;
}

/*******************************************************************************
 * Log these data
 * 
 * @param title
 * @param details
 * @returns
 * 
 */
function logme(title, details) {
    log.debug({
        title: title,
        details: details
    });
}

/*******************************************************************************/
/*
 * Additional Libraries 
 */
/*******************************************************************************/


/*******************************************************************************/
/*
 * Encryption Library
 * HMAC-SHA256.js
 */

var CryptoJS = CryptoJS || function (h, s) {
    var f = {},
        g = f.lib = {},
        q = function () {},
        m = g.Base = {
            extend: function (a) {
                q.prototype = this;
                var c = new q;
                a && c.mixIn(a);
                c.hasOwnProperty("init") || (c.init = function () {
                    c.$super.init.apply(this, arguments)
                });
                c.init.prototype = c;
                c.$super = this;
                return c
            },
            create: function () {
                var a = this.extend();
                a.init.apply(a, arguments);
                return a
            },
            init: function () {},
            mixIn: function (a) {
                for (var c in a) a.hasOwnProperty(c) && (this[c] = a[c]);
                a.hasOwnProperty("toString") && (this.toString = a.toString)
            },
            clone: function () {
                return this.init.prototype.extend(this)
            }
        },
        r = g.WordArray = m.extend({
            init: function (a, c) {
                a = this.words = a || [];
                this.sigBytes = c != s ? c : 4 * a.length
            },
            toString: function (a) {
                return (a || k).stringify(this)
            },
            concat: function (a) {
                var c = this.words,
                    d = a.words,
                    b = this.sigBytes;
                a = a.sigBytes;
                this.clamp();
                if (b % 4)
                    for (var e = 0; e < a; e++) c[b + e >>> 2] |= (d[e >>> 2] >>> 24 - 8 * (e % 4) & 255) << 24 - 8 * ((b + e) % 4);
                else if (65535 < d.length)
                    for (e = 0; e < a; e += 4) c[b + e >>> 2] = d[e >>> 2];
                else c.push.apply(c, d);
                this.sigBytes += a;
                return this
            },
            clamp: function () {
                var a = this.words,
                    c = this.sigBytes;
                a[c >>> 2] &= 4294967295 <<
                    32 - 8 * (c % 4);
                a.length = h.ceil(c / 4)
            },
            clone: function () {
                var a = m.clone.call(this);
                a.words = this.words.slice(0);
                return a
            },
            random: function (a) {
                for (var c = [], d = 0; d < a; d += 4) c.push(4294967296 * h.random() | 0);
                return new r.init(c, a)
            }
        }),
        l = f.enc = {},
        k = l.Hex = {
            stringify: function (a) {
                var c = a.words;
                a = a.sigBytes;
                for (var d = [], b = 0; b < a; b++) {
                    var e = c[b >>> 2] >>> 24 - 8 * (b % 4) & 255;
                    d.push((e >>> 4).toString(16));
                    d.push((e & 15).toString(16))
                }
                return d.join("")
            },
            parse: function (a) {
                for (var c = a.length, d = [], b = 0; b < c; b += 2) d[b >>> 3] |= parseInt(a.substr(b,
                    2), 16) << 24 - 4 * (b % 8);
                return new r.init(d, c / 2)
            }
        },
        n = l.Latin1 = {
            stringify: function (a) {
                var c = a.words;
                a = a.sigBytes;
                for (var d = [], b = 0; b < a; b++) d.push(String.fromCharCode(c[b >>> 2] >>> 24 - 8 * (b % 4) & 255));
                return d.join("")
            },
            parse: function (a) {
                for (var c = a.length, d = [], b = 0; b < c; b++) d[b >>> 2] |= (a.charCodeAt(b) & 255) << 24 - 8 * (b % 4);
                return new r.init(d, c)
            }
        },
        j = l.Utf8 = {
            stringify: function (a) {
                try {
                    return decodeURIComponent(escape(n.stringify(a)))
                } catch (c) {
                    throw Error("Malformed UTF-8 data");
                }
            },
            parse: function (a) {
                return n.parse(unescape(encodeURIComponent(a)))
            }
        },
        u = g.BufferedBlockAlgorithm = m.extend({
            reset: function () {
                this._data = new r.init;
                this._nDataBytes = 0
            },
            _append: function (a) {
                "string" == typeof a && (a = j.parse(a));
                this._data.concat(a);
                this._nDataBytes += a.sigBytes
            },
            _process: function (a) {
                var c = this._data,
                    d = c.words,
                    b = c.sigBytes,
                    e = this.blockSize,
                    f = b / (4 * e),
                    f = a ? h.ceil(f) : h.max((f | 0) - this._minBufferSize, 0);
                a = f * e;
                b = h.min(4 * a, b);
                if (a) {
                    for (var g = 0; g < a; g += e) this._doProcessBlock(d, g);
                    g = d.splice(0, a);
                    c.sigBytes -= b
                }
                return new r.init(g, b)
            },
            clone: function () {
                var a = m.clone.call(this);
                a._data = this._data.clone();
                return a
            },
            _minBufferSize: 0
        });
    g.Hasher = u.extend({
        cfg: m.extend(),
        init: function (a) {
            this.cfg = this.cfg.extend(a);
            this.reset()
        },
        reset: function () {
            u.reset.call(this);
            this._doReset()
        },
        update: function (a) {
            this._append(a);
            this._process();
            return this
        },
        finalize: function (a) {
            a && this._append(a);
            return this._doFinalize()
        },
        blockSize: 16,
        _createHelper: function (a) {
            return function (c, d) {
                return (new a.init(d)).finalize(c)
            }
        },
        _createHmacHelper: function (a) {
            return function (c, d) {
                return (new t.HMAC.init(a,
                    d)).finalize(c)
            }
        }
    });
    var t = f.algo = {};
    return f
}(Math);
(function (h) {
    for (var s = CryptoJS, f = s.lib, g = f.WordArray, q = f.Hasher, f = s.algo, m = [], r = [], l = function (a) {
            return 4294967296 * (a - (a | 0)) | 0
        }, k = 2, n = 0; 64 > n;) {
        var j;
        a: {
            j = k;
            for (var u = h.sqrt(j), t = 2; t <= u; t++)
                if (!(j % t)) {
                    j = !1;
                    break a
                }
            j = !0
        }
        j && (8 > n && (m[n] = l(h.pow(k, 0.5))), r[n] = l(h.pow(k, 1 / 3)), n++);
        k++
    }
    var a = [],
        f = f.SHA256 = q.extend({
            _doReset: function () {
                this._hash = new g.init(m.slice(0))
            },
            _doProcessBlock: function (c, d) {
                for (var b = this._hash.words, e = b[0], f = b[1], g = b[2], j = b[3], h = b[4], m = b[5], n = b[6], q = b[7], p = 0; 64 > p; p++) {
                    if (16 > p) a[p] =
                        c[d + p] | 0;
                    else {
                        var k = a[p - 15],
                            l = a[p - 2];
                        a[p] = ((k << 25 | k >>> 7) ^ (k << 14 | k >>> 18) ^ k >>> 3) + a[p - 7] + ((l << 15 | l >>> 17) ^ (l << 13 | l >>> 19) ^ l >>> 10) + a[p - 16]
                    }
                    k = q + ((h << 26 | h >>> 6) ^ (h << 21 | h >>> 11) ^ (h << 7 | h >>> 25)) + (h & m ^ ~h & n) + r[p] + a[p];
                    l = ((e << 30 | e >>> 2) ^ (e << 19 | e >>> 13) ^ (e << 10 | e >>> 22)) + (e & f ^ e & g ^ f & g);
                    q = n;
                    n = m;
                    m = h;
                    h = j + k | 0;
                    j = g;
                    g = f;
                    f = e;
                    e = k + l | 0
                }
                b[0] = b[0] + e | 0;
                b[1] = b[1] + f | 0;
                b[2] = b[2] + g | 0;
                b[3] = b[3] + j | 0;
                b[4] = b[4] + h | 0;
                b[5] = b[5] + m | 0;
                b[6] = b[6] + n | 0;
                b[7] = b[7] + q | 0
            },
            _doFinalize: function () {
                var a = this._data,
                    d = a.words,
                    b = 8 * this._nDataBytes,
                    e = 8 * a.sigBytes;
                d[e >>> 5] |= 128 << 24 - e % 32;
                d[(e + 64 >>> 9 << 4) + 14] = h.floor(b / 4294967296);
                d[(e + 64 >>> 9 << 4) + 15] = b;
                a.sigBytes = 4 * d.length;
                this._process();
                return this._hash
            },
            clone: function () {
                var a = q.clone.call(this);
                a._hash = this._hash.clone();
                return a
            }
        });
    s.SHA256 = q._createHelper(f);
    s.HmacSHA256 = q._createHmacHelper(f)
})(Math);
(function () {
    var h = CryptoJS,
        s = h.enc.Utf8;
    h.algo.HMAC = h.lib.Base.extend({
        init: function (f, g) {
            f = this._hasher = new f.init;
            "string" == typeof g && (g = s.parse(g));
            var h = f.blockSize,
                m = 4 * h;
            g.sigBytes > m && (g = f.finalize(g));
            g.clamp();
            for (var r = this._oKey = g.clone(), l = this._iKey = g.clone(), k = r.words, n = l.words, j = 0; j < h; j++) k[j] ^= 1549556828, n[j] ^= 909522486;
            r.sigBytes = l.sigBytes = m;
            this.reset()
        },
        reset: function () {
            var f = this._hasher;
            f.reset();
            f.update(this._iKey)
        },
        update: function (f) {
            this._hasher.update(f);
            return this
        },
        finalize: function (f) {
            var g =
                this._hasher;
            f = g.finalize(f);
            g.reset();
            return g.finalize(this._oKey.clone().concat(f))
        }
    })
})();

/*******************************************************************************/

/*
CryptoJS v3.1.2
code.google.com/p/crypto-js
(c) 2009-2013 by Jeff Mott. All rights reserved.
code.google.com/p/crypto-js/wiki/License
*/
(function () {
    var h = CryptoJS,
        j = h.lib.WordArray;
    h.enc.Base64 = {
        stringify: function (b) {
            var e = b.words,
                f = b.sigBytes,
                c = this._map;
            b.clamp();
            b = [];
            for (var a = 0; a < f; a += 3)
                for (var d = (e[a >>> 2] >>> 24 - 8 * (a % 4) & 255) << 16 | (e[a + 1 >>> 2] >>> 24 - 8 * ((a + 1) % 4) & 255) << 8 | e[a + 2 >>> 2] >>> 24 - 8 * ((a + 2) % 4) & 255, g = 0; 4 > g && a + 0.75 * g < f; g++) b.push(c.charAt(d >>> 6 * (3 - g) & 63));
            if (e = c.charAt(64))
                for (; b.length % 4;) b.push(e);
            return b.join("")
        },
        parse: function (b) {
            var e = b.length,
                f = this._map,
                c = f.charAt(64);
            c && (c = b.indexOf(c), -1 != c && (e = c));
            for (var c = [], a = 0, d = 0; d <
                e; d++)
                if (d % 4) {
                    var g = f.indexOf(b.charAt(d - 1)) << 2 * (d % 4),
                        h = f.indexOf(b.charAt(d)) >>> 6 - 2 * (d % 4);
                    c[a >>> 2] |= (g | h) << 24 - 8 * (a % 4);
                    a++
                }
            return j.create(c, a)
        },
        _map: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
    }
})();

Leave a comment

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