Jira Code: TC-81
This article briefs about a custom page update that is used to send customer statements in bulk. And customized it so that the start date become editable.
Client script
/**
* @NApiVersion 2.x
* @NScriptType ClientScript
* @NModuleScope SameAccount
*/
/*******************************************************************************
* * Taipan Canada | TC | TC-40 | Customer Details Form *
* **************************************************************************
*
*
* Author: Jobin & Jismi IT Services LLP
*
* REVISION HISTORY
*
*
******************************************************************************/
define(['N/https', 'N/currentRecord', 'N/runtime', 'N/url', 'N/ui/message'],
function (https, currentRecord, runtime, url, message) {
//To check whether a value exists in parameter
function checkForParameter(parameter, parameterName) {
if (parameter !== null && parameter !== undefined && parameter !== false && parameter !== "null" && parameter !== "undefined" && parameter !== "false" && parameter != "" && parameter != " ") {
return true;
} else {
if (parameterName)
console.log('Empty Value found for parameter' + parameterName);
return false;
}
}
//To assign a default value if the it is empty
function assignDefaultValue(value, defaultValue) {
if (checkForParameter(value))
return value;
else
return defaultValue;
}
// for getting parameter by name .................
function getParameterByName(name, url) {
if (!url)
url = window.location.href;
name = name.replace(/[\[\]]/g, "\\$&");
var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
results = regex
.exec(url);
if (!results)
return null;
if (!results[2])
return ' ';
return decodeURIComponent(results[2].replace(/\+/g, " "));
}
var main = {
loadLibrary: function (url, type, isAsync) {
if (checkForParameter(url) && checkForParameter(type)) {
isAsync = (isAsync) ? true : false;
var head, script;
if (type == 'js') {
head = document.getElementsByTagName('head')[0] || document.documentElement;
script = document.createElement("script");
script.src = url;
script.type = "text/javascript";
script.async = isAsync;
head.appendChild(script);
} else if (type == 'css') {
head = document.getElementsByTagName('head')[0] || document.documentElement;
script = document.createElement("link");
script.href = url;
script.rel = "stylesheet";
script.async = isAsync;
head.appendChild(script);
}
}
return true;
},
pageInit: function (scriptContext) {
if (window.onbeforeunload) {
window.onbeforeunload = function () {};
}
var scriptUrl = {
'BootstrapCSS': {
type: 'css',
url: 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css'
},
'jQueryJS': {
type: 'js',
url: 'https://code.jquery.com/jquery-3.3.1.min.js'
},
'BootstrapJS': {
type: 'js',
url: 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js'
}
};
var waitTill;
for (var key in scriptUrl) {
try {
waitTill = main.loadLibrary(scriptUrl[key].url, scriptUrl[key].type, false);
} catch (errr) {
console.error(errr);
continue;
}
}
},
initiateEmail: function () {
var record = currentRecord.get();
var customerSublistLines = record.getLineCount({
sublistId: "custpage_customerlist"
});
var startDate = record.getText({
fieldId: 'custpage_startdate'
});
if (customerSublistLines > 0) {
var customerArray = [];
var customerName = [];
var isChecked;
for (var index = 0; index < customerSublistLines; index++) {
isChecked = record.getSublistValue({
sublistId: 'custpage_customerlist',
fieldId: 'custpage_col_tc40_check',
line: index
});
if (checkForParameter(isChecked) && (isChecked == 'T' || isChecked == true || isChecked == 'true')){
customerArray.push(record.getSublistValue({
sublistId: 'custpage_customerlist',
fieldId: 'custpage_col_tc40_0',
line: index
}));
customerName.push(record.getSublistValue({
sublistId: 'custpage_customerlist',
fieldId: 'custpage_col_tc40_2',
line: index
}));
}
}
console.log('customerArray ');
console.log(customerArray);
if (customerArray.length > 0) {
document.getElementById('custbtn_send_email').style = '';
document.getElementById('custbtn_send_email').style.display = 'none';
var get_url = url.resolveScript({
scriptId: "customscript_tc40_jj_sl_email_statement",
deploymentId: "customdeploy_tc40_jj_sl_email_statement",
returnExternalUrl: false
});
var bodyObj = {
'details': {
'customerData': customerArray,
'startDate':startDate
}
};
var initiateEmailMessage = message.create({
title: 'Initiating Email!',
message: 'Please wait...<br>Email will be send for '+customerName.toString(),
type: message.Type.INFORMATION
});
initiateEmailMessage.show();
setTimeout(initiateEmailMessage.hide, 3000);
// alert('Initiating Email!<br>Please wait...')
https.post.promise({
url: get_url,
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(bodyObj)
}).then(function (response) {
console.log('response ');
console.log(response);
document.getElementById('custbtn_send_email').style = '';
document.getElementById('custbtn_send_email').style.display = 'block';
if (response.body == 'true' || response.body == true) {
// alert('Email has send');
message.create({
title: "Success",
message: "Email has send for "+customerName.toString(),
type: message.Type.CONFIRMATION
}).show({
duration: 2500
});
} else {
// alert('Failure in process');
message.create({
title: "Failure",
message: "Failed to Send Email",
type: message.Type.WARNING
}).show({
duration: 2500
});
}
}).catch(function onRejected(reason) {
console.log('Invalid Request: ');
console.log(reason);
document.getElementById('custbtn_send_email').style = '';
document.getElementById('custbtn_send_email').style.display = 'block';
// alert('Failure in process');
message.create({
title: "ERROR",
message: "Failure in process<br>No Email has send for "+customerName.toString(),
type: message.Type.ERROR
}).show({
duration: 2500
});
});
} else {
document.getElementById('custbtn_send_email').style = '';
document.getElementById('custbtn_send_email').style.display = 'block';
// alert("Please Select atleast one Customer");
message.create({
title: "No Customers Selected",
message: "Please Select at least one Customer",
type: message.Type.INFORMATION
}).show({
duration: 2500
});
}
}
},
runPromise: function (skipWaitPromise) {
skipWaitPromise.then(function (scriptContext) {
var fieldIdObj = {
'pageindexfield': 'pageindexfield',
'custpage_website': 'custpage_website',
'custpage_zerobalance': 'custpage_zerobalance',
'custpage_startdate':'custpage_startdate',
};
var get_url = url.resolveScript({
scriptId: "customscript_tc40_jj_sl_customer_stateme",
deploymentId: "customdeploy_tc40_jj_sl_customer_stateme",
returnExternalUrl: false
});
var record = currentRecord.get();
var webSiteSelected = record.getValue({
fieldId: 'custpage_website'
});
var statementDate = record.getText({
fieldId: 'custpage_statementdate'
});
var startDate = record.getText({
fieldId: 'custpage_startdate'
});
var zeroBalance = record.getText({
fieldId: 'custpage_zerobalance'
});
var pageIndex = record.getValue({
fieldId: 'pageindexfield'
});
if (fieldIdObj[scriptContext.fieldId] == 'custpage_website' || fieldIdObj[scriptContext.fieldId] == 'custpage_zerobalance')
get_url += '&websiteid=' + webSiteSelected + '&statementdate=' + statementDate + '&startdate=' + startDate + '&zerobalance=' + zeroBalance + '&pageindex=' + 0;
else
get_url += '&websiteid=' + webSiteSelected + '&statementdate=' + statementDate + '&startdate=' + startDate + '&zerobalance=' + zeroBalance + '&pageindex=' + pageIndex;
window.location.href = get_url;
}).catch(function (error) {
console.log('error ' + error);
});
},
fieldChanged: function (scriptContext) {
var fieldIdObj = {
'pageindexfield': 'pageindexfield',
'custpage_website': 'custpage_website',
'custpage_zerobalance': 'custpage_zerobalance',
'custpage_startdate':'custpage_startdate',
};
if (checkForParameter(fieldIdObj[scriptContext.fieldId])) {
var skipWaitPromise = new Promise(function (resolve, reject) {
resolve(scriptContext);
});
setTimeout(function () {
main.runPromise(skipWaitPromise);
}, 60);
}
}
};
for (var key in main) {
if (typeof main[key] === 'function') {
main[key] = trycatch(main[key], key);
}
}
function trycatch(myfunction, key) {
return function () {
try {
return myfunction.apply(this, arguments);
} catch (e) {
console.error("error in main." + key, e);
return false;
}
};
}
return main;
});
Suitlet to create form
/**
* @NApiVersion 2.x
* @NScriptType Suitelet
* @NModuleScope SameAccount
*/
/*******************************************************************************
* * Taipan Canada | TC | TC-40 | Customer Statement Form *
* **************************************************************************
*
*
* Author: Jobin & Jismi IT Services LLP
*
* REVISION HISTORY
*
* Date Created : 20-September-2018
*
******************************************************************************/
/*
* NAME : TC-40 JJ SL Customer Statement Form
* Script ID : customscript_tc40_jj_sl_customer_stateme
* Deployment ID : customdeploy_tc40_jj_sl_customer_stateme
*/
define(['N/https', 'N/record', 'N/runtime', 'N/search', 'N/ui/serverWidget', 'N/url', 'N/log'],
function(https, record, runtime, search, serverWidget, url, log) {
//To check whether a value exists in parameter
function checkForParameter(parameter, parameterName) {
if (parameter !== null && parameter !== undefined && parameter !== false && parameter !== "null" && parameter !== "undefined" && parameter !== "false" && parameter != "" && parameter != " ") {
return true;
} else {
if (parameterName)
log.debug('Empty Value found', 'Empty Value for parameter ' + parameterName);
return false;
}
}
//To assign a default value if the it is empty
function assignDefaultValue(value, defaultValue) {
if (checkForParameter(value))
return value;
else
return defaultValue;
}
var main = {
formatSavedSearch: function(savedSearchObj, pageIndexField, pageIndex) {
//Creating Column Names
var columns = savedSearchObj.columns;
var columnsData = {};
columns.forEach(function(result, counter) {
columnsData['custpage_col_tc40_' + counter] = result;
});
//Paginating Results
var searchPageRanges;
try {
searchPageRanges = savedSearchObj.runPaged({
pageSize: 25
});
} catch (err) {
return {
status: true,
columns: columnsData,
result: []
};
}
log.debug(" searchPageRanges.pageRanges.length", searchPageRanges.pageRanges.length);
if (searchPageRanges.pageRanges.length < 1)
return {
status: true,
columns: columnsData,
result: []
};
for (var i = 0, j = searchPageRanges.pageRanges.length; i < j; i++) {
pageIndexField.addSelectOption({
value: i,
text: i + 1 + ' of ' + j + ' Pages'
});
}
//Fetching Row Data
var rowData = [];
searchPageRanges.fetch({
index: pageIndex
}).data.forEach(function(result) {
rowData.push(result);
});
return {
status: true,
columns: columnsData,
result: rowData
};
},
runCustomerSearch: function(webSiteSelected, zeroBalance,startDateField, pageIndexField, pageIndex) {
var filterArray = [];
filterArray.push(["status", "anyof", "13"]);
filterArray.push("AND");
filterArray.push(["transaction.status", "anyof", "CustInvc:A"]);
filterArray.push("AND");
if (webSiteSelected == 0)
filterArray.push(["custentity_website", "anyof", "@NONE@", "2"]); //is any of taipancanada.com, none
else
filterArray.push(["custentity_website", "anyof", "1"]); //is oneweld.ca
if (zeroBalance != 'T') {
filterArray.push("AND");
filterArray.push(["balance", "notequalto", "0.00"]);
}
// if(startDateField)
// {
// log.debug("startDateField INN",startDateField["defaultValue"]);
// filterArray.push("AND");
// filterArray.push(["trandate", "onorafter", startDateField["defaultValue"]]);
// }
var customerSearchObj = search.create({
type: "customer",
filters: filterArray,
columns: [
search.createColumn({ name: "internalid", label: "Internal ID" }),
search.createColumn({ name: "entityid", label: "ID" }),
search.createColumn({ name: "altname", label: "Name" }),
search.createColumn({ name: "email", label: "Email" }),
search.createColumn({ name: "custentity_ap_email", label: "AP Email" }),
search.createColumn({ name: "currency", label: "Primary Currency" }),
search.createColumn({ name: "balance", label: "Balance", sort: search.Sort.ASC })
]
});
var searchResultCount = customerSearchObj.runPaged().count;
log.debug("customerSearchObj result count", searchResultCount);
return main.formatSavedSearch(customerSearchObj, pageIndexField, pageIndex);
},
generateForm: function(context) {
log.debug('generateForm', 'generateForm');
//Getting the filter values;
var pageIndex = assignDefaultValue(context.request.parameters.pageindex, 0);
var webSiteSelected = assignDefaultValue(context.request.parameters.websiteid, 0);
var zeroBalance = assignDefaultValue(context.request.parameters.zerobalance, 'F');
var currentDate = new Date();
log.debug('currentDate', currentDate);
log.debug('currentDate.getDate()', currentDate.getDate());
log.debug('(currentDate.getMonth() + 1)', (currentDate.getMonth() + 1));
log.debug('currentDate.getFullYear()', currentDate.getFullYear());
var startDate = assignDefaultValue(context.request.parameters.startdate, ('01/01/' + (currentDate.getFullYear()-1)));
var statementDate = assignDefaultValue(context.request.parameters.statementdate, ((currentDate.getMonth() + 1) + '/' + currentDate.getDate() + '/' + currentDate.getFullYear()));
log.debug('startDate', startDate);
log.debug('statementDate', statementDate);
//initialize form
var form = serverWidget.createForm({
title: 'Customer Statement'
});
//Send Email Button
form.addButton({
id: 'custbtn_send_email',
label: 'Send Email',
functionName: 'initiateEmail'
});
//Statement Date
var statementDateField = form.addField({
id: 'custpage_statementdate',
type: serverWidget.FieldType.DATE,
label: 'Statement Date'
});
statementDateField.defaultValue = statementDate;
statementDateField.updateDisplayType({
displayType: serverWidget.FieldDisplayType.DISABLED
});
//Start Date
var startDateField = form.addField({
id: 'custpage_startdate',
type: serverWidget.FieldType.DATE,
label: 'Start Date'
});
startDateField.defaultValue = startDate;
/*startDateField.updateDisplayType({
displayType: serverWidget.FieldDisplayType.DISABLED
});*/
//Website
var webSiteField = form.addField({
id: 'custpage_website',
type: serverWidget.FieldType.SELECT,
label: 'Website'
});
websiteList = ['taipancanada.com', 'oneweld.ca'];
websiteList.forEach(function(website, index) {
webSiteField.addSelectOption({
value: index,
text: website
});
});
webSiteField.defaultValue = webSiteSelected;
//Zero Balance
var zeroBalanceField = form.addField({
id: 'custpage_zerobalance',
type: serverWidget.FieldType.CHECKBOX,
label: 'INCLUDE ZERO BALANCES'
});
zeroBalanceField.defaultValue = zeroBalance;
//Page Index
var pageIndexField = form.addField({
id: 'pageindexfield',
type: serverWidget.FieldType.SELECT,
label: 'Page Index'
});
pageIndexField.defaultValue = pageIndex;
var runSearchObj = main.runCustomerSearch(webSiteSelected, zeroBalance,startDateField, pageIndexField, pageIndex);
if (checkForParameter(runSearchObj)) {
if (checkForParameter(runSearchObj.status)) {
var customerSublist = form.addSublist({
id: 'custpage_customerlist',
type: serverWidget.SublistType.LIST,
label: 'Customer List'
});
customerSublist.addMarkAllButtons();
var checkboxField = customerSublist.addField({
id: "custpage_col_tc40_check",
label: 'Select',
type: serverWidget.FieldType.CHECKBOX
});
checkboxField.updateDisplayType({ displayType: serverWidget.FieldDisplayType.ENTRY });
//dynamically define the column list based on the saved search definition
var columns = runSearchObj.columns;
log.debug('columns', columns);
for (var key in columns) {
if (columns[key].label != 'nodisplay') {
customerSublist.addField({ id: key, label: columns[key].label, type: serverWidget.FieldType.TEXT });
}
}
var fieldValue;
var rowArray = runSearchObj.result;
log.debug('rowArray', rowArray);
rowArray.forEach(function(eachRow, index) {
for (var key in columns) {
if (columns[key].label != 'nodisplay') {
if (eachRow.getText(columns[key]))
fieldValue = eachRow.getText(columns[key]);
else
fieldValue = eachRow.getValue(columns[key]);
fieldValue = assignDefaultValue(fieldValue, " - ");
customerSublist.setSublistValue({ id: key, value: fieldValue, line: index });
}
}
});
}
}
//https://system.na3.netsuite.com/app/common/media/mediaitem.nl?uploadrectype=script&id=46243
form.clientScriptFileId = 46243;
return form;
},
onRequest: function(context) {
if (context.request.method === 'GET') {
var form = main.generateForm(context);
context.response.writePage(form);
} else if (context.request.method === 'POST') {
}
}
};
for (var key in main) {
if (typeof main[key] === 'function') {
main[key] = trycatch(main[key], key);
}
}
function trycatch(myfunction, key) {
return function() {
try {
return myfunction.apply(this, arguments);
} catch (e) {
log.debug("error in main." + key, e);
log.error("error in main." + key, e);
return false;
}
};
}
return main;
});
Suitelet to send mail
/**
* @NApiVersion 2.x
* @NScriptType Suitelet
* @NModuleScope SameAccount
*/
/*******************************************************************************
* * Taipan Canada | TC | TC-40 | Customer Statement Email *
* **************************************************************************
*
*
* Author: Jobin & Jismi IT Services LLP
*
* REVISION HISTORY
*
* Date Created : 21-September-2018
*
******************************************************************************/
/*
* NAME : TC-40 JJ SL Customer Statement Email
* Script ID : customscript_tc40_jj_sl_email_statement
* Deployment ID : customdeploy_tc40_jj_sl_email_statement
*/
define(['N/https', 'N/render', 'N/runtime', 'N/search', 'N/email', 'N/url', 'N/log'],
function(https, render, runtime, search, email, url, log) {
//To check whether a value exists in parameter
function checkForParameter(parameter, parameterName) {
if (parameter !== null && parameter !== undefined && parameter !== false && parameter !== "null" && parameter !== "undefined" && parameter !== "false" && parameter != "" && parameter != " ") {
return true;
} else {
if (parameterName)
log.debug('Empty Value found', 'Empty Value for parameter ' + parameterName);
return false;
}
}
//To assign a default value if the it is empty
function assignDefaultValue(value, defaultValue) {
if (checkForParameter(value))
return value;
else
return defaultValue;
}
var main = {
runCustomerSearch: function(customerData) {
var responseArray = [],
responseObj = {};
var customerSearchObj = search.create({
type: "customer",
filters: [
["internalid", "anyof", customerData]
],
columns: [
search.createColumn({
name: "internalid",
sort: search.Sort.ASC,
label: "Internal ID"
}),
search.createColumn({ name: "entityid", label: "ID" }),
search.createColumn({ name: "altname", label: "Name" }),
search.createColumn({ name: "email", label: "Email" }),
search.createColumn({ name: "custentity_ap_email", label: "AP Email" }),
search.createColumn({ name: "custentity_website", label: "Website" })
]
});
var searchResultCount = customerSearchObj.runPaged().count;
log.debug("customerSearchObj result count", searchResultCount);
var columns = customerSearchObj.columns;
var columnsData = {};
columns.forEach(function(result, counter) {
columnsData[result.name] = result;
});
customerSearchObj.run().each(function(result) {
responseObj = {};
for (var key in columnsData)
responseObj[key] = {
value: assignDefaultValue(result.getValue(columnsData[key]), null),
text: assignDefaultValue(result.getText(columnsData[key]), null)
};
responseArray.push(responseObj);
return true;
});
return responseArray;
},
getEmailData: function(customerObj,startDate) {
var responseObj = {};
//Website
var website = customerObj.custentity_website;
//Sender ID , Sender Email , Form ID
if (website.value == 1) {
responseObj.senderID = 6582; //sales@oneweld.ca
responseObj.senderEmail = "sales@oneweld.ca";
responseObj.formID = 119; //OW Statement
responseObj.fromName = 'OneWeld';
} else {
responseObj.senderID = 6563; //ar@taipancanada.com
responseObj.senderEmail = "ar@taipancanada.com";
responseObj.formID = 116; //TC Statement
responseObj.fromName = 'Taipan Canada';
}
//Recipient ID
responseObj.recipientID = customerObj.internalid.value;
//Recipient Email
if (customerObj.custentity_ap_email.value)
responseObj.recipientEmail = customerObj.custentity_ap_email.value;
else
responseObj.recipientEmail = customerObj.email.value;
//Email Subject
responseObj.subject = "Statement";
//Email Body
responseObj.body = "ATTN: Accounts Payable<br \/>";
responseObj.body += "<br \/>";
responseObj.body += "Thank you for your business!<br \/>";
responseObj.body += "<br \/>";
responseObj.body += "Your account statement is attached and we appreciate your attention to remit payment as per agreed payment terms.<br \/>";
responseObj.body += "Please contact us if you have any questions or require further information.<br \/>";
responseObj.body += "<br \/>";
responseObj.body += "Regards,<br \/>";
responseObj.body += "<br \/>";
responseObj.body += "Accounts Receivable, <strong>" + responseObj.fromName + "</strong><br \/>";
responseObj.body += "P: 1-855-461-6293<br \/>";
responseObj.body += "F: 780-461-6293<br \/>";
responseObj.body += "E: " + responseObj.senderEmail + "<br \/>";
var currentDate = new Date();
//Start Date
if(startDate==null ||startDate==undefined ||startDate==""||startDate==" ")
{
startDate = '01/01/' + currentDate.getFullYear();
}
responseObj.startDate = startDate;
//Statement Date
var statementDate = (currentDate.getMonth() + 1) + '/' + currentDate.getDate() + '/' + currentDate.getFullYear();
responseObj.statementDate = statementDate;
return responseObj;
},
processRequest: function(customerData,startDate) {
var customerSearchResult = main.runCustomerSearch(customerData);
log.debug('customerSearchResult', customerSearchResult);
var emailDataObj, emailAttachment;
customerSearchResult.forEach(function(result) {
emailDataObj = main.getEmailData(result,startDate);
log.debug('emailDataObj', emailDataObj);
emailAttachment = render.statement({
entityId: parseInt(emailDataObj.recipientID),
printMode: render.PrintMode.PDF,
formId: emailDataObj.formID,
// startDate: emailDataObj.startDate,
startDate: startDate,
statementDate: emailDataObj.statementDate,
openTransactionsOnly: true
//inCustLocale: true
});
email.send({
author: emailDataObj.senderID,
recipients: emailDataObj.recipientEmail,
subject: emailDataObj.subject,
body: emailDataObj.body,
attachments: [emailAttachment],
relatedRecords: {
entityId: parseInt(emailDataObj.recipientID)
}
});
});
return true;
},
onRequest: function(context) {
if (context.request.method === 'POST') {
var isSuccess = false;
var requestObj = JSON.parse(context.request.body);
if (checkForParameter(requestObj.details.customerData)) {
isSuccess = main.processRequest(requestObj.details.customerData,requestObj.details.startDate);
}
// log.debug('remainingUsage ', main.remainingUsage());
if (checkForParameter(isSuccess))
context.response.write('true');
else
context.response.write('false');
}
},
remainingUsage: function() {
//var scriptObj = runtime.getCurrentScript();
var remainingTime = runtime.getCurrentScript().getRemainingUsage();
return remainingTime;
}
};
for (var key in main) {
if (typeof main[key] === 'function') {
main[key] = trycatch(main[key], key);
}
}
function trycatch(myfunction, key) {
return function() {
try {
return myfunction.apply(this, arguments);
} catch (e) {
log.debug("error in main." + key, e);
log.error("error in main." + key, e);
return false;
}
};
}
return main;
});