Markus Kraus
Kilo Sage

Want this?

find_real_file.png

Please fork the following GitHub repository:

https://github.com/kr4uzi/ServiceNow-Portal-Approval

Note: As this scoped app does not add neither tables nor fields, you are "safe" in licensing terms.

 

Then create a new scoped app by importing from git using the newly created repository. 

 

The PopUp behaviour can be configured using the system properties provided by the scoped app:

68747470733a2f2f692e696d6775722e636f6d2f386e30794d44652e706e67.png

Comments
Padmini5
Tera Contributor

Would like to display comments box only when state is rejected not when it is approved. WHat code lines to be changed ?

Markus Kraus
Kilo Sage

Replace the client controller with:

api.controller=function(spModal, spUtil, spUIActionsExecuter, $q) {
	var c = this;
	var approvalInProgress = false;
	var targetScope;
	var ESIGNATURE_PARAMS;
	var ESIGNATURE = {
		'approved': 'cbfe291147220100ba13a5554ee4904d',
		'rejected': '580f711147220100ba13a5554ee4904b'
	};

	c.init = function (targetElement) {
		targetScope = targetElement.scope();		
		targetScope.approve = handleApproval.bind(c, 'approved');
		targetScope.reject = handleApproval.bind(c, 'rejected');
		if (targetScope.data.esignature) {
			ESIGNATURE_PARAMS = {
				username: targetScope.data.esignature.username,
				userSysId: targetScope.data.esignature.userSysId
			};
		}
		
		// only relevant for Widget 'Approval Info' (/sp?id=approval&sys_id=...)
		if (targetScope.c) {
			targetScope.c.action = function (action) {
				handleApproval(action, targetScope.data.sys_id, targetScope.data.esignature.e_sig_required);
			};
		}
	};

	function handleApproval(action, sys_id, requireEsignatureApproval) {
		if (approvalInProgress) {
			return;
		}
		
		approvalInProgress = true;
		(action == 'approved' ? $q.resolve() : spModal.open({
			title: action == 'approved' ? 'Approve' : 'Reject',
			message: 'Please provide a comment for this approval',
			input: true
		})).then(function (comment) {
			if (requireEsignatureApproval) {
				return spUIActionsExecuter.executeFormAction(ESIGNATURE[action], 'sysapproval_approve' , sys_id, [{ name: 'comments', value: comment }] , '', ESIGNATURE_PARAMS);
			} else {
				return c.server.get({ 
					action: action,
					sys_id: sys_id,
					comment: comment
				}).then(function (response) {
					if (response.data.success) {
						spUtil.update(targetScope);
					} else {
						// if the update fails, the Data Policy or Business Rule will most likely print an error message anyways
						// if you still want to display a message, you can use this:
						// spUtil.addInfoMessage(response.data.message);
					}
				});
			}
		})['finally'](function () {
			approvalInProgress = false;
		});
	}
};

 

Padmini5
Tera Contributor

 

Thanks for your reply. But it didn't work. When I click on Reject the comments box opens up, which is good. When I approve, nothing happens. The record is not getting approved.

 

When I click approve, the record to be approved without requesting comments., The updated code is not requesting comments but also not approving the record.

 

Markus Kraus
Kilo Sage

You have to remove '&& input.comment' in the very first lines of the server controller in order to be able to approve without comment.

Padmini5
Tera Contributor

Thanks Mark. That Worked

lholl
Tera Contributor

In San Diego - followed all steps, Approval widget just disappears?

Markus Kraus
Kilo Sage

@lholl Please check again, i tested the steps and for me it worked even on tokyo.

 

I have a new update however, it requires no setup and it is easier to maintain, as well as easier to configure. Please fork from this git repository and install this custom app:
https://github.com/kr4uzi/ServiceNow-Portal-Approval

Shailesh Jeneka
Tera Contributor

Can we use this for approvals for RITM from the portal? 

Aditi6
Tera Contributor

When I forked above Github code and tried to update comments, it is updating as below :

 

[object Object].

 

Please help.

 

Thank & Regards,
AJ

Markell
Tera Guru

@Markus Kraus first off great work and thank you for sharing.

Is there anyway that this can be made to work with customised widgets? I had to copy the OOTB Widget to make customer requested changes but this solution doesn't seem to work unless I use the OOTB Widget

Markell
Tera Guru

Figured it out Add the Widget sys_id to the link code 👍

Kevin Lübben
Tera Contributor

@Markus Kraus Thank you!

Is there also a way to write the comment into journal of sysapproval_approver and not into the RITM?

 

Thanks for a short hint

Markus Kraus
Kilo Sage

@Kevin Lübben Actually, this is what is happening (please see the Server Side Code in the Widget -> Only the sysapproval_approver record is being touched). There is an OOTB script which is updating the RITM upon approval.

Kachu
Kilo Sage

How can we restrict this feature to have only specific users to comment on the approvals when Approve or Reject?

Markus Kraus
Kilo Sage

@Kachu You would need to modify the approval_inject UI Script:

//...
var commentRequired = isApprove ? config.approve_comment_mandatory : config.reject_comment_mandatory;
// here you need to either modify this line to your needs or you intercept the code at this line with a GlideAjax call
//...
DJayBlackout
Tera Explorer

Hi Markus,

I'm currently trying to get this to work for our Customer Support page, we have external customers come in to approve change requests etc, now I had to change the Access Control for PortalApprovalUtilClient to include snc_external, this enabled the comment pop up to appear, it wasn't without doing this. When testing with a customer account, the pop up appears upon click of Approve/Reject, you input your text and it updates the sysapproval_approver record with the comment, but it does not actually change the status to Approved/Rejected. What do I need to change to make this work for snc_external?

Markus Kraus
Kilo Sage

@DJayBlackout I'd assume this might be an ACL issue on sysapproval_approver -> can you verify that the user has sufficient privileges to approve/reject the record?

The PortalApprovalUtilClient is using a GlideRecordSecure and performs the update on this record, meaning that it is doing the approve/reject in respect to ACLs.

DJayBlackout
Tera Explorer

@Markus Krausyes the user has the sn_esm_user role which i've checked the read and write ACL for sysapproval_approver and that role is included in it.

DJayBlackout_0-1709200293427.png

 

Markus Kraus
Kilo Sage

@DJayBlackout I suspect 99% that the reason for this is that the PortalApprovalUtilClient has an ACL which prevents externals from accessing it.

Please sync your fork. Then open the app in the studio and select "Source Control > Apply Remote Changes" to import the ACL modification (i've actually only added sn_esm_user to the ACL of the Script Include).

DJayBlackout
Tera Explorer

@Markus Kraus I feel like we're getting somewhere, thank you for your help so far.

 

As you can see from the screenshot of the widget below, its updating the record but not moving the state?

DJayBlackout_0-1709636214370.png

 

Markus Kraus
Kilo Sage

@DJayBlackout I think i've figured out whats wrong: Please take a look at
/nav_to.do?uri=sys_security_acl.do?sys_id=476967a60a0a0b0c0019e98fbc0a83d8

The write-ACL for sysapproval_approver.state is configured for snc_internal only (even with CSM installed). 
You need to add sn_esm_user here:

MarkusKraus_0-1709645772137.png

 

DJayBlackout
Tera Explorer

@Markus Krausamazing stuff it works, thank you so much for your help.

Version history
Last update:
‎03-18-2023 09:44 AM
Updated by:
Contributors