How to make rejection comments mandatory on Service Portal

kashifansari07
Tera Expert

On the Approval for a record, i need the rejection comments mandatory on Portal. Same is achieved by cloning the Approval info widget with the below code. However i need it to be consistent on portal on the index page containing Approvals widget. can any one help me with the requirement.

Code for Approval info widget is below(Paris release):

Server Side :

(function() {
	data.actionPreventedMsg = gs.getMessage("Update failed");
	var gr = $sp.getRecord();
	if (gr == null || !gr.isValid()) {
		data.isValid = false;
		return;
	}

	data.isValid = true;
	data.isMine = isApprovalMine(gr);

	var approverDisplay = gr.approver.getDisplayValue();
	if (!data.isMine && approverDisplay)
		data.approverDisplay = approverDisplay;

	if (approverDisplay) {
		data.approvedMsg = gs.getMessage("Approved by {0}", approverDisplay);
		data.rejectedMsg = gs.getMessage("Rejected by {0}", approverDisplay);
	} else {
		data.approvedMsg = gs.getMessage("Approved");
		data.rejectedMsg = gs.getMessage("Rejected");
	}
	if (input && input.op && data.isMine) {
		gr.state = input.op;
		if (gr.state == "rejected") {
			gr.comments = "Requested Item rejected by "+gs.getUserDisplayName()+" via Service Portal \nRejected with comments: "+ input.comments; //Custom code (DFCT0010123)
		}
		data.updateID = gr.update();
		if (GlideStringUtil.nil(data.updateID)) {
			// update failed so fetch again for correct values
			gr = $sp.getRecord();
		}
		data.op = "";
	}

	var fields = $sp.getFields(gr, 'state,sys_created_on');

	if (gr.sys_mod_count > 0)
		fields.push($sp.getField(gr, 'sys_updated_on'));

	data.fields = fields;
	data.state = gr.state.toString();
	data.sys_updated_on = gr.sys_updated_on.toString();
	data.sys_id = gr.getUniqueValue();
	data.table = gr.getTableName();
	data.label = getRecordBeingApproved(gr).getLabel();
	data.esignature = {
		username:  gs.getUserName(),
		userSysId: gs.getUserID(),
		e_sig_required: checkESig(gr)
	};
	function checkESig(approvalGR) {
		var esigRegistryGR = new GlideRecord("e_signature_registry");
		if (!esigRegistryGR.isValid())
			return false;

		var table = approvalGR.getValue("source_table");
		if (!table)
			table = approvalGR.sysapproval.sys_class_name;
		if (!table)
			return false;

		esigRegistryGR.addQuery("enabled", "true");
		esigRegistryGR.addQuery("table_name", table);
		esigRegistryGR.query();
		return esigRegistryGR.hasNext();
	}

	function getRecordBeingApproved(gr) {
		if (!gr.sysapproval.nil())
			return gr.sysapproval.getRefRecord();

		return gr.document_id.getRefRecord();
	}
})();

 

 

Client Controller :

 

function ($scope, spUIActionsExecuter, spUtil, spModal) {
	var c = this;

	var ESIGNATURE = {
		"approved": "cbfe291147220100ba13a5554ee4904d",
		"rejected": "580f711147220100ba13a5554ee4904b"
	};

	spUtil.recordWatch($scope, "sysapproval_approver", "state=requested^sys_id="+ c.data.sys_id);

	c.action = function(state) {
		if(c.data.esignature.e_sig_required) {
			var requestParams = {
				username: c.data.esignature.username,
				userSysId: c.data.esignature.userSysId
			};
			spUIActionsExecuter.executeFormAction(ESIGNATURE[state], "sysapproval_approver" , c.data.sys_id, [] , "", requestParams).then(function(response) {
			});
		} else {	
			if (state == "rejected") {
				spModal.prompt("Provide a reason for rejecting this approval").then(function(newComments) {
					c.data.comments = newComments;
					c.data.op = state;
					c.server.update().then(function() {
						if (!c.data.updateID) // update failed
							spUtil.addErrorMessage(c.data.actionPreventedMsg);
						else
							c.data.state = state;
					});
				});
			}
			else 
			{
				c.data.op = state;
				c.server.update().then(function() {
					if (!c.data.updateID) // update failed
						spUtil.addErrorMessage(c.data.actionPreventedMsg);
					else
						c.data.state = state;
				});
			}
		}
	}	
}

 

