The suitelet is added below
/**
* @NApiVersion 2.x
* @NScriptType Suitelet
*/
define(['N/search', 'N/record', 'N/file', "N/render"],
function (search, record, file, render) {
var ITEM_OBJ = {};
var diffDays;
var main = {
onRequest: function (context) {
try {
if (context.request.method == 'GET') {
// var filter = context.request.parameters.filter;
var mode = context.request.parameters.mode;
var fromDate1 = context.request.parameters.fromDate;
var toDate1 = context.request.parameters.toDate;
var fromDate = decodeURIComponent(fromDate1);
var toDate = decodeURIComponent(toDate1);
fromDate = fromDate.toString();
fromDate = fromDate.split("-");
fromDate = fromDate[1] + "/" + fromDate[2] + "/" + fromDate[0];
toDate = toDate.toString();
toDate = toDate.split("-");
toDate = toDate[1] + "/" + toDate[2] + "/" + toDate[0];
var dateFirst = new Date(fromDate);
var dateSecond = new Date(toDate);
ITEM_OBJ.dateFirst = dateFirst;
ITEM_OBJ.dateSecond = dateSecond;
// time difference
var timeDiff = Math.abs(dateSecond.getTime() - dateFirst.getTime());
// days difference
diffDays = Math.ceil(timeDiff / (1000 * 3600 * 24));
if (mode == 'CHANGE') {
var content = main.fetch_Backorderdetails(fromDate, toDate, mode);
} else {
var content = main.fetch_Backorderdetails(fromDate, toDate, mode);
}
var datahtml = file.load({ id: 962146 }).getContents();
/* log.debug("datahtml", datahtml);*/
var renderer = render.create();
renderer.templateContent = datahtml;
renderer.addCustomDataSource({
format: render.DataSource.OBJECT,
alias: "content",
data: content
});
context.response.write(renderer.renderAsString());
}
} catch (er) {
log.debug('err@onRequest', er.message);
}
},
/**
* @description The function is used for fetch the backordered item details
* @param {object} fromDate-The date is the from date from filter used in the page
* @param {object} toDate-The date is the to date from filter used in the page
* @param {object} mode-The date is the to mode from filter used in the page
*/
fetch_Backorderdetails: function (fromDate, toDate, mode) {
try {
var backorderedItem_array = [];
var filterArr = [];
var columnSearch;
filterArr.push(["type", "anyof", "SalesOrd"]);
filterArr.push("AND");
filterArr.push(["item.quantitybackordered", "greaterthan", "0"]);
var bckorderedSearchObj;
if (!mode) {
filterArr.push("AND");
filterArr.push(["trandate", "within", "today"]);
columnSearch = [
search.createColumn({
name: "itemid",
join: "item",
summary: "GROUP",
label: "Name"
}),
search.createColumn({
name: "salesdescription",
join: "item",
summary: "GROUP",
label: "Description"
}),
search.createColumn({
name: "quantitybackordered",
join: "item",
summary: "GROUP",
label: "Back Ordered"
}),
search.createColumn({
name: "custitem_jj_itemquick_ship",
join: "item",
summary: "GROUP",
label: "Quick Ship"
}),
search.createColumn({
name: "internalid",
summary: "GROUP",
label: "Internal ID",
join: "item"
}),
search.createColumn({
name: "quantityonorder",
join: "item",
summary: "GROUP",
label: "On Order"
}),
search.createColumn({
name: "trandate",
summary: "GROUP",
sort: search.Sort.ASC,
label: "Date"
})
]
} else if ((mode != null) && (mode != undefined) && (mode != "")) {
filterArr.push("AND");
filterArr.push(["trandate", "within", fromDate, toDate]);
columnSearch = [
search.createColumn({
name: "itemid",
join: "item",
summary: "GROUP",
label: "Name"
}),
search.createColumn({
name: "salesdescription",
join: "item",
summary: "GROUP",
label: "Description"
}),
search.createColumn({
name: "quantitybackordered",
join: "item",
summary: "GROUP",
label: "Back Ordered"
}),
search.createColumn({
name: "custitem_jj_itemquick_ship",
join: "item",
summary: "GROUP",
label: "Quick Ship"
}),
search.createColumn({
name: "internalid",
summary: "GROUP",
label: "Internal ID",
join: "item"
}),
search.createColumn({
name: "quantityonorder",
join: "item",
summary: "GROUP",
label: "On Order"
}),
search.createColumn({
name: "trandate",
summary: "GROUP",
sort: search.Sort.ASC,
label: "Date"
})
]
}
bckorderedSearchObj = search.create({
type: "salesorder",
filters: filterArr,
columns: columnSearch
});
var searchResultCount = bckorderedSearchObj.runPaged().count;
if (searchResultCount > 0) {
bckorderedSearchObj.run().each(function (result) {
var backordered_obj = {};
backordered_obj.internalid = result.getValue({ name: "internalid", join: "item", summary: "GROUP" });
backordered_obj.Item = main.ItemName(result.getValue({ name: "itemid", join: "item", summary: "GROUP" }));
backordered_obj.Description = result.getValue({ name: "salesdescription", join: "item", summary: "GROUP" });
backordered_obj.BackOrder = result.getValue({ name: "quantitybackordered", join: "item", summary: "GROUP" });
backordered_obj.OnOrder = result.getValue({ name: "quantityonorder", join: "item", summary: "GROUP" });
backordered_obj.PurchaseFirstDate = main.DateDiffrents(result.getValue({ name: "trandate", summary: "GROUP" }));
backordered_obj.QuickShip = main.capitalizeFirstLetter(result.getValue({ name: "custitem_jj_itemquick_ship", join: "item", summary: "GROUP" }));
backordered_obj.Purchaselist = []
backorderedItem_array.push(backordered_obj);
return true;
});
var removeDuplicate=main.combineArrayObjectsByInternalId(backorderedItem_array)
var purchaseorderlist = main.combinedObject(removeDuplicate)
if (purchaseorderlist.internalid) {
var list = main.removeDuplicateValues(purchaseorderlist.internalid)
var purchaselist = main.fetchPurchaseOrder(list,mode,fromDate, toDate);
var Itemlist = main.CombineItem(removeDuplicate, purchaselist)
Itemlist.forEach(function (result, i) {
if (result.Purchaselist) {
var combinePurchaselist = main.combinedObject(result.Purchaselist)
combinePurchaselist.Date = main.removeDuplicateValues(combinePurchaselist.Date)
combinePurchaselist.vendor = main.removeDuplicateValues(combinePurchaselist.vendor)
Itemlist[i]['purchaseObject'] = combinePurchaselist
}
return true;
});
log.debug('purchaselist', Itemlist)
}
return { Item: Itemlist };
}
log.debug('filterArr_phone', filterArr)
} catch (error) {
log.debug('error', error)
}
},
/**
* @description The function is used for getting the actual item name .
* @param {object} name-The item full name from netsuite
*/
ItemName: function (name) {
try {
if (name != undefined && name != null) {
var namevalue = name.split(':')
if (namevalue.length > 1) {
var itemname = namevalue[1];
return itemname
}
else {
var itemname = namevalue[0];
return itemname
}
}
} catch (error) {
log.debug('err@ItemName', er.message);
}
},
/**
* @description The function is used for getting the diffrents of day with today date.
* @param {object} name-The date what to check the diffrents
*/
DateDiffrents: function (date) {
try {
if (date != undefined && date != null) {
var datearray = date.split('/')
if (datearray.length > 1) {
var toDate = datearray[2] + "/" + datearray[0] + "/" + datearray[1];
var today = new Date();
var olddate=new Date(toDate);
var timeDifference =Math.abs(today.getTime() - olddate.getTime()) ;
var daysDifference = Math.ceil(timeDifference / (1000 * 60 * 60 * 24));
return daysDifference +' days '
}
}
} catch (error) {
log.debug('err@errorDateDiffrents', error.message);
}
},
/**
* @description The function is used for rearrange the date from netsuite as per the client format
* @param {object} date-The date of the item and purchase order
*/
DateArrange: function (date) {
try {
if (date != undefined && date != null) {
var datearray = date.split('/')
if (datearray.length > 1) {
var toDate = datearray[1] + "/" + datearray[0] + "/" + datearray[2];
return toDate
}
}
else{
return 'Not Available'
}
} catch (error) {
log.debug('err@ItemName', er.message);
}
},
/**
* @description The function is used for fetch the purchase order list of item.
* @param {object} fromDate-The date is the from date from filter used in the page
* @param {object} toDate-The date is the to date from filter used in the page
* @param {object} mode-The date is the to mode from filter used in the page
*/
fetchPurchaseOrder: function (internalids,mode,fromDate, toDate) {
try {
var purchaseorder_array = [];
var filterArr = [];
filterArr.push(["type", "anyof", "PurchOrd"]);
filterArr.push("AND");
filterArr.push(["item.internalid", "anyof", internalids]);
if (!mode) {
filterArr.push("AND");
filterArr.push(["trandate", "within", "today"]);
}
else if ((mode != null) && (mode != undefined) && (mode != "")) {
filterArr.push("AND");
filterArr.push(["trandate", "within", fromDate, toDate]);;
}
var columnslist = [
search.createColumn({
name: "duedate",
summary: "GROUP",
label: "Due Date/Receive By"
}),
search.createColumn({
name: "tranid",
summary: "GROUP",
sort: search.Sort.ASC,
label: "Document Number"
}),
search.createColumn({
name: "altname",
join: "vendor",
summary: "GROUP",
label: "Name"
}),
search.createColumn({
name: "internalid",
join: "item",
summary: "GROUP",
label: "Internal ID"
})
]
purchaseorderSearchObj = search.create({
type: "purchaseorder",
filters: filterArr,
columns: columnslist
});
var resultCount = purchaseorderSearchObj.runPaged({
pageSize: 1000
});
for (var i = 0; i < resultCount.pageRanges.length; i++) {
var currentPage = resultCount.fetch(i);
currentPage.data.forEach(function (result) {
var purchaseorder_obj = {}
var date=result.getValue({ name: "duedate", summary: "GROUP", label: "Due Date/Receive By" })
if(date===''){
purchaseorder_obj.Date ='Not Available'
}else{
purchaseorder_obj.Date = date;
}
purchaseorder_obj.ponumber = result.getValue({ name: "tranid", summary: "GROUP", sort: search.Sort.ASC, label: "Document Number" });
purchaseorder_obj.vendor = result.getValue({ name: "altname", join: "vendor", summary: "GROUP", label: "Name" });
purchaseorder_obj.internalid = result.getValue({ name: "internalid", join: "item", summary: "GROUP", label: "Internal ID" });
purchaseorder_array.push(purchaseorder_obj)
return true;
});
};
return purchaseorder_array;
} catch (error) {
}
},
/**
* @description The function is used for combine the array to single object
* @param {object} array-The array list from the item and purchase order
*/
combinedObject: function (array) {
try {
var combinedObject = {};
array.forEach(function (obj) {
for (var key in obj) {
if (combinedObject[key]) {
combinedObject[key] += ", " + obj[key];
} else {
combinedObject[key] = obj[key];
}
}
});
return combinedObject;
} catch (error) {
}
},
/**
* @description The function is used for remove the duplicate value from the object value.
* @param {object} inputString-The inputString is the object key value
*/
removeDuplicateValues: function (inputString) {
try {
var values = inputString.split(','); // Split the string into an array
var uniqueValues = [];
for (var i = 0; i < values.length; i++) {
var value = values[i].trim(); // Remove leading/trailing whitespace
if (value && value != undefined && value != 'undefined' && uniqueValues.indexOf(value) === -1) {
uniqueValues.push(value);
}
}
// Join the unique values with commas to create the result string
var resultString = uniqueValues.join(', ');
return resultString;
} catch (error) {
}
}
/**
* @description The function is used for combine the purchase order and backordered list.
* @param {object} array1-The array1 is an array of the back order item.
* @param {object} array2-The array2 is an array of the purchase order item.
*/
, CombineItem: function (array1, array2) {
try {
var mergedArray = [];
// log.debug('array1', array1)
// log.debug('array2', array2)
// Iterate through the first array
for (var i = 0; i < array1.length; i++) {
var item1 = array1[i];
// Iterate through the second array
for (var j = 0; j < array2.length; j++) {
var item2 = array2[j];
// Compare internal IDs
if (item1.internalid === item2.internalid) {
// Push the matching items to the merged array
array1[i].Purchaselist.push(array2[j])
}
}
}
return array1;
} catch (error) {
}
},
/**
* @description The function is used for combineArrayObjectsByInternalId the string.
* @param {object} arr-array.
*/
combineArrayObjectsByInternalId: function (arr) {
var seenInternalids = {};
var uniqueArr = [];
for (var i = 0; i < arr.length; i++) {
var obj = arr[i];
var internalid = obj.internalid;
if (!seenInternalids[internalid]) {
// This is the first occurrence of the internalId
seenInternalids[internalid] = true;
uniqueArr.push(obj);
}
}
return uniqueArr;
}
/**
* @description The function is used for capitalizeFirstLetter the string.
* @param {object} str-string.
*/
,
capitalizeFirstLetter:function(str) {
if (typeof str === 'string' ) {
// Return the original input if it's not a string
return str.charAt(0).toUpperCase() + str.slice(1);
}
else if(typeof str === 'boolean'){
return str.toString().charAt(0).toUpperCase() + str.toString().slice(1);
}
return str;
}
}
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("e in " + key, e);
}
}
};
return main;
});
The HTML page is added below
<!DOCTYPE html>
<html>
<head>
<title>Item Back Order Report</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
</head>
<body class="ItemBackOrderReport_data" onload="url_load()">
<!-- onload="url_load()" -->
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<div class="ItemBackOrderReport_heading">Item Back Order Report</div>
<div class="date_field_align" margin-left="1.2%">
<div style="display: inline-block;">
DATE: 
<input type="text" id="message">
</div>
<div style="display: inline-block;margin-left: 50px;">
FROM : 
<input type="date" id="fromdate" onchange="handler('from')">
</div>
<div style="display: inline-block;margin-left: 50px;">
TO : 
<input type="date" id="todate" onchange="handler('to')">
</div>
</div>
<div>
<div class="ItemBackOrderReport_data_nodata" id="nodata">
<!-- No Activities By Reps Available -->
</div>
</div>
<div class="ItemBackOrderReport_data_main">
<table>
<tr class="ItemBackOrderReport_data_main_content">
<td class="Item_Sku_Part_label ItemBackOrderReport_data_label">ITEM/SKU/PART NUMBER</td>
<td class="Description_label ItemBackOrderReport_data_label">DESCRIPTION</td>
<td class="Back_Oder_Qty_label ItemBackOrderReport_data_label">BACK ORDERED QTY</td>
<td class="On_Order_Qty_label ItemBackOrderReport_data_label">ON ORDER QTY</td>
<td class="On_Purchase_Order_label ItemBackOrderReport_data_label">ON PURCHASE ORDER #</td>
<td class="Purchase_Order_Recive_label ItemBackOrderReport_data_label">PURCHASE ORDER RECEIVE BY DATE</td>
<td class="Vendor_label ItemBackOrderReport_data_label">VENDOR</td>
<td class="Quick_Ship_Available_label ItemBackOrderReport_data_label">QUICK SHIP Available?</td>
<td class="Of_Days_Back_Order_label ItemBackOrderReport_data_label"># OF DAYS BACKORDERED</td>
</tr>
<#list content.Item as content_line>
<tr class="ItemBackOrderReport_data_main_content_line">
<td class="Item_Sku_Part_line">${content_line.Item}</td>
<td class="Description_line">${content_line.Description}</td>
<td class="Back_Oder_Qty_line">${content_line.BackOrder}</td>
<td class="On_Order_Qty_line">${content_line.OnOrder}</td>
<td class="On_Purchase_Order_line">${content_line.purchaseObject.ponumber}</td>
<td class="Purchase_Order_Recive_line">${content_line.purchaseObject.Date}</td>
<td class="Vendor_line">${content_line.purchaseObject.vendor}</td>
<td class="Quick_Ship_Available_line">${content_line.QuickShip}</td>
<td class="Of_Days_Back_Order_line">${content_line.PurchaseFirstDate}</td>
</tr>
</#list>
</table>
</div>
<br />
</body>
</html>
<script type="text/javascript">
function getUrlVars() {
var vars = {};
var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function (m, key, value) {
vars[key] = value;
});
return vars;
}
function url_load() {
var current_url = window.location.href;
setTimeout("location.href = '" + current_url + "';", 30000);
document.getElementById("fromdate").value = getUrlVars().fromDate;
document.getElementById("todate").value = getUrlVars().toDate;
var messageText = getUrlVars().diff;
if (messageText == 0) {
document.getElementById("message").value = 'TODAY';
} else if (messageText == 7) {
document.getElementById("message").value = 'WEEK';
} else if (messageText == 30) {
document.getElementById("message").value = 'MONTH';
} else if (messageText != 30 || diffDays != 7 || diffDays != 0) {
document.getElementById("message").value = 'WITH IN DATE FILTER';
}
}
function handler(type) {
fromDate = document.getElementById("fromdate").value
toDate = document.getElementById("todate").value
new Date(fromDate);
new Date(toDate);
var url = "https://3889163.extforms.netsuite.com/app/site/hosting/scriptlet.nl?script=364&deploy=1&compid=3889163&h=ba145a04d55bfea390c1";
var dateFirst = new Date(fromDate);
var dateSecond = new Date(toDate);
// time difference
var timeDiff = Math.abs(dateSecond.getTime() - dateFirst.getTime());
// days difference
var diffDays = Math.ceil(timeDiff / (1000 * 3600 * 24));
if ((fromDate != "") && (toDate != "") && (dateFirst <= dateSecond)) {
if (url.indexOf('?') > -1) {
url += '&mode=CHANGE' + '&fromDate=' + encodeURIComponent(fromDate) + '&toDate=' + encodeURIComponent(toDate) + '&diff=' + encodeURIComponent(diffDays);
} else {
url += '?mode=CHANGE=' + '&fromDate=' + encodeURIComponent(fromDate) + '&toDate=' + encodeURIComponent(toDate) + '&diff=' + encodeURIComponent(diffDays);
}
window.onbeforeunload = function () { };
window.location.href = url;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
</script>
<style type="text/css">
table,
td,
th {
border: 1px solid black;
border-collapse: collapse;
text-align: center;
padding: 0px;
}
.tabicon {
width: 19%;
display: inline-block;
}
.ItemBackOrderReport_heading {
text-align: center;
font-size: 25px;
font-weight: bold;
background: #BA0020;
margin-bottom: 3%;
}
.ItemBackOrderReport_data_selectoption {
width: 10%;
margin: 0% 0% 4% 0%;
padding: 0.5% 0% 0.5% 0%;
font-weight: bold;
background: #e6e6e6;
}
.ItemBackOrderReport_data {
margin: 2% 2% 2% 2%;
display: inline-block;
}
.ItemBackOrderReport_data_main {
text-align: center;
margin-bottom: 3%;
}
.ItemBackOrderReport_data_main_content {
font-weight: 700;
background: lightgreen;
}
.ItemBackOrderReport_data_main_content_label {
background: #e6e6e6;
}
.chart_div1,
.chart_div2,
.chart_div3,
.chart_div4,
.chart_div5,
.chart_div6 {
/*margin-bottom: 5%;*/
height: 300px;
text-align: -webkit-center
}
.Rep_name_label {
width: 13%;
}
.ItemBackOrderReport_data_label {
width: 7.25%;
word-break: break-word;
}
#nodata {
width: 100%;
text-align: center;
margin-bottom: 2%;
color: red;
font-size: 20px;
}
.chart_div_box {
width: 100%;
}
.box_Target {
padding-right: 2%;
padding-left: 1%;
font-size: 14px;
}
.box_Actual {
padding-left: 1%;
font-size: 14px;
}
.Description_line{
padding: 3px;
}
</style>