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+/="
}
})();