1 ACCEPTED SOLUTION

Try now

 

Client Controller:

 

function ($scope, spUtil, spUIActionsExecuter, spModal) {
	var ESIGNATURE = {
		TYPE: "form",
		APPROVE_SYS: "cbfe291147220100ba13a5554ee4904d",
		REJECT_SYS: "580f711147220100ba13a5554ee4904b"
	};

	if ($scope.options.portal == true || $scope.options.portal == 'true') {
		$scope.contentColClass = "col-xs-12";
		$scope.options.portal = true;
	} else {
		$scope.options.portal = false;
		$scope.contentColClass = "col-sm-8";
	}

	$scope.data.op = "";
	spUtil.recordWatch($scope, "sysapproval_approver", "state=requested^approverIN" + $scope.data.myApprovals.toString(), function(data) {
		// don't double-roundtrip if update came from record just approved/rejected
		if (data.data.sys_id != $scope.data.target)
			spUtil.update($scope);
	});

	function get() {
		spUtil.update($scope);
	}

	$scope.approve = function(id, esigRequired) {
		var requestParams = {
			username: $scope.data.esignature.username,
			userSysId: $scope.data.esignature.userSysId
		};

		if($scope.data.esignature.e_sig_required && esigRequired) {
			spUIActionsExecuter.executeFormAction(ESIGNATURE.APPROVE_SYS, "sysapproval_approver" , id, [] , "", requestParams).then(function(response) {
			});			
		} else {
			$scope.data.op = "approved";
			$scope.data.target = id;
			get();
		}
	}

	$scope.reject = function(id, esigRequired) {

		spModal.open({
			title: 'Reject Approval',
			message: 'Provide a reason for rejecting this approval',
			input: true,
			value: $scope.name
		}).then(function(name) {
			$scope.name = name;

			var requestParams = {
				username: $scope.data.esignature.username,
				userSysId: $scope.data.esignature.userSysId
			};

			if($scope.data.esignature.e_sig_required && esigRequired) {
				spUIActionsExecuter.executeFormAction(ESIGNATURE.REJECT_SYS, "sysapproval_approver" , id, [] , "", requestParams).then(function(response) {
				});
			} else {
				$scope.data.op = "rejected";
				$scope.data.target = id;
				$scope.data.reject_comment = "Rejection reason: " + $scope.name;
				get();
			}
		});
	};

	// pagination
	$scope.previousPage = function() {
		if ($scope.data.pagination.currentPage > 1)
			$scope.data.pagination.currentPage = $scope.data.pagination.currentPage - 1;
		else
			$scope.data.pagination.currentPage = 0;

		get();
	}

	$scope.nextPage = function() {
		$scope.data.pagination.currentPage = $scope.data.pagination.currentPage+1;
		get();
	}

	$scope.getItemDisplay = function(task) {
		if (task.number && task.short_description)
			return task.number + " - " + task.short_description;

		return task.number || task.short_description || "";
	}
}

 

Server Side:

 

g_approval_form_request = true;

