want to make state field editable till one month after ticket is closed only for two users

siva14
Tera Contributor

"we want to make state field editable till one month after ticket is closed only for two users" in incident form, anyone please help how to achieve this 

 

#client script #ACL #business rule

6 REPLIES 6

Bert_c1
Kilo Patron

Hi,

 

I believe it is possible, using a Client script that runs 'onLoad', uses GlideAjax to call a script include. The script include can check for the current user (or passed by the client script), and look at the 'closed_at' field to compare with the current date-time. Return true is less that 30 days and the current user is either of the "two users".  The client script then uses 'g_form.setReadOnly("state", true);'  Both the Client Script and script include need to be defined.

Bert_c1
Kilo Patron
var checkUserForState = Class.create();
checkUserForState.prototype = Object.extendsObject(AbstractAjaxProcessor, {

	checkUser: function() {
        var userID = this.getParameter("sysparm_user_id");
		var incNum = this.getParameter("sysparm_inc_number");
		var result = true;

		// see if we have either of the two users (need sys_id)
		if ((userID != '6816f79cc0a8016401c5a33be04be441') && (userID != '123')) {
			// User is not meant
			return result;
		}

//		gs.info("checkUserForState: userID: " + userID + " inc: " + incNum);
		var inc = new GlideRecord('incident');
		inc.addQuery('number', incNum);
		inc.setLimit(1);
		inc.query();
//		gs.info("checkUserForState: Found " + inc.getRowCount() + " inc records.");
		if (inc.next()) {
			var closeDate = new GlideDateTime(inc.closed_at);
			var now = new GlideDateTime();
//			gs.info("checkUserForState: closed_at: " + closeDate + ", now: " + now);
			var diffSecs = gs.dateDiff(closeDate.getDisplayValue(), now.getDisplayValue(), true);
//			gs.info("checkUserForState: diff seconds: " + diffSecs);
			if (diffSecs < (30*24*60*60))
				// diff is less than 30 days
				result = false;
		}
//		gs.info("checkUserForState: Returning string: " + result);
		return JSON.stringify(result);
    },

    type: 'XUserDetailsAjax'
});

@siva14 ,

 

I was able to get what i proposed working, based on the approach I proposed.  The client script:

 

Screenshot 2024-07-24 180106.png

The script:

 

function onLoad() {

	//Type appropriate comment here, and begin script below
	// check if state is closed
	var incState = g_form.getValue('state');
	if (incState != 7) {
		// state is not closed
		return;
	}
//	alert('incState = ' + incState);
	// call script include to get user data
	var usr = g_user.getUserID();
//	alert('usr='+usr);
	var incNumber = g_form.getValue('number');
	var ga = new GlideAjax('checkUserForState');
	ga.addParam('sysparm_name','checkUser'); // function in the script include we're calling
	ga.addParam('sysparm_user_id', usr);
	ga.addParam('sysparm_inc_number', incNumber);

	/* Call function with user set and use the callback function getResponse() to return the result when ready */
	ga.getXMLAnswer(getResponse);	// when script include returns a string
}

// callback function for returning the result from the script include
function getResponse(response) {
	var result = response;
//	alert('result: ' + result);
	if (result == 'false')
		g_form.setReadOnly('state', false);
}

 

The script include has Client callable enabled, name is checkUserForState, and script:

 

var checkUserForState = Class.create();
checkUserForState.prototype = Object.extendsObject(AbstractAjaxProcessor, {

	checkUser: function() {
        var userID = this.getParameter("sysparm_user_id");
		var incNum = this.getParameter("sysparm_inc_number");
		var result = true;

		// see if we have either of the two users (need sys_id)
		if ((userID != '6816f79cc0a8016401c5a33be04be441') && (userID != '123')) {
			// User is not meant
			return result;
		}

//		gs.info("checkUserForState: userID: " + userID + " inc: " + incNum);
		var inc = new GlideRecord('incident');
		inc.addQuery('number', incNum);
		inc.setLimit(1);
		inc.query();
//		gs.info("checkUserForState: Found " + inc.getRowCount() + " inc records.");
		if (inc.next()) {
			var closeDate = new GlideDateTime(inc.closed_at);
			var now = new GlideDateTime();
//			gs.info("checkUserForState: closed_at: " + closeDate + ", now: " + now);
			var diffSecs = gs.dateDiff(closeDate.getDisplayValue(), now.getDisplayValue(), true);
//			gs.info("checkUserForState: diff seconds: " + diffSecs);
			if (diffSecs < (30*24*60*60))
				// diff is less than 30 days
				result = false;
		}
//		gs.info("checkUserForState: Returning string: " + result);
		return JSON.stringify(result);
		return result;
    },

    type: 'XUserDetailsAjax'
});

 

 Maybe there's is other approaches.

Tai Vu
Kilo Patron
Kilo Patron

Hi @siva14 

In addition to the GlideAjax solution from Bert, you can also leverage the Date object to achieve the date time validation part within the client script.

Sample.

var closedDate = new Date(g_form.getValue('closed_at'));
closedDate.setMonth(closedDate.getMonth() + 1); //1 month later since closed
var uneditableDateTime = formatDate(closedDate, g_user_date_time_format);

var nowDate = new Date();
var nowDateTime = formatDate(nowDate, g_user_date_time_format); //current date time

alert(nowDateTime < uneditableDateTime);

g_form.setReadOnly('state', (nowDateTime < uneditableDateTime));

 

Cheers,

Tai Vu

Bert_c1
Kilo Patron

The above doesn't work for me, as I don't have the 'closed_at' field on the incident form.  So I use GlideAjax to get that.  A change to check for the user in the client script is better, to avoid the server-side transaction.  The following can be added to either client script for that:

 

	// get the user
	var usr = g_user.getUserID();
	// now check if either of the two users
	if ((usr != 'user1_sys_id') && (user != 'user2_sys_id')) {
		return;
	}

Timi's solution can work if line 1 works in the client script.