User event script:
/**
* @NApiVersion 2.1
* @NScriptType UserEventScript
*/
define([‘N/currentRecord’, ‘N/record’, ‘N/search’, ‘N/runtime’, ‘N/ui/serverWidget’],
/**
* @param{currentRecord} currentRecord
* @param{record} record
* @param{search} search
* @param{runtime} runtime
*/
(currentRecord, record, search, runtime, serverWidget) => {
/**
* Defines the function definition that is executed before record is loaded.
* @param {Object} scriptContext
* @param {Record} scriptContext.newRecord – New record
* @param {string} scriptContext.type – Trigger type; use values from the context.UserEventType enum
* @param {form1} scriptContext.form – Current form
* @param {ServletRequest} scriptContext.request – HTTP request information sent from the browser for a client action only.
* @since 2015.2
*/
const beforeLoad = (scriptContext) => {
try {
let form1 = scriptContext.form;
form1.clientScriptFileId = 4;
let currentRecordObj = scriptContext.newRecord;
let currentUser = runtime.getCurrentUser();
let userId = currentUser.id;
let userRole = currentUser.role;
let creatorId = currentRecordObj.getValue({
fieldId: ‘custentity_jj_created_user’
});
let creatorRole = currentRecordObj.getValue({
fieldId: ‘custentity_jj_user_role’
});
let approvalStatus = currentRecordObj.getValue({
fieldId: ‘custentity_jj_approvalstatus’
});
let isinactiveField = form1.getField({
id: ‘isinactive’
});
isinactiveField.updateDisplayType({
displayType: serverWidget.FieldDisplayType.DISABLED
});
if (userId == creatorId && scriptContext.type === ‘view’) {
form1.addButton({
id: ‘custpage_bn_submit for approval’,
label: ‘SUBMIT FOR APPROVAL ‘,
functionName: `submitApprove(‘${creatorId}‘,’${creatorRole}‘,’${approvalStatus}‘)`
});
}
if (approvalStatus == 3 || approvalStatus == 2) {
if (userId == creatorId) {
form1.removeButton(‘custpage_bn_submit for approval’);
}
}
if (userRole == creatorRole && userId != creatorId) {
if (scriptContext.type === ‘view’) {
form1.addButton({
id: ‘custpage_bn_approve’,
label: ‘APPROVE ‘,
functionName: ‘onButtonClick()’
});
form1.addButton({
id: ‘custpage_bn_reject’,
label: ‘REJECT’,
functionName: `onRejectButtonClick(‘${creatorId}‘)`
});
form1.addButton({
id: ‘custpage_bn_resubmit’,
label: ‘REJECT AND RESUBMIT ‘,
functionName: `onResubmitButtonClick(‘${creatorId}‘)`
});
}
}
}
catch (error) {
log.error(‘Error in Before load:’, error);
}
}
/**
* Defines the function definition that is executed before record is submitted.
* @param {Object} scriptContext
* @param {Record} scriptContext.newRecord – New record
* @param {Record} scriptContext.oldRecord – Old record
* @param {string} scriptContext.type – Trigger type; use values from the context.UserEventType enum
* @since 2015.2
*/
const beforeSubmit = (scriptContext) => {
try {
let currentUser = runtime.getCurrentUser();
let userId = currentUser.id;
let userRole = currentUser.role;
let currentRecord = scriptContext.newRecord;
if (scriptContext.type === ‘create’) {
currentRecord.setValue({
fieldId: ‘custentity_jj_created_user’,
value: userId
});
currentRecord.setValue({
fieldId: ‘custentity_jj_user_role’,
value: userRole
});
currentRecord.setValue({
fieldId: “isinactive”,
value: true,
});
}
}
catch (error) {
log.error(‘Error in Before submit:’, error);
}
}
/**
* Defines the function definition that is executed after record is submitted.
* @param {Object} scriptContext
* @param {Record} scriptContext.newRecord – New record
* @param {Record} scriptContext.oldRecord – Old record
* @param {string} scriptContext.type – Trigger type; use values from the context.UserEventType enum
* @since 2015.2
*/
const afterSubmit = (scriptContext) => {
}
return { beforeLoad, beforeSubmit, afterSubmit }
});
client script :
/**
* @NApiVersion 2.1
* @NScriptType ClientScript
* @NModuleScope SameAccount
*/
define([‘N/currentRecord’, ‘N/record’, ‘N/search’, ‘N/email’],
/**
* @param{currentRecord} currentRecord
* @param{record} record
*/
function (currentRecord, record, search, email) {
/**
* Function to be executed after page is initialized.
*
* @param {Object} scriptContext
* @param {Record} scriptContext.currentRecord – Current form record
* @param {string} scriptContext.mode – The mode in which the record is being accessed (create, copy, or edit)
*
* @since 2015.2
*/
function pageInit(scriptContext) {
}
/**
* Function to fetch employee details based on user role and excluding given user ID.
* @param {number} userId – ID of the user to exclude from search.
* @param {string} userRole – Role of the user to filter employee search.
* @returns {Array} – Array of objects containing employee details (internalId and name).
*/
function getEmployee(userId, userRole) {
try {
let employeeSearchObj = search.create({
type: “employee”,
filters:
[
[“role”, “anyof”, userRole],
“AND”,
[“internalid”, “noneof”, userId]
],
columns:
[
search.createColumn({ name: “entityid”, label: “Name” }),
search.createColumn({ name: “internalid”, label: “Internal ID” }),
]
});
let searchResultCount = employeeSearchObj.runPaged().count;
if (searchResultCount <= 0) return false;
let employeeDetailsArray = [];
employeeSearchObj.run().each(function (result) {
let employeeObj = {};
employeeObj.internalId = result.getValue({
name: “internalid”,
label: “Internal ID”,
});
employeeObj.name = result.getValue({ name: “entityid”, label: “Name” });
employeeDetailsArray.push(employeeObj);
return true;
});
log.debug(“employee details”, employeeDetailsArray);
return employeeDetailsArray;
}
catch (e) {
log.debug(‘Error@EmployeeSearch’, e)
return [];
}
}
/**
* Function to fetch record details and generate link based on record type.
* @param {number} recid – ID of the record to fetch details.
* @returns {Array} – Array of objects containing link and record type.
*/
function recordSearch(recid) {
try {
let entityType;
let entitySearchObj = search.create({
type: “entity”,
filters: [
[“internalid”, “anyof”, recid]
],
columns: [
search.createColumn({
name: “formulatext”,
formula: “CASE WHEN {type} = ‘Customer’ THEN (‘https://8314533-rp.app.netsuite.com/app/common/entity/custjob.nl?id=’||{internalid}) WHEN {type} = ‘Vendor’ THEN (‘https://8314533-rp.app.netsuite.com/app/common/entity/vendor.nl?id=’||{internalid}) ELSE ‘Invalid Record Type’ END”,
label: “Link to Entity”
}),
search.createColumn({ name: “type”, label: “Primary Type (Deprecated)” })
]
});
let searchResult = entitySearchObj.run().getRange({
start: 0,
end: 1
});
if (!searchResult || searchResult.length === 0) return false;
let recordlinkArray = [];
searchResult.forEach(function (result) {
let link = result.getValue({
name: “formulatext”,
label: “Link”
});
let eType = result.getValue({
name: “type”,
label: “Primary Type (Deprecated)”
});
if (eType === “CustJob”) {
entityType = “customer”
recordlinkArray.push({ link: link, entityType: entityType })
}
else {
entityType = result.getValue({
name: “type”,
label: “Primary Type (Deprecated)”
});
recordlinkArray.push({ link: link, entityType: entityType })
}
});
//log.debug(“recarray”, recordlinkArray);
return recordlinkArray;
} catch (e) {
log.debug(‘Error@record Search’, e)
return [];
}
}
/**
* Function to submit approval status and notify users accordingly.
* @param {number} creatorId – ID of the creator.
* @param {string} creatorRole – Role of the creator.
* @param {number} approvalStatus – Approval status (1 for approve, 5 for resubmit).
*/
function submitApprove(creatorId, creatorRole, approvalStatus) {
try {
let currentRecordObj = currentRecord.get();
let recid = currentRecordObj.id;
let recResult = recordSearch(recid);
let reclink = recResult[0].link;
let recType = recResult[0].entityType;
let employeeResult = getEmployee(creatorId, creatorRole);
if (employeeResult && reclink && approvalStatus == 1) {
for (let j = 0; j < employeeResult.length + 1; j++) {
if (employeeResult[j]) {
let emailContent = “Dear “ +
employeeResult[j].name + “,<br/><br/>” + “A New Record has been created with inactive status. Approve the Record to come to active status.” + “<br>”
+ ‘<br>Please click “Approve Record” to navigate to the Record page.</p><a href=”‘ + reclink + ‘” style=”display: inline-block; padding: 10px 10px; background-color:#39e600; color:#FFFFFF; border-radius: 10px; text-align: center; text-decoration: none; font-size: 14px; cursor: pointer;”>Approve Record</a><p>Thank you</p>’
email.send({
author: 11,
recipients: 11, // Assuming you have valid recipient IDs here
subject: ‘New Record has been created’,
body: emailContent,
});
}
}
}
if (!approvalStatus || approvalStatus == 1) {
record.submitFields({
type: recType,
id: recid,
values: {
custentity_jj_approvalstatus: 1
},
options: {
ignoreMandatoryFields: true
}
});
window.location.reload();
} else {
record.submitFields({
type: recType,
id: recid,
values: {
custentity_jj_approvalstatus: 5 // Or the appropriate status code for rejection
},
options: {
ignoreMandatoryFields: true
}
});
window.location.reload();
if (approvalStatus == 5) {
for (let j = 0; j < employeeResult.length + 1; j++) {
if (employeeResult[j]) {
let emailContent = “Dear “ +
employeeResult[j].name + “,<br/><br/>” + “Record has been resubmitted for approval.” + “<br>”
+ ‘<br>Please review the record by clicking the below button.</p>’ + “<br/><br/>” + ‘<a href=”‘ + reclink + ‘” style=”display: inline-block; padding: 10px 10px; background-color:#39e600; color:#FFFFFF; border-radius: 10px; text-align: center; text-decoration: none; font-size: 14px; cursor: pointer;”>Resubmitted Record</a>’ + “<br/><br/>” + ‘Thank you.’;
email.send({
author: 11,
recipients: 11, // Assuming you have valid recipient IDs here
subject: ‘ Record has been Resubmitted for the Approval’,
body: emailContent,
});
}
}
}
}
}
catch (error) {
log.error(‘Error in submitApprove function:’, error);
}
}
/**
* Function to handle button click event.
*/
function onButtonClick() {
try {
let currentRecordObj = currentRecord.get();
let recid = currentRecordObj.id;
let recResult = recordSearch(recid);
let recType = recResult[0].entityType;
record.submitFields({
type: recType,
id: recid,
values: {
custentity_jj_approvalstatus: 2,
isinactive: false
},
options: {
ignoreMandatoryFields: true
}
});
window.location.reload();
}
catch (error) {
log.error(‘Error in onButton click function:’, error);
}
}
/**
* Function to handle button click event.
*/
function onRejectButtonClick(creatorId) {
try {
let currentRecordObj = currentRecord.get();
let recid = currentRecordObj.id;
let recResult = recordSearch(recid);
let reclink = recResult[0].link;
let recType = recResult[0].entityType;
let employeeLookup = search.lookupFields({
type: search.Type.EMPLOYEE,
id: creatorId,
columns: ‘entityid’
});
let employeeName = employeeLookup.entityid;
if (creatorId) {
let emailContent = “Dear “ +
employeeName + “,<br/><br/>” + “Record has been Rejected by the Approver.” + “<br>”
+ ‘<br>Please check the record by clicking the below button.</p>’ + “<br/><br/>” + ‘<a href=”‘ + reclink + ‘” style=”display: inline-block; padding: 10px 10px; background-color:#39e600; color:#FFFFFF; border-radius: 10px; text-align: center; text-decoration: none; font-size: 14px; cursor: pointer;”>Rejected Record</a>’ + “<br/><br/>” + ‘Thank you.’
email.send({
author: 11,
recipients: 11,
subject: recType + ‘ Record has been Rejected’,
body: emailContent,
});
}
record.submitFields({
type: recType,
id: recid,
values: {
custentity_jj_approvalstatus: 3,
isinactive: true
},
options: {
ignoreMandatoryFields: true
}
});
window.location.reload();
}
catch (error) {
log.error(‘Error while updating approval status:’, error);
}
}
/**
* Function to handle button click event for rejecting a record.
* @param {number} creatorId – ID of the creator.
*/
function onResubmitButtonClick(creatorId) {
try {
let currentRecordObj = currentRecord.get();
let recid = currentRecordObj.id;
let recResult = recordSearch(recid);
let reclink = recResult[0].link;
let recType = recResult[0].entityType;
let employeeLookup = search.lookupFields({
type: search.Type.EMPLOYEE,
id: creatorId,
columns: ‘entityid’
});
let employeeName = employeeLookup.entityid;
if (creatorId) {
let emailContent = “Dear “ +
employeeName + “,<br/><br/>” + “Record has been rejected for resubmited by the Approver.” + “<br>”
+ ‘<br>Please check the record by clicking the below button and submit again for approval.</p>’ + “<br/><br/>” + ‘<a href=”‘ + reclink + ‘” style=”display: inline-block; padding: 10px 10px; background-color:#39e600; color:#FFFFFF; border-radius: 10px; text-align: center; text-decoration: none; font-size: 14px; cursor: pointer;”>Rejected Record</a>’ + “<br/><br/>” + ‘Thank you.’
email.send({
author: 11,
recipients: 11,
subject: ‘ Record has been Rejected for Resubmit’,
body: emailContent,
});
} record.submitFields({
type: recType,
id: recid,
values: {
custentity_jj_approvalstatus: 4,
isinactive: true
},
options: {
ignoreMandatoryFields: true
}
});
window.location.reload();
}
catch (e) {
log.error(‘Error while updating approval status:’, e);
}
}
return {
pageInit: pageInit,
onButtonClick: onButtonClick,
submitApprove: submitApprove,
onRejectButtonClick: onRejectButtonClick,
onResubmitButtonClick: onResubmitButtonClick,
};
});