//we get only a max number of elements to avoid to have a big list of it
var maxNumberOfItemsInTheList = parseInt(options.max_number_of_elements_shown_on_the_list);
//set 10 if maxnumber is undefined, empty or negative value
maxNumberOfItemsInTheList = maxNumberOfItemsInTheList>0 ? maxNumberOfItemsInTheList : 10; 
var initRow = 0;
var lastRow = maxNumberOfItemsInTheList;
var currentPage = 0; //0 is the first page
if (input) {
	// update pagination
	currentPage = input.pagination.currentPage;
	initRow = (currentPage * maxNumberOfItemsInTheList);
	lastRow = initRow + maxNumberOfItemsInTheList;

	if (input.op == 'approved' || input.op == 'rejected') {
		var app = new GlideRecord("sysapproval_approver");
		if (app.get(input.target)) {
			app.state = input.op;
			if(input.op == 'rejected'){
				app.comments = input.reject_comment;
			}

			app.update();

		}
	}
}

data.ViewApprovalPageMsg = gs.getMessage("View approval page");
data.esignature = {
	username:  gs.getUserName(),
	userSysId: gs.getUserID(),
	e_sig_required: GlidePluginManager.isRegistered('com.glide.e_signature_approvals')
};

var esigRequiredMap = {};
if (data.esignature.e_sig_required) {
	var esigRegistryGR = new GlideRecord("e_signature_registry");
	esigRegistryGR.addQuery("enabled", "true");
	esigRegistryGR.query();
	while(esigRegistryGR.next()) {
		esigRequiredMap[esigRegistryGR.getValue("table_name")] = true;
	}
}

var gr = new GlideRecord('sysapproval_approver');
gr.chooseWindow(initRow, lastRow);
var qc1 = gr.addQuery("state", "requested");
//if (input)
//  qc1.addOrCondition("sys_id", "IN", input.ids);
data.myApprovals = getMyApprovals();
gr.addQuery("approver", data.myApprovals);
gr.orderBy("sys_created_on");
gr.query();
var rowCount = gr.getRowCount();
var approvals = [];
var ids = [];
var source_tables = [];

while (gr.next()) {
	var task = getRecordBeingApproved(gr);
	if (!task.isValidRecord())
		continue;

	ids.push(gr.getUniqueValue());
	var t = {};
	t.number = task.getDisplayValue();
	t.short_description = task.short_description.toString();
	if (gr.getValue("approver") != gs.getUserID())
		t.approver = gr.approver.getDisplayValue();
	if (task.isValidField("opened_by") && !task.opened_by.nil())
		t.opened_by = task.opened_by.getDisplayValue();

	// requestor >> opener
	if (task.isValidField("requested_by") && !task.requested_by.nil())
		t.opened_by = task.requested_by.getDisplayValue();

	t.start_date = task.start_date.getDisplayValue();
	t.end_date = task.end_date.getDisplayValue();
	t.quantity = task.quantity.getDisplayValue();
	t.table = task.getLabel();
	if (task.getValue("price") > 0)
		t.price = task.getDisplayValue("price");

	if (task.getValue("recurring_price") > 0)
		t.recurring_price = task.getDisplayValue("recurring_price");

	t.recurring_frequency = task.getDisplayValue("recurring_frequency");

	var items = [];
	var idx = 0;
	var itemsGR = new GlideRecord("sc_req_item");
	itemsGR.addQuery("request", task.sys_id);
	itemsGR.query();
	if (itemsGR.getRowCount() > 1)
		t.short_description = itemsGR.getRowCount() + " requested items";

	while (itemsGR.next()) {
		var item = {};
		item.short_description = itemsGR.short_description.toString();
		if (itemsGR.getValue("price") > 0)
			item.price = itemsGR.getDisplayValue("price");
		if (itemsGR.getValue("recurring_price") > 0) {
			item.recurring_price = itemsGR.getDisplayValue("recurring_price");
			item.recurring_frequency = itemsGR.getDisplayValue("recurring_frequency");
		}
		if (itemsGR.getRowCount() == 1) {
			item.variables = new GlobalServiceCatalogUtil().getVariablesForTask(itemsGR, true);
			item.variableSummarizerWidget = $sp.getWidget('sc-variable-summarizer', {'variables' : item.variables, 'toggle' : false, 'task' :t.number });
			t.short_description = itemsGR.short_description.toString();
		}

		items[idx] = item;
		idx++;
	}

	var j = {};
	j.sys_id = gr.getUniqueValue();
	j.table = gr.getRecordClassName();
	j.approval_source_table = gr.getValue("source_table");
	if (!j.approval_source_table)
		j.approval_source_table = gr.sysapproval.sys_class_name + "";
	j.requireEsigApproval = esigRequiredMap[j.approval_source_table];
	j.task = t;
	if (task) {
		j.variables = new GlobalServiceCatalogUtil().getVariablesForTask(task, true);
		j.variableSummarizerWidget = $sp.getWidget('sc-variable-summarizer', {'variables' : j.variables, 'toggle' : false, 'task': t.number });
	}
	j.items = items;
	j.state = gr.getValue("state");
	j.stateLabel = gr.state.getDisplayValue();
	approvals.push(j);
}

