We've updated the ServiceNow Community Code of Conduct, adding guidelines around AI usage, professionalism, and content violations. Read more

Make comment mandatory when rejecting an approval on service portal

Gab
Tera Expert

We have a requirement to make the comment mandatory when rejecting an approval in Service Portal. I've already see Portal diaries: Service Portal — Making Rejection Comments Mandatory on Approval Record this thread but the problem is I don't know how to apply this on a Scope Application and also the comment is being duplicated.

How do you require a comment whenever these buttons below are clicked?

find_real_file.png

 

find_real_file.png

I'm using Rome version

1 ACCEPTED SOLUTION

Service_RNow
Mega Sage

Please Try this below code:

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

16 REPLIES 16

@Gab 

I already shared you the link for the solution.

How to make rejection comments mandatory on Service Portal

The answer marked as correct copies the same script i.e. Client Controller + Server side + Screenshots/Demo from the link I already shared 3 days ago.

Did you mistakenly marked other response as correct?

Please mark appropriate response as correct based on timely response.

find_real_file.png

Regards
Ankur

Regards,
Ankur
Certified Technical Architect  ||  10x ServiceNow MVP  ||  ServiceNow Community Leader

Raghu Ram Y
Kilo Sage

Hi @Gab 

I will share some similar approach.. modify ur code according to that...

HTML

<div>
<button type="button" ng-click = "c.reject()" class="btn btn-danger pull-right" >Reject</button>
</div>

Client Controller

c.reject = function(){
c.data.action2 = 'rejected';
spModal.open({
            title: 'Comments are mandatory while rejecting the approval',
            message: 'Enter the reason for rejecting the approval',
            input: true,
            value: c.name
        }).then(function(name) {
         c.data.action3 = name;
	 c.server.update();
	 spUtil.addErrorMessage("Rejected");
    })

Server Script

if(input.action2 == 'rejected'){
	var getSysidd =  $sp.getParameter("sys_id");
	var gr1 = new GlideRecord('sysapproval_approver');
	gr1.addQuery('sys_id', getSysidd);
	gr1.query();
	if(gr1.next())
	{
		gr1.state = 'rejected';
		gr1.comments = input.action3;
		gr1.update();
	}
}

Which widget is this? Do i have to clone it from my scoped application?

Nope, it's not OOB...custom one which I have created...

It works..

 

@Gab wasn't my solution found helpful?