Scenario:
We need to create a suitelet page for resource allocation. The suitelet page should contain similar pages like the same. The Body fields should contain,
- Project Name.
- Common project fields.
- The sublist structure should same as the below image.
Solution
We can use a client script for the validation and another suitelet for background process
//JJ SL Suitelet Page for Resource Allocation.js
/**
* @NApiVersion 2.1
* @NScriptType Suitelet
*/
define(['N/currentRecord', 'N/error', 'N/https', 'N/record', 'N/runtime', 'N/search', 'N/ui/serverWidget', 'N/url', 'N/ui/message'],
/**
* @param{currentRecord} currentRecord
* @param{error} error
* @param{https} https
* @param{record} record
* @param{runtime} runtime
* @param{search} search
* @param{serverWidget} serverWidget
* @param{url} url
* @param{message} message
*/
(currentRecord, error, https, record, runtime, search, serverWidget, url, message) => {
/**
* Function to check whether the field has an empty value or not.
*
* @param {parameter} parameter - fieldValue
* @returns {boolean} true - if the value is not empty
* @returns {boolean} false - if the value is empty
*
* @since 2015.2
*/
function checkForParameter(parameter) {
try{
if (parameter != "" && parameter != null && parameter != undefined && parameter != "null" && parameter != "undefined" && parameter != " " && parameter != false) {
return true;
}
else {
return false;
}
}
catch (e) {
log.error({
title: "Error @ empty check Function: ",
details: e.name+' : '+e.message
})
}
}
function projectSearch(user,userSubsidary,roleCenter){
try{
if(checkForParameter(roleCenter)==true) {
var filterArr = []
if (roleCenter == "FINANCIAL") {
if(checkForParameter(userSubsidary)==true) {
filterArr = [
["isinactive", "is", "F"],
"AND",
["status", "anyof", "2"],
"AND",
["subsidiary", "anyof", userSubsidary]
]
}
}
else{
if(checkForParameter(user)==true) {
filterArr = [
["isinactive", "is", "F"],
"AND",
[[["jobresource", "anyof", user], "AND", ["jobresourcerole", "anyof", "-2"]], "OR", ["projectmanager", "anyof", user]],
"AND",
["status", "anyof", "2"]
]
}
}
log.debug("filterArr: ",filterArr)
var jobSearchObj = search.create({
type: "job",
filters: filterArr,
columns:
[
search.createColumn({
name: "internalid",
sort: search.Sort.ASC,
label: "Internal ID"
}),
search.createColumn({name: "entityid", label: "Name"}),
search.createColumn({name: "customer", label: "Client"}),
search.createColumn({name: "subsidiary", label: "Subsidiary"}),
search.createColumn({name: "calculatedwork", label: "Calculated Work"}),
search.createColumn({name: "plannedwork", label: "Planned Work"}),
search.createColumn({name: "actualtime", label: "Actual Work"}),
search.createColumn({name: "timeremaining", label: "Remaining Work"}),
search.createColumn({name: "entitystatus", label: "Status"})
]
});
var searchResultCount = jobSearchObj.runPaged().count;
var res = []
if (searchResultCount > 0) {
jobSearchObj.run().each(function (result) {
// .run().each has a limit of 4,000 results
var prjId = result.getValue({name: "internalid", sort: search.Sort.ASC})
var prjName = result.getValue({name: "entityid"})
var client = result.getValue({name: "customer"})
var subsidiary = result.getValue({name: "subsidiary"})
var calculatedWork = result.getValue({name: "calculatedwork"})
var plannedWork = result.getValue({name: "plannedwork"})
var actualWork = result.getValue({name: "actualtime"})
var remainingWork = result.getValue({name: "timeremaining"})
var status = result.getValue({name: "entitystatus"})
res.push({
prjId: prjId,
prjName: prjName,
client: client,
subsidiary: subsidiary,
calculatedWork: calculatedWork,
plannedWork: plannedWork,
actualWork: actualWork,
remainingWork: remainingWork,
status: status
})
return true;
});
}
return res;
}
}
catch (e) {
log.error({
title: "Error @ Project Search: ",
details: e.name+' : '+e.message
})
}
}
function projectTaskSearch(prjId){
try{
if(checkForParameter(prjId)==true) {
var projecttaskSearchObj = search.create({
type: "projecttask",
filters:
[
["project", "anyof", prjId],
"AND",
["status","anyof","PROGRESS","NOTSTART"],
"AND",
["ismilestone","is","F"]
],
columns:
[
search.createColumn({
name: "internalid",
sort: search.Sort.ASC,
label: "Internal ID"
}),
search.createColumn({name: "title", label: "Name"}),
search.createColumn({name: "company", label: "Project"})
]
});
var searchResultCount = projecttaskSearchObj.runPaged().count;
var res = [];
projecttaskSearchObj.run().each(function (result) {
// .run().each has a limit of 4,000 results
var taskId = result.getValue({
name: "internalid",
sort: search.Sort.ASC
})
var taskName = result.getValue({
name: "title"
})
res.push({
taskId: taskId,
taskName: taskName
})
return true;
});
return res;
}
}
catch (e) {
log.error({
title: "Error @ Project Task Search: ",
details: e.name+' : '+e.message
})
}
}
function genericResourceSearch(subs){
try{
var genericresourceSearchObj = search.create({
type: "genericresource",
filters:
[
["isinactive","is","F"],
"AND",
["subsidiary","anyof",subs]
],
columns:
[
search.createColumn({
name: "internalid",
sort: search.Sort.ASC,
label: "Internal ID"
}),
search.createColumn({name: "entityid", label: "Name"})
]
});
var searchResultCount = genericresourceSearchObj.runPaged().count;
var res = [];
genericresourceSearchObj.run().each(function(result){
// .run().each has a limit of 4,000 results
var genericId = result.getValue({name: "internalid", sort: search.Sort.ASC})
var genericName = result.getValue({name: "entityid"})
res.push({
genericId: genericId,
genericName: genericName
})
return true;
});
return res;
}
catch (e) {
log.error({
title: "Error @ genericManagerSearch: ",
details: e.name+' : '+e.message
})
}
}
function billingCardSearch(subsidary){
try{
var billingratecardSearchObj = search.create({
type: "billingratecard",
filters:
[
["isinactive","is","F"],
"AND",
["custrecord23","anyof",subsidary]
],
columns:
[
search.createColumn({
name: "internalid",
sort: search.Sort.ASC,
label: "Internal ID"
}),
search.createColumn({name: "name", label: "Name"}),
search.createColumn({name: "custrecord23", label: "Subsidary"})
]
});
var searchResultCount = billingratecardSearchObj.runPaged().count;
var res = [];
billingratecardSearchObj.run().each(function(result){
// .run().each has a limit of 4,000 results
var cardId = result.getValue({name: "internalid", sort: search.Sort.ASC})
var cardName = result.getValue({name: "name"})
res.push({
cardId: cardId,
cardName: cardName
})
return true;
});
return res;
}
catch (e) {
log.error({
title: "Error @ Billing rate card search: ",
details: e.name+' : '+e.message
})
}
}
/**
* 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) => {
try{
var prjIdParam = scriptContext.request.parameters.prjId
var userObj = runtime.getCurrentUser();
var currUser = userObj.id
var roleCenter = userObj.roleCenter;
log.debug('String value of current user center type (role center): ' + roleCenter);
var userLookup = search.lookupFields({
type: record.Type.EMPLOYEE,
id: currUser,
columns: ["subsidiary"]
})
var userSubsidary = userLookup && userLookup.subsidiary.length>0 && userLookup.subsidiary[0].value
log.debug("userSubsidary: ",userSubsidary)
var prjList = projectSearch(currUser,userSubsidary,roleCenter)
var projectTaskList = projectTaskSearch(prjIdParam)
var form = serverWidget.createForm({
title: 'Resource Allocation'
});
form.clientScriptFileId = 180706
var progressBarField = form.addField({
id: 'custpage_progress_bar',
type: 'INLINEHTML',
label: 'Progress bar'
});
var loadingUrl = "https://3689903.app.netsuite.com/core/media/media.nl?id=32305&c=3689903&h=dcec0a9dd4c1943ff816";
var html = "<div><img id='custpage_load_img' style='height:60px;width:100px;top: 305px;left: 693px;float: right;position: absolute;display: none;' src='" + loadingUrl + "'/></div>";
progressBarField.defaultValue = html;
if(scriptContext.request.method === 'GET') {
var projectList = form.addField({
id: 'custpage_project',
type: serverWidget.FieldType.SELECT,
label: 'Project Name'
})
projectList.addSelectOption({
value: " ",
text: "SELECT",
isSelected: true
})
if(prjList.length>0){
for(var i=0;i<prjList.length;i++) {
projectList.addSelectOption({
value: prjList[i].prjId,
text: prjList[i].prjName
})
}
}
projectList.isMandatory = true
projectList.defaultValue = prjIdParam
if(checkForParameter(prjIdParam)==true) {
var fieldLookUp = search.lookupFields({
type: search.Type.JOB,
id: prjIdParam,
columns: ['customer', 'subsidiarynohierarchy', 'calculatedwork', 'plannedwork', 'actualtime', 'timeremaining', 'entitystatus','custentity3','currency','allowallresourcesfortasks']
});
log.debug("fieldLookUp: ",fieldLookUp)
// var pref = fieldLookUp&&fieldLookUp.allowallresourcesfortasks
var subs = fieldLookUp.subsidiarynohierarchy[0].value
var genericResources = genericResourceSearch(subs)
var ratecardSearch = billingCardSearch(fieldLookUp.subsidiarynohierarchy[0].value)
var prjRec = record.load({
type: record.Type.JOB,
id: prjIdParam,
isDynamic: true
})
prjRec.setValue({
fieldId: 'allowallresourcesfortasks',//checking the value DISPLAY ALL RESOURCES FOR PROJECT TASK ASSIGNMENT in Project Record to automatically add resources to project record
value: true
})
prjRec.save()
var pref = prjRec.getValue({
fieldId: 'allowallresourcesfortasks'
})
log.debug("PREFERENCE: ",pref)
var client = form.addField({
id: 'custpage_client',
type: serverWidget.FieldType.TEXT,
label: 'Client'
})
client.defaultValue = fieldLookUp.customer.length>0 && fieldLookUp.customer[0].text;
client.updateDisplayType({
displayType: serverWidget.FieldDisplayType.INLINE
})
var subsidiary = form.addField({
id: 'custpage_subsidiary',
type: serverWidget.FieldType.TEXT,
label: 'Subsidiary'
})
subsidiary.defaultValue = fieldLookUp.subsidiarynohierarchy.length>0 && fieldLookUp.subsidiarynohierarchy[0].text
subsidiary.updateDisplayType({
displayType: serverWidget.FieldDisplayType.INLINE
})
var subsidiaryId = form.addField({
id: 'custpage_subsidiaryid',
type: serverWidget.FieldType.TEXT,
label: 'Subsidiary ID'
})
subsidiaryId.defaultValue = fieldLookUp.subsidiarynohierarchy.length>0 && fieldLookUp.subsidiarynohierarchy[0].value
subsidiaryId.updateDisplayType({
displayType: serverWidget.FieldDisplayType.HIDDEN
})
var calculatedWork = form.addField({
id: 'custpage_calculated_work',
type: serverWidget.FieldType.TEXT,
label: 'Calculated Work'
})
calculatedWork.defaultValue = fieldLookUp.calculatedwork
calculatedWork.updateDisplayType({
displayType: serverWidget.FieldDisplayType.INLINE
})
var plannedWork = form.addField({
id: 'custpage_planned_work',
type: serverWidget.FieldType.TEXT,
label: 'Planned Work'
})
plannedWork.defaultValue = fieldLookUp.plannedwork
plannedWork.updateDisplayType({
displayType: serverWidget.FieldDisplayType.INLINE
})
var actualWork = form.addField({
id: 'custpage_actual_work',
type: serverWidget.FieldType.TEXT,
label: 'Actual Work'
})
actualWork.defaultValue = fieldLookUp.actualtime
actualWork.updateDisplayType({
displayType: serverWidget.FieldDisplayType.INLINE
})
var remainingWork = form.addField({
id: 'custpage_remaining_work',
type: serverWidget.FieldType.TEXT,
label: 'Remaining Work'
})
remainingWork.defaultValue = fieldLookUp.timeremaining
remainingWork.updateDisplayType({
displayType: serverWidget.FieldDisplayType.INLINE
})
var currency = form.addField({
id: 'custpage_currency',
type: serverWidget.FieldType.TEXT,
label: 'Currency'
})
currency.defaultValue = fieldLookUp.currency.length>0 && fieldLookUp.currency[0].text
currency.updateDisplayType({
displayType: serverWidget.FieldDisplayType.INLINE
})
var currencyId = form.addField({
id: 'custpage_currencyid',
type: serverWidget.FieldType.TEXT,
label: 'Currency ID'
})
currencyId.defaultValue = fieldLookUp.currency.length>0 && fieldLookUp.currency[0].value
currencyId.updateDisplayType({
displayType: serverWidget.FieldDisplayType.HIDDEN
})
var status = form.addField({
id: 'custpage_status',
type: serverWidget.FieldType.TEXT,
label: 'Status'
})
status.defaultValue = fieldLookUp.entitystatus.length>0 && fieldLookUp.entitystatus[0].text
status.updateDisplayType({
displayType: serverWidget.FieldDisplayType.INLINE
})
var rateCards = form.addField({
id: 'custpage_billing_rate_card',
type: serverWidget.FieldType.TEXT,
label: 'Rate Card'
})
rateCards.defaultValue = fieldLookUp.custentity3.length>0 ? fieldLookUp.custentity3[0].text : ''
rateCards.updateDisplayType({
displayType: serverWidget.FieldDisplayType.INLINE
})
var rateCardsId = form.addField({
id: 'custpage_billing_rate_card_id',
type: serverWidget.FieldType.TEXT,
label: 'Rate Card ID'
})
rateCardsId.defaultValue = fieldLookUp.custentity3.length>0 ? fieldLookUp.custentity3[0].value : ''
rateCardsId.updateDisplayType({
displayType: serverWidget.FieldDisplayType.HIDDEN
})
//SUBLIST
var sublist = form.addSublist({
id: 'custpage_allocation_details',
type: serverWidget.SublistType.INLINEEDITOR,
label: 'Allocation Details'
})
var taskList = sublist.addField({
id: 'custpage_project_task',
type: serverWidget.FieldType.SELECT,
label: 'Project Task'
})
taskList.addSelectOption({
value: " ",
text: "SELECT TASK",
isSelected: true
})
if (projectTaskList.length > 0) {
for (var j = 0; j < projectTaskList.length; j++) {
taskList.addSelectOption({
value: projectTaskList[j].taskId,
text: projectTaskList[j].taskName
})
}
}
taskList.isMandatory = true
var taskBillingRateCard = sublist.addField({
id: 'custpage_project_task_billing_rate_card',
type: serverWidget.FieldType.TEXT,
label: 'Project Task Billing Rate Card'
})
taskBillingRateCard.updateDisplayType({
displayType: serverWidget.FieldDisplayType.HIDDEN
})
var estimatedFee = sublist.addField({
id: 'custpage_estimated_fee',
type:serverWidget.FieldType.TEXT,
label: 'Estimated Fee'
})
estimatedFee.updateDisplayType({
displayType: serverWidget.FieldDisplayType.DISABLED
})
var billingType = sublist.addField({
id: 'custpage_billing_type',
type:serverWidget.FieldType.TEXT,
label: 'Billing Type'
})
billingType.updateDisplayType({
displayType: serverWidget.FieldDisplayType.DISABLED
})
var genericEmployee = sublist.addField({
id: 'custpage_generic_employee',
type: serverWidget.FieldType.SELECT,
label: 'Generic Employee'
})
genericEmployee.addSelectOption({
value: " ",
text: "SELECT",
isSelected: true
})
if(genericResources.length>0){
for(var k=0;k<genericResources.length;k++){
genericEmployee.addSelectOption({
value: genericResources[k].genericId,
text: genericResources[k].genericName
})
}
}
genericEmployee.isMandatory = true
var genericBillingClass = sublist.addField({
id: 'custpage_generic_billingclass',
type: serverWidget.FieldType.TEXT,
label: 'Generic Billing Class'
})
genericBillingClass.updateDisplayType({
displayType: serverWidget.FieldDisplayType.DISABLED
})
var genericBillingClassId = sublist.addField({
id: 'custpage_generic_billingclassid',
type: serverWidget.FieldType.TEXT,
label: 'Generic Billing Class ID'
})
genericBillingClassId.updateDisplayType({
displayType: serverWidget.FieldDisplayType.HIDDEN
})
var vendorCheck = sublist.addField({
id: 'custpage_is_vendor',
type: serverWidget.FieldType.CHECKBOX,
label: 'Add Vendors'
})
vendorCheck.defaultValue = false
var rateCard = sublist.addField({
id: 'custpage_rate_card',
type: serverWidget.FieldType.SELECT,
label: 'Rate Card'
})
rateCard.addSelectOption({
value: " ",
text: "SELECT",
isSelected: true
})
if(ratecardSearch.length>0){
for(var k=0;k<ratecardSearch.length;k++){
rateCard.addSelectOption({
value: ratecardSearch[k].cardId,
text: ratecardSearch[k].cardName,
})
}
}
var checkVal = sublist.addField({
id: 'custpage_is_project_rate_card',
type: serverWidget.FieldType.CHECKBOX,
label: 'Use Project/Task Rate Card'
})
checkVal.defaultValue = false
var prjTaskRateCard = sublist.addField({
id: 'custpage_project_task_rate_card',
type: serverWidget.FieldType.TEXT,
label: 'Project Task Rate Card'
})
prjTaskRateCard.updateDisplayType({
displayType: serverWidget.FieldDisplayType.DISABLED
})
var plannedHrs = sublist.addField({
id: 'custpage_planned_hours',
type: serverWidget.FieldType.FLOAT,
label: 'Planned Hours'
})
plannedHrs.isMandatory = true
var unitPrice = sublist.addField({
id: 'custpage_rate',
type: serverWidget.FieldType.FLOAT,
label: 'Unit Price'
})
unitPrice.isMandatory =true
var totalPrice = sublist.addField({
id: 'custpage_value',
type: serverWidget.FieldType.FLOAT,
label: 'Price'
})
totalPrice.updateDisplayType({
displayType: serverWidget.FieldDisplayType.DISABLED
})
form.addButton({
id: 'custpage_add_btn',
label: 'SUBMIT',
functionName: 'addRec'
})
// form.addSubmitButton({
// label: 'SUBMIT'
// })
}
scriptContext.response.writePage(form);
}
}
catch (e) {
log.error({
title: "Error @ onRequest: ",
details: e.name+' : '+e.message
})
}
}
return {onRequest}
});
// JJ CS Validation.js
/**
* @NApiVersion 2.x
* @NScriptType ClientScript
* @NModuleScope SameAccount
*/
define(['N/currentRecord', 'N/https', 'N/record', 'N/search', 'N/runtime', 'N/url','N/ui/message'],
/**
* @param{currentRecord} currentRecord
* @param{https} https
* @param{record} record
* @param{search} search
* @param{runtime} runtime
* @param{url} url
* @param{message} message
*/
function(currentRecord, https, record, search, runtime, url,message) {
var currentRec = currentRecord.get()
var project,projectSub,projectPref;
/**
* Function to check whether the field has an empty value or not.
*
* @param {parameter} parameter - fieldValue
* @returns {boolean} true - if the value is not empty
* @returns {boolean} false - if the value is empty
*
* @since 2015.2
*/
function checkForParameter(parameter) {
try{
if (parameter != "" && parameter != null && parameter != undefined && parameter != "null" && parameter != "undefined" && parameter != " " && parameter != false) {
return true;
}
else {
return false;
}
}
catch (e) {
console.log("Error @ empty check Function: ",e.name+' : '+e.message)
}
}
/**
* Function to check the price of the rate card.
*
* @param {genericBillingClass} genericBillingClass - fieldValue
* @param {rateCardId} rateCardId - fieldValue
* @param {prjCurrency} prjCurrency - fieldValue
* @returns {res} res - result
*
* @since 2015.2
*/
function rateCardSearch(genericBillingClass,rateCardId,prjCurrency){
try{
if(checkForParameter(genericBillingClass)==true&&checkForParameter(rateCardId)==true&&checkForParameter(prjCurrency)==true){
var billingratecardSearchObj = search.create({
type: "billingratecard",
filters:
[
["currency","anyof",prjCurrency],
"AND",
["internalid","anyof",rateCardId],
"AND",
["billingclass","anyof",genericBillingClass],
"AND",
["effectivedate","onorbefore","today"],
"AND",
[["enddate","onorafter","today"],"OR",["formuladate: {enddate}","isempty",""]]
],
columns:
[
search.createColumn({
name: "name",
summary: "MAX",
sort: search.Sort.ASC,
label: "Name"
}),
search.createColumn({
name: "price",
summary: "MAX",
label: "Price"
})
]
});
var searchResultCount = billingratecardSearchObj.runPaged().count;
var res= []
billingratecardSearchObj.run().each(function(result){
// .run().each has a limit of 4,000 results
var name = result.getValue({
name: "name",
summary: "MAX",
sort: search.Sort.ASC
})
var price = result.getValue({
name: "price",
summary: "MAX"
})
res.push({
name: name,
price: price
})
return true;
});
}
return res
}
catch (e) {
console.log("Error @ ratecard Search: ",e.name+": "+e.message)
}
}
/**
* Function to be executed when field is changed.
*
* @param {Object} scriptContext
* @param {Record} scriptContext.currentRecord - Current form record
* @param {string} scriptContext.sublistId - Sublist name
* @param {string} scriptContext.fieldId - Field name
* @param {number} scriptContext.lineNum - Line number. Will be undefined if not a sublist or matrix field
* @param {number} scriptContext.columnNum - Line number. Will be undefined if not a matrix field
*
* @since 2015.2
*/
function fieldChanged(scriptContext) {
try {
if (window.onbeforeunload) {
window.onbeforeunload = function () {
null;
};
}
var oldUrl = window.location.href;
var curRec = scriptContext.currentRecord
var prjId = curRec.getValue({
fieldId: 'custpage_project'
})
project = prjId
if(checkForParameter(prjId)==true) {
var prjFieldLookUp = search.lookupFields({
type: search.Type.JOB,
id: prjId,
columns: ['currency','subsidiarynohierarchy','allowallresourcesfortasks']
});
var prjCurrency = prjFieldLookUp.currency.length > 0 && prjFieldLookUp.currency[0].value
projectSub = prjFieldLookUp && prjFieldLookUp.subsidiarynohierarchy.length>0 && prjFieldLookUp.subsidiarynohierarchy[0].value
projectPref = prjFieldLookUp && prjFieldLookUp.allowallresourcesfortasks
if (scriptContext.fieldId == 'custpage_project') {
oldUrl = oldUrl.split('&deploy=' + 1);
if (checkForParameter(prjId) == true) {
var newUrl = oldUrl[0] + "&deploy=1&prjId=" + prjId;
window.location.href = newUrl;
} else {
window.location.href = oldUrl;
}
}
var prjTaskId = curRec.getCurrentSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_project_task'
})
var prjTaskBillingRateCard, prjTaskBillingRateCardId, estimatedFee, billingType;
if (checkForParameter(prjTaskId) == true) {
var fieldLookup = search.lookupFields({
type: search.Type.PROJECT_TASK,
id: prjTaskId,
columns: ['custevent3', 'custevent_jj_billing_type', 'custevent_jj_total_estimated']
});
prjTaskBillingRateCardId = (fieldLookup && fieldLookup.custevent3.length > 0) ? fieldLookup.custevent3[0].value : " "
prjTaskBillingRateCard = (fieldLookup && fieldLookup.custevent3.length > 0) ? fieldLookup.custevent3[0].text : " "
estimatedFee = (fieldLookup && fieldLookup.custevent_jj_total_estimated) ? fieldLookup.custevent_jj_total_estimated : " "
billingType = (fieldLookup && fieldLookup.custevent_jj_billing_type.length > 0) ? fieldLookup.custevent_jj_billing_type[0].text : " "
}
var genericResource = curRec.getCurrentSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_generic_employee'
})
var genericBillingClass, genericBillingClassId;
if (checkForParameter(genericResource) == true) {
var genericLookup = search.lookupFields({
type: record.Type.GENERIC_RESOURCE,
id: genericResource,
columns: ['billingclass']
})
genericBillingClass = (genericLookup && genericLookup.billingclass.length > 0) ? genericLookup.billingclass[0].text : " "
genericBillingClassId = (genericLookup && genericLookup.billingclass.length > 0) ? genericLookup.billingclass[0].value : " "
}
var manualRateCard = curRec.getCurrentSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_rate_card'
})
var checkboxValue = curRec.getCurrentSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_is_project_rate_card'
})
var autoRateCard = curRec.getValue({
fieldId: 'custpage_billing_rate_card'
})
var autoRateCardId = curRec.getValue({
fieldId: 'custpage_billing_rate_card_id'
})
var plannedHours = curRec.getCurrentSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_planned_hours'
})
var rate = curRec.getCurrentSublistValue({ //unit price
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_rate'
})
var value = curRec.getCurrentSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_value'
})
var autoCardValue = curRec.getCurrentSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_project_task_rate_card'
})
var autoUnitPrice = []
if (scriptContext.fieldId == 'custpage_project_task') {
if (checkForParameter(estimatedFee) == true) {
curRec.setCurrentSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_estimated_fee',
value: estimatedFee ? Number(estimatedFee).toFixed(2) : Number(0).toFixed(2)
})
}
if (checkForParameter(billingType) == true) {
curRec.setCurrentSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_billing_type',
value: billingType ? billingType : " "
})
}
if (checkForParameter(prjTaskId) == false) {
curRec.setCurrentSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_estimated_fee',
value: ''
})
curRec.setCurrentSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_billing_type',
value: ''
})
}
}
if (scriptContext.fieldId == 'custpage_generic_employee') {
if (checkForParameter(genericResource) == true) {
curRec.setCurrentSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_generic_billingclass',
value: genericBillingClass ? genericBillingClass : ''
})
curRec.setCurrentSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_generic_billingclassid',
value: genericBillingClassId ? genericBillingClassId : ''
})
}
else {
curRec.setCurrentSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_generic_billingclass',
value: ''
})
curRec.setCurrentSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_generic_billingclassid',
value: ''
})
curRec.setCurrentSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_is_vendor',
value: false
})
curRec.setCurrentSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_rate_card',
value: ''
})
curRec.setCurrentSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_is_project_rate_card',
value: false
})
curRec.setCurrentSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_project_task_rate_card',
value: ' '
})
curRec.setCurrentSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_planned_hours',
value: ''
})
curRec.setCurrentSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_rate',
value: ''
})
curRec.setCurrentSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_value',
value: ''
})
}
}
if (scriptContext.fieldId == 'custpage_planned_hours' || scriptContext.fieldId == 'custpage_rate') {
if (checkForParameter(plannedHours) == true && checkForParameter(rate) == true) {
var total = Number(plannedHours) * Number(rate)
curRec.setCurrentSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_value',
value: Number(total).toFixed(2)
})
return true
}
else {
curRec.setCurrentSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_value',
value: ''
})
return false
}
}
if (scriptContext.fieldId == 'custpage_is_project_rate_card') {
if (checkForParameter(manualRateCard) == true) {
if (checkboxValue == true) {
curRec.setCurrentSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_is_project_rate_card',
value: false
})
alert("You can't perform this operation Now. You have already selected the Rate card Manually")
return false
} else {
return true
}
}
if (checkForParameter(checkboxValue) == true && checkForParameter(prjTaskBillingRateCard) == true) {
curRec.setCurrentSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_project_task_rate_card',
value: prjTaskBillingRateCard
})
autoUnitPrice = rateCardSearch(genericBillingClassId, prjTaskBillingRateCardId, prjCurrency)
curRec.setCurrentSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_rate',
value: (autoUnitPrice && autoUnitPrice.length > 0) && Number(autoUnitPrice[0].price).toFixed(2)
})
}
else if (checkForParameter(checkboxValue) == true && checkForParameter(prjTaskBillingRateCard) == false && checkForParameter(autoRateCard) == true) {
curRec.setCurrentSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_project_task_rate_card',
value: autoRateCard
})
var autoUnitPrice = rateCardSearch(genericBillingClassId, autoRateCardId, prjCurrency)
curRec.setCurrentSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_rate',
value: (autoUnitPrice && autoUnitPrice.length > 0) && Number(autoUnitPrice[0].price).toFixed(2)
})
} else {
curRec.setCurrentSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_project_task_rate_card',
value: ''
})
curRec.setCurrentSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_rate',
value: ''
})
curRec.setCurrentSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_planned_hours',
value: ''
})
curRec.setCurrentSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_value',
value: ''
})
}
}
if (scriptContext.fieldId == 'custpage_rate_card') {
if (checkboxValue == true) {
if (checkForParameter(manualRateCard) == true) {
curRec.setCurrentSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_rate_card',
value: " "
})
alert("You can't perform this operation Now. You have already selected the Rate card Automatically")
return false
}
}
if (checkboxValue == false) {
if (checkForParameter(manualRateCard) == true) {
var manualUnitPrice = rateCardSearch(genericBillingClassId, manualRateCard, prjCurrency)
curRec.setCurrentSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_rate',
value: (manualUnitPrice && manualUnitPrice.length > 0) && Number(manualUnitPrice[0].price).toFixed(2)
})
}
if (checkForParameter(manualRateCard) == false) {
curRec.setCurrentSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_rate',
value: ''
})
curRec.setCurrentSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_planned_hours',
value: ''
})
curRec.setCurrentSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_value',
value: ''
})
}
}
}
}
if(checkForParameter(prjId)==false) {
oldUrl = oldUrl.split('&deploy=' + 1);
var newUrl = oldUrl[0] + "&deploy=1";
window.location.href = newUrl;
return true
}
}
catch (e) {
console.log("Error @ Field Changed: ",e.name+" : "+e.message)
}
}
/**
* Validation function to be executed when sublist line is committed.
*
* @param {Object} scriptContext
* @param {Record} scriptContext.currentRecord - Current form record
* @param {string} scriptContext.sublistId - Sublist name
*
* @returns {boolean} Return true if sublist line is valid
*
* @since 2015.2
*/
function validateLine(scriptContext){
try{
if(scriptContext.sublistId == 'custpage_allocation_details') {
var curRec = scriptContext.currentRecord
var prjTaskId = curRec.getCurrentSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_project_task'
})
var genericResource = curRec.getCurrentSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_generic_employee'
})
var plannedHrs = curRec.getCurrentSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_planned_hours'
})
var rate = curRec.getCurrentSublistValue({ //unit price
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_rate'
})
var price = curRec.getCurrentSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_value'
})
if(checkForParameter(prjTaskId)==false&&checkForParameter(genericResource)==false&&checkForParameter(plannedHrs)==false&&checkForParameter(rate)==false){
alert("Please enter values for Project Task, Generic Employee, Planned Hours, Unit Price")
return false
}
if(Number(rate)<=0 || Number(plannedHrs)<=0){
alert("Value Should be greater than Zero")
return false
}
if(checkForParameter(price)==false || Number(price)<0){
alert("Price should have a value. Values for Unit Price should be a Non Zero or Positive number")
return false
}
else {
return true
}
}
}
catch (e) {
console.log("Error @ Validate Line: ",e.name+" : "+e.message)
}
}
// /**
// * Validation function to be executed when record is saved.
// *
// * @param {Object} scriptContext
// * @param {Record} scriptContext.currentRecord - Current form record
// * @returns {boolean} Return true if record is valid
// *
// * @since 2015.2
// */
function addRec() {
try{
console.log("clicked")
var promise = new Promise(function (resolve, reject) {
jQuery("#custpage_load_img").css("display", "block");
setTimeout(function () {
resolve();
}, 5000)
});
console.log("promise: ",promise)
var projectId = project
var projectSubsidiary = projectSub
var prjPref = projectPref
var count = currentRec.getLineCount({
sublistId: 'custpage_allocation_details'
})
console.log("projectId: ",projectId)
console.log("projectSubsidiary: ",projectSubsidiary)
console.log("prjPref: ",prjPref)
console.log("count: ",count)
var taskArr = []
if(count>0) {
for (var i = 0; i < count; i++) {
var taskId = currentRec.getSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_project_task',
line: i
})
var genericEmp = currentRec.getSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_generic_employee',
line: i
})
var plannedHrs = currentRec.getSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_planned_hours',
line: i
})
var unitPrice = currentRec.getSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_rate',
line: i
})
var billingClass = currentRec.getSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_generic_billingclassid',
line: i
})
var isVendor = currentRec.getSublistValue({
sublistId: 'custpage_allocation_details',
fieldId: 'custpage_is_vendor',
line: i
})
taskArr.push({
taskId: taskId,
genericEmp: genericEmp,
plannedHrs: plannedHrs,
unitPrice: unitPrice,
billingClass: billingClass,
isVendor: isVendor
})
}
}
console.log("taskArr: ",JSON.stringify(taskArr))
var strTaskArr = JSON.stringify(taskArr)
var objParam = {
projectId: projectId,
projectSubsidiary: projectSubsidiary,
prjPref: prjPref,
taskArr: strTaskArr
}
console.log("objParam: ",objParam)
var output = url.resolveScript({
scriptId: 'customscript_jj_sl_suitelet_for_msg_aq',
deploymentId: 'customdeploy_jj_sl_suitelet_for_msg_aq',
params: objParam
});
console.log("output: ",output)
var response = https.post({
url: output,
body: 'Background Processing'
});
console.log("response: ",response)
var body = JSON.parse(response.body)
console.log("body: ",body)
var responseStatus = body.status;
console.log("responseStatus: ",responseStatus)
if(responseStatus == "SUCCESS"){
jQuery("#custpage_load_img").css("display", "none");
var redirectUrl = 'https://3689903-sb1.app.netsuite.com/app/site/hosting/scriptlet.nl?script=788&deploy=1'
window.location.href = redirectUrl
return true
}
else {
jQuery("#custpage_load_img").css("display", "none");
var msg = message.create({
title: "Error Occurred",
message: "An Error Occurred during the Process. Allocation Failed",
type: message.Type.ERROR,
duration: 10000
})
msg.show()
return false
}
}
catch (e) {
console.log("ERROR @ addRec: ",e.name+" : "+e.message)
}
}
return {
fieldChanged: fieldChanged,
validateLine: validateLine,
addRec: addRec
};
});
//JJ SL Background Script.js
/**
* @NApiVersion 2.1
* @NScriptType Suitelet
*/
define(['N/currentRecord', 'N/error', 'N/record', 'N/runtime', 'N/ui/message', 'N/ui/serverWidget', 'N/url', 'N/search'],
/**
* @param{currentRecord} currentRecord
* @param{error} error
* @param{record} record
* @param{runtime} runtime
* @param{message} message
* @param{search} search
* @param{serverWidget} serverWidget
* @param{url} url
*/
(currentRecord, error, record, runtime, message, serverWidget, url, search) => {
/**
* Function to check whether the field has an empty value or not.
*
* @param {parameter} parameter - fieldValue
* @returns {boolean} true - if the value is not empty
* @returns {boolean} false - if the value is empty
*
* @since 2015.2
*/
function checkForParameter(parameter) {
try{
if (parameter != "" && parameter != null && parameter != undefined && parameter != "null" && parameter != "undefined" && parameter != " " && parameter != false) {
return true;
}
else {
return false;
}
}
catch (e) {
log.error({
title: "Error @ empty check Function: ",
details: e.name+' : '+e.message
})
}
}
function employeeSearch(subsidiary,billingClass){
try{
if(checkForParameter(subsidiary)==true&&checkForParameter(billingClass)==true) {
var employeeSearchObj = search.create({
type: "employee",
filters:
[
["isinactive", "is", "F"],
"AND",
["isjobresource", "is", "T"],
"AND",
[["releasedate", "isempty", ""], "OR", ["releasedate", "after", "today"]],
"AND",
["subsidiary", "anyof", subsidiary],
"AND",
["billingclass", "anyof", billingClass]
],
columns:
[
search.createColumn({name: "internalid", label: "Internal ID"}),
search.createColumn({
name: "entityid",
sort: search.Sort.ASC,
label: "Name"
})
]
});
var searchResultCount = employeeSearchObj.runPaged().count;
var res = []
employeeSearchObj.run().each(function (result) {
// .run().each has a limit of 4,000 results
var empId = result.getValue({
name: "internalid"
})
var empName = result.getValue({
name: "entityid",
sort: search.Sort.ASC
})
res.push({
empId: empId,
empName:empName
})
return true;
});
return res
}
}
catch (e) {
log.error({
title: "Error @ Employee Search: ",
details: e.name+' : '+e.message
})
}
}
function vendorSearch(subsidiary,billingClass){
try{
if(checkForParameter(subsidiary)==true&&checkForParameter(billingClass)==true){
var vendorSearchObj = search.create({
type: "vendor",
filters:
[
["isinactive","is","F"],
"AND",
["isjobresourcevend","is","T"],
"AND",
["msesubsidiary.internalid","anyof",subsidiary],
"AND",
["billingclass","anyof",billingClass]
],
columns:
[
search.createColumn({name: "internalid", label: "Internal ID"}),
search.createColumn({
name: "entityid",
sort: search.Sort.ASC,
label: "Name"
})
]
});
var searchResultCount = vendorSearchObj.runPaged().count;
var res = [];
vendorSearchObj.run().each(function(result){
// .run().each has a limit of 4,000 results
var empId = result.getValue({
name: "internalid"
})
var empName = result.getValue({
name: "entityid",
sort: search.Sort.ASC
})
res.push({
empId: empId,
empName:empName
})
return true;
});
return res
}
}
catch (e) {
log.error({
title: "Error @ vendorSearch: ",
details: e.name+' : '+e.message
})
}
}
/**
* 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) => {
try{
if(scriptContext.request.method === 'POST') {
var projectId = scriptContext.request.parameters.projectId
var projectSubsidiary = scriptContext.request.parameters.projectSubsidiary
var prjPref = scriptContext.request.parameters.prjPref
var taskArr = scriptContext.request.parameters.taskArr
var count = JSON.parse(taskArr)
log.debug("projectId: ",projectId)
log.debug("prjPref: ",prjPref)
log.debug("projectSubsidiary: ",projectSubsidiary)
log.debug("taskArr: ",taskArr)
log.debug("count: ",count)
if (count.length > 0) {
for (var i = 0; i < count.length; i++) {
var taskId = count[i].taskId
var genericEmp = count[i].genericEmp
var plannedHrs = count[i].plannedHrs
var unitPrice = count[i].unitPrice
var billingClass = count[i].billingClass
var isVendor = count[i].isVendor
var allocationList = []
var allocationEmpList = []
var vendorList = [];
var filteredList = []
allocationEmpList.push(genericEmp)
allocationList.push({
empId: genericEmp,
empType: 'Generic Resource'
})
if (isVendor == 'T') {
vendorList = vendorSearch(projectSubsidiary, billingClass)
if (vendorList.length > 0) {
for (var j = 0; j < vendorList.length; j++) {
allocationEmpList.push(vendorList[j].empId)
allocationList.push({
empId: vendorList[j].empId,
empType: 'Vendor'
})
}
}
}
var employeeList = employeeSearch(projectSubsidiary, billingClass)
if (employeeList.length > 0) {
for (var j = 0; j < employeeList.length; j++) {
allocationEmpList.push(employeeList[j].empId)
allocationList.push({
empId: employeeList[j].empId,
empType: 'Employee'
})
}
}
if (checkForParameter(taskId) == true) {
if (allocationEmpList.length > 0) {
var rec = record.load({
type: record.Type.PROJECT_TASK,
id: taskId,
isDynamic: true
})
var gLine = rec.getLineCount({
sublistId: 'assignee'
})
var resourceList = []
for (var l = 0; l < gLine; l++) {
var res = rec.getSublistValue({
sublistId: 'assignee',
fieldId: 'resource',
line: l
})
resourceList.push(res)
}
log.debug("resourceList: ", resourceList)
for (var x = 0; x < allocationEmpList.length; x++) {
if (!resourceList.includes(allocationEmpList[x])) {
filteredList.push({
empId: allocationList[x].empId,
empType: allocationList[x].empType
})
}
}
log.debug("filteredList: ", filteredList)
if (filteredList.length > 0) {
for (var k = 0; k < filteredList.length; k++) {
rec.selectNewLine({
sublistId: 'assignee'
})
rec.setCurrentSublistValue({
sublistId: 'assignee',
fieldId: 'resource',
value: filteredList.length > 0 ? filteredList[k].empId : ''
})
rec.setCurrentSublistValue({
sublistId: 'assignee',
fieldId: 'plannedwork',
value: ((filteredList && filteredList.length > 0) && (filteredList[k].empType == 'Generic Resource')) ? Number(plannedHrs) : Number(0)
})
rec.setCurrentSublistValue({
sublistId: 'assignee',
fieldId: 'unitcost',
value: unitPrice
})
rec.setCurrentSublistValue({
sublistId: 'assignee',
fieldId: 'units',
value: 100.0
})
rec.setCurrentSublistValue({
sublistId: 'assignee',
fieldId: 'serviceitem',
value: 57
})
rec.setCurrentSublistValue({
sublistId: 'assignee',
fieldId: 'unitprice',
value: Number(unitPrice)
})
rec.commitLine({
sublistId: 'assignee'
})
}
rec.save()
if (checkForParameter(projectId) == true) {
var prjRec = record.load({
type: record.Type.JOB,
id: projectId,
isDynamic: true
})
prjRec.setValue({
fieldId: 'allowallresourcesfortasks',
value: false
})
prjRec.save()
prjPref = prjRec.getValue({
fieldId: 'allowallresourcesfortasks'
})
log.debug("prjPref: ", prjPref)
}
}
}
}
}
scriptContext.response.write(JSON.stringify({
status: "SUCCESS",
message: prjPref
}));
}
}
}
catch (e) {
log.debug("Error: ",e.name+" : "+e.message)
}
}
return {onRequest}
});
Output