data.ids = ids;
data.approvals = approvals;
data.showApprovals = gs.getUser().hasRole('approver_user');
// for pagination
data.pagination = {};
data.pagination.hasNext = (approvals.length == (parseInt(lastRow) - parseInt(initRow)) && lastRow < rowCount);
data.pagination.hasPrevious = parseInt(initRow) > 0;
data.pagination.from = parseInt(initRow + 1);
data.pagination.to = parseInt(lastRow) < parseInt(rowCount) ? parseInt(lastRow) : parseInt(rowCount);
data.pagination.of = parseInt(rowCount);
data.pagination.showPagination = data.pagination.hasPrevious || data.pagination.hasNext;
data.pagination.currentPage = data.pagination.from > data.pagination.to ? currentPage -1 : currentPage;
delete g_approval_form_request;
function getRecordBeingApproved(gr) {
	if (!gr.sysapproval.nil())
		return gr.sysapproval.getRefRecord();

	return gr.document_id.getRefRecord();
}


 

 

Adding xml of the widget which i have tried on my personal instance and working fine. 

 

Quick Demo:

 

find_real_file.png

 

If my answer helped you, kindly mark it as correct and helpful.

 

View solution in original post

13 REPLIES 13

hello Thrupthi,

i already reviewed the thread, but its not working for me in my instance. We are currently on Paris release.

I did get help on the Approval info widget for which i included the code above in the question.

I would need help on My Approvals (Approvals widget)so that the functionality of approval is streamlined on the portal with Rejection comments as mandatory.

 

kashifansari07
Tera Expert

@Harshvardhan can you help?

Try now

 

Client Controller:

 

function ($scope, spUtil, spUIActionsExecuter, spModal) {
	var ESIGNATURE = {
		TYPE: "form",
		APPROVE_SYS: "cbfe291147220100ba13a5554ee4904d",
		REJECT_SYS: "580f711147220100ba13a5554ee4904b"
	};

	if ($scope.options.portal == true || $scope.options.portal == 'true') {
		$scope.contentColClass = "col-xs-12";
		$scope.options.portal = true;
	} else {
		$scope.options.portal = false;
		$scope.contentColClass = "col-sm-8";
	}

	$scope.data.op = "";
	spUtil.recordWatch($scope, "sysapproval_approver", "state=requested^approverIN" + $scope.data.myApprovals.toString(), function(data) {
		// don't double-roundtrip if update came from record just approved/rejected
		if (data.data.sys_id != $scope.data.target)
			spUtil.update($scope);
	});

	function get() {
		spUtil.update($scope);
	}

	$scope.approve = function(id, esigRequired) {
		var requestParams = {
			username: $scope.data.esignature.username,
			userSysId: $scope.data.esignature.userSysId
		};

		if($scope.data.esignature.e_sig_required && esigRequired) {
			spUIActionsExecuter.executeFormAction(ESIGNATURE.APPROVE_SYS, "sysapproval_approver" , id, [] , "", requestParams).then(function(response) {
			});			
		} else {
			$scope.data.op = "approved";
			$scope.data.target = id;
			get();
		}
	}

	$scope.reject = function(id, esigRequired) {

		spModal.open({
			title: 'Reject Approval',
			message: 'Provide a reason for rejecting this approval',
			input: true,
			value: $scope.name
		}).then(function(name) {
			$scope.name = name;

			var requestParams = {
				username: $scope.data.esignature.username,
				userSysId: $scope.data.esignature.userSysId
			};

			if($scope.data.esignature.e_sig_required && esigRequired) {
				spUIActionsExecuter.executeFormAction(ESIGNATURE.REJECT_SYS, "sysapproval_approver" , id, [] , "", requestParams).then(function(response) {
				});
			} else {
				$scope.data.op = "rejected";
				$scope.data.target = id;
				$scope.data.reject_comment = "Rejection reason: " + $scope.name;
				get();
			}
		});
	};

	// pagination
	$scope.previousPage = function() {
		if ($scope.data.pagination.currentPage > 1)
			$scope.data.pagination.currentPage = $scope.data.pagination.currentPage - 1;
		else
			$scope.data.pagination.currentPage = 0;

		get();
	}

	$scope.nextPage = function() {
		$scope.data.pagination.currentPage = $scope.data.pagination.currentPage+1;
		get();
	}

	$scope.getItemDisplay = function(task) {
		if (task.number && task.short_description)
			return task.number + " - " + task.short_description;

		return task.number || task.short_description || "";
	}
}

 

