The client needs to display their daily finance details on a suitelet page in a table format.
/**
* @NApiVersion 2.1
* @NScriptType Suitelet
*/
define(['N/record', 'N/render', 'N/search', 'N/ui/serverWidget'],
/**
* @param{record} record
* @param{render} render
* @param{search} search
* @param{serverWidget} serverWidget
*/
(record, render, search, serverWidget) => {
/**
* @description Global variable for storing errors ----> for debuging purposes
* @type {Array.<Error>}
* @constant
*/
const ERROR_STACK = [];
/**
* @description Check whether the given parameter argument has value on it or is it empty.
* ie, To check whether a value exists in parameter
* @author Manu Antony
* @param {*} parameter parameter which contains/references some values
* @param {*} parameterName name of the parameter, not mandatory
* @returns {Boolean} true if there exist a value else false
*/
const checkForParameter = (parameter, parameterName) => {
if (parameter !== "" && parameter !== null && parameter !== undefined && parameter !== false && parameter !== "null" && parameter !== "undefined" && parameter !== " " && parameter !== 'false') {
return true;
} else {
if (parameterName)
log.debug('Empty Value found', 'Empty Value for parameter ' + parameterName);
return false;
}
};
/**
* @description To assign a default value if the value argument is empty
* @author Manu Antony
* @param {String|Number|Boolean|Object|Array|null|undefined} value
* @param {String|Number|Boolean|Object|Array} defaultValue
* @returns {*} either value or defaultValue
*/
const assignDefaultValue = (value, defaultValue) => {
if (checkForParameter(value))
return value;
else
return defaultValue;
};
/**
* @description To round a float number
* @author Manu Antony
* @param {Number|String} value
* @param {Number|String} decimals
* @returns {Number} Floating Point Number with the given precision
*/
const roundFloat = (value, decimals) => {
decimals = (decimals) ? decimals : 2;
return Number(Math.round(parseFloat(value) + 'e' + parseInt(decimals)) + 'e-' + parseInt(decimals));
};
/**
* @description To fix a float number to specified decimal parts
* @author Manu Antony
* @param {Number|String} value
* @param {Number|String} decimals
* @returns {Number|String}
*/
const fixFloat = (value, decimals) => {
decimals = (decimals) ? decimals : 2;
// return roundFloat(parseFloat(value), parseInt(decimals)).toFixed(parseInt(decimals));
return parseFloat(value).toFixed(decimals);
};
/**
* @description Common Try-Catch function, applies to Object contains methods/function
* @author Manu Antony
* @param {Object.<string,Function|any>} DATA_OBJ Object contains methods/function
* @param {String} NAME Name of the Object
* @returns {void}
*/
const applyTryCatch = (DATA_OBJ, NAME) => {
/**
* @description Try-Catch function
* @author Manu Antony
* @param {Function} myfunction - reference to a function
* @param {String} key - name of the function
* @returns {Function|false}
*/
const tryCatch = function (myfunction, key) {
return function () {
try {
return myfunction.apply(this, arguments);
} catch (e) {
log.error("error in " + key, e);
ERROR_STACK.push(JSON.stringify(e));
return false;
}
};
};
for (let key in DATA_OBJ) {
if (typeof DATA_OBJ[key] === "function") {
DATA_OBJ[key] = tryCatch(DATA_OBJ[key], NAME + "." + key);
}
}
};
/**
* @description Function to get last day of current month
* @param month
* @param year
* @returns {Date}
*/
const getLastDayOfMonth = (month, year) => {
return new Date(parseInt(year), parseInt(month) + 1, 0);
}
/**
* @description dataSets from Saved Search and formatting Saved Search results
*/
const dataSets = {
/**
* @description Object referencing NetSuite Saved Search
* @typedef {Object} SearchObj
* @property {Object[]} filters - Filters Array in Search
* @property {Object[]} columns - Columns Array in Search
*/
/**
* @description to format Saved Search column to key-value pair where each key represents each columns in Saved Search
* @param {SearchObj} savedSearchObj
* @param {void|String} priorityKey
* @returns {Object.<String,SearchObj.columns>}
*/
fetchSavedSearchColumn(savedSearchObj, priorityKey) {
let columns = savedSearchObj.columns;
let columnsData = {},
columnName = '';
columns.forEach(function (result, counter) {
columnName = '';
if (result[priorityKey]) {
columnName += result[priorityKey];
} else {
if (result.summary)
columnName += result.summary + '__';
if (result.formula)
columnName += result.formula + '__';
if (result.join)
columnName += result.join + '__';
columnName += result.name;
}
columnsData[columnName] = result;
});
return columnsData;
},
/**
* @description Representing each result in Final Saved Search Format
* @typedef formattedEachSearchResult
* @type {{value:any,text:any}}
*/
/**
* @description to fetch and format the single saved search result. ie, Search result of a single row containing both text and value for each columns
* @param {Object[]} searchResult contains search result of a single row
* @param {Object.<String,SearchObj.columns>} columns
* @returns {Object.<String,formattedEachSearchResult>|{}}
*/
formatSingleSavedSearchResult(searchResult, columns) {
let responseObj = {};
for (let column in columns)
responseObj[column] = {
value: searchResult.getValue(columns[column]),
text: searchResult.getText(columns[column])
};
return responseObj;
},
/**
* @description to iterate over and initiate format of each saved search result
* @param {Object} param
* @param {SearchObj} param.searchObj
* @param {void|Object.<String,SearchObj.columns>} param.columns
* @param {number} param.PAGE_INDEX
* @param {number} param.PAGE_SIZE
* @returns {[]|Object[]}
*/
iterateSavedSearch({
searchObj,
columns,
PAGE_INDEX = 1,
PAGE_SIZE = 1000
}) {
if (!checkForParameter(searchObj))
return false;
if (!checkForParameter(columns))
columns = dataSets.fetchSavedSearchColumn(searchObj);
let response = [];
let searchPageRanges;
try {
searchPageRanges = searchObj.runPaged({
pageSize: Number.isInteger(Number(PAGE_SIZE)) ? parseInt(Number(PAGE_SIZE)) : 1000 //Default Page Size
});
} catch (err) {
return Number.isInteger(PAGE_INDEX) ? {
pageInfo: {
pageLength: 1,
pageIndex: 1,
isLastPage: true
},
lines: []
} : [];
}
if (searchPageRanges.pageRanges.length < 1)
return Number.isInteger(PAGE_INDEX) ? {
pageInfo: {
pageLength: 1,
pageIndex: 1,
isLastPage: true
},
lines: []
} : [];
let pageRangeLength = searchPageRanges.pageRanges.length;
log.debug('pageRangeLength', pageRangeLength);
//To make sure the pageIndex has minimum value of one and maximum value of pageRangeLength
const pageIndexRangeRectifier = function (value, pageRange) {
if (!Number.isInteger(Number(value)))
return 1;
if ((Number(value) - 1) <= 0)
return 1;
if ((Number(value) - 1) >= Number(pageRange))
return Number(pageRange);
return Number(value);
};
if (Number.isInteger(PAGE_INDEX))
searchPageRanges.fetch({
index: pageIndexRangeRectifier(PAGE_INDEX, pageRangeLength) - 1
}).data.forEach(function (result) {
response.push(dataSets.formatSingleSavedSearchResult(result, columns));
});
else
for (let pageIndex = 0; pageIndex < pageRangeLength; pageIndex++)
searchPageRanges.fetch({
index: pageIndex
}).data.forEach(function (result) {
response.push(dataSets.formatSingleSavedSearchResult(result, columns));
});
return Number.isInteger(PAGE_INDEX) ? {
pageInfo: {
pageLength: pageRangeLength,
pageIndex: Number(pageIndexRangeRectifier(PAGE_INDEX, pageRangeLength)),
isLastPage: Number(pageIndexRangeRectifier(PAGE_INDEX, pageRangeLength)) >= Number(pageRangeLength) ? true : false
},
lines: response
} : response;
}
};
applyTryCatch(dataSets, 'JJ CM NS Utility, dataSets');
function weeklySearch(){
try {
var customrecord_jj_kpi_parentSearchObj = search.create({
type: "customrecord_jj_kpi_parent",
filters:
[
["created", "within", "05/01/2022 0:00", "06/04/2022 23:59"]
],
columns:
[
search.createColumn({
name: "custrecord_jj_weekly_date",
join: "CUSTRECORD_JJ_WEEKLY_PARENT_KPI",
label: "DATE"
}),
search.createColumn({
name: "custrecord_jj_weekly_zero_cogs",
join: "CUSTRECORD_JJ_WEEKLY_PARENT_KPI",
label: "ZERO_COGS"
}),
search.createColumn({
name: "custrecord_jj_weekly_zero_cogs_item",
join: "CUSTRECORD_JJ_WEEKLY_PARENT_KPI",
label: "ZERO_COGS_ITEMS"
})
]
});
var searchResultCount = customrecord_jj_kpi_parentSearchObj.runPaged().count;
log.debug("customrecord_jj_kpi_parentSearchObj result count", searchResultCount);
return dataSets.iterateSavedSearch({
searchObj: customrecord_jj_kpi_parentSearchObj,
columns: dataSets.fetchSavedSearchColumn(customrecord_jj_kpi_parentSearchObj, 'label'),
PAGE_INDEX: false,
PAGE_SIZE: 1000
}) || [];
}
catch (e) {
log.debug("error@search",e);
}
}
/**
* Defines the Suitelet script trigger point.
* @param {Object} scriptContext
* @param {ServerRequest} scriptContext.request - Incoming request
* @param {ServerResponse} scriptContext.response - Suitelet response
* @since 2015.2
*/
const onRequest = (scriptContext) => {
return scriptContext.response.write(JSON.stringify({
data: weeklySearch().map(el => {
let resEl = {};
for (let key in el)
resEl[key] = el[key].text || el[key].value;
return resEl;
}),
}));
}
return {onRequest}
});