Server Side:

 

g_approval_form_request = true;

//we get only a max number of elements to avoid to have a big list of it
var maxNumberOfItemsInTheList = parseInt(options.max_number_of_elements_shown_on_the_list);
//set 10 if maxnumber is undefined, empty or negative value
maxNumberOfItemsInTheList = maxNumberOfItemsInTheList>0 ? maxNumberOfItemsInTheList : 10; 
var initRow = 0;
var lastRow = maxNumberOfItemsInTheList;
var currentPage = 0; //0 is the first page
if (input) {
	// update pagination
	currentPage = input.pagination.currentPage;
	initRow = (currentPage * maxNumberOfItemsInTheList);
	lastRow = initRow + maxNumberOfItemsInTheList;

	if (input.op == 'approved' || input.op == 'rejected') {
		var app = new GlideRecord("sysapproval_approver");
		if (app.get(input.target)) {
			app.state = input.op;
			if(input.op == 'rejected'){
				app.comments = input.reject_comment;
			}

			app.update();

		}
	}
}

data.ViewApprovalPageMsg = gs.getMessage("View approval page");
data.esignature = {
	username:  gs.getUserName(),
	userSysId: gs.getUserID(),
	e_sig_required: GlidePluginManager.isRegistered('com.glide.e_signature_approvals')
};

var esigRequiredMap = {};
if (data.esignature.e_sig_required) {
	var esigRegistryGR = new GlideRecord("e_signature_registry");
	esigRegistryGR.addQuery("enabled", "true");
	esigRegistryGR.query();
	while(esigRegistryGR.next()) {
		esigRequiredMap[esigRegistryGR.getValue("table_name")] = true;
	}
}

var gr = new GlideRecord('sysapproval_approver');
gr.chooseWindow(initRow, lastRow);
var qc1 = gr.addQuery("state", "requested");
//if (input)
//  qc1.addOrCondition("sys_id", "IN", input.ids);
data.myApprovals = getMyApprovals();
gr.addQuery("approver", data.myApprovals);
gr.orderBy("sys_created_on");
gr.query();
var rowCount = gr.getRowCount();
var approvals = [];
var ids = [];
var source_tables = [];

while (gr.next()) {
	var task = getRecordBeingApproved(gr);
	if (!task.isValidRecord())
		continue;

	ids.push(gr.getUniqueValue());
	var t = {};
	t.number = task.getDisplayValue();
	t.short_description = task.short_description.toString();
	if (gr.getValue("approver") != gs.getUserID())
		t.approver = gr.approver.getDisplayValue();
	if (task.isValidField("opened_by") && !task.opened_by.nil())
		t.opened_by = task.opened_by.getDisplayValue();

	// requestor >> opener
	if (task.isValidField("requested_by") && !task.requested_by.nil())
		t.opened_by = task.requested_by.getDisplayValue();

	t.start_date = task.start_date.getDisplayValue();
	t.end_date = task.end_date.getDisplayValue();
	t.quantity = task.quantity.getDisplayValue();
	t.table = task.getLabel();
	if (task.getValue("price") > 0)
		t.price = task.getDisplayValue("price");

	if (task.getValue("recurring_price") > 0)
		t.recurring_price = task.getDisplayValue("recurring_price");

	t.recurring_frequency = task.getDisplayValue("recurring_frequency");

	var items = [];
	var idx = 0;
	var itemsGR = new GlideRecord("sc_req_item");
	itemsGR.addQuery("request", task.sys_id);
	itemsGR.query();
	if (itemsGR.getRowCount() > 1)
		t.short_description = itemsGR.getRowCount() + " requested items";

	while (itemsGR.next()) {
		var item = {};
		item.short_description = itemsGR.short_description.toString();
		if (itemsGR.getValue("price") > 0)
			item.price = itemsGR.getDisplayValue("price");
		if (itemsGR.getValue("recurring_price") > 0) {
			item.recurring_price = itemsGR.getDisplayValue("recurring_price");
			item.recurring_frequency = itemsGR.getDisplayValue("recurring_frequency");
		}
		if (itemsGR.getRowCount() == 1) {
			item.variables = new GlobalServiceCatalogUtil().getVariablesForTask(itemsGR, true);
			item.variableSummarizerWidget = $sp.getWidget('sc-variable-summarizer', {'variables' : item.variables, 'toggle' : false, 'task' :t.number });
			t.short_description = itemsGR.short_description.toString();
		}

		items[idx] = item;
		idx++;
	}

	var j = {};
	j.sys_id = gr.getUniqueValue();
	j.table = gr.getRecordClassName();
	j.approval_source_table = gr.getValue("source_table");
	if (!j.approval_source_table)
		j.approval_source_table = gr.sysapproval.sys_class_name + "";
	j.requireEsigApproval = esigRequiredMap[j.approval_source_table];
	j.task = t;
	if (task) {
		j.variables = new GlobalServiceCatalogUtil().getVariablesForTask(task, true);
		j.variableSummarizerWidget = $sp.getWidget('sc-variable-summarizer', {'variables' : j.variables, 'toggle' : false, 'task': t.number });
	}
	j.items = items;
	j.state = gr.getValue("state");
	j.stateLabel = gr.state.getDisplayValue();
	approvals.push(j);
}

data.ids = ids;
data.approvals = approvals;
data.showApprovals = gs.getUser().hasRole('approver_user');
// for pagination
data.pagination = {};
data.pagination.hasNext = (approvals.length == (parseInt(lastRow) - parseInt(initRow)) && lastRow < rowCount);
data.pagination.hasPrevious = parseInt(initRow) > 0;
data.pagination.from = parseInt(initRow + 1);
data.pagination.to = parseInt(lastRow) < parseInt(rowCount) ? parseInt(lastRow) : parseInt(rowCount);
data.pagination.of = parseInt(rowCount);
data.pagination.showPagination = data.pagination.hasPrevious || data.pagination.hasNext;
data.pagination.currentPage = data.pagination.from > data.pagination.to ? currentPage -1 : currentPage;
delete g_approval_form_request;
function getRecordBeingApproved(gr) {
	if (!gr.sysapproval.nil())
		return gr.sysapproval.getRefRecord();

	return gr.document_id.getRefRecord();
}


 

 

Adding xml of the widget which i have tried on my personal instance and working fine. 

 

Quick Demo:

 

find_real_file.png

 

If my answer helped you, kindly mark it as correct and helpful.