Approval widgets saving comments twice

Aanchal3
Kilo Contributor

Hello,   

I've updated the Approval Info widget and added a comment field, but when I add a comment and reject or accept a particular approval request, the comments are updated twice. I checked for UI Action, Client Script and others but cant find a solution.

Any suggestion would be appreciated. 

13 REPLIES 13

did you try to put some log in the script? and see where exactly it has stopped . log would be help you to troubleshoot this issue. 

VigneshMC
Mega Sage

can you share the complete widget code?, Also did you check that whether comments aren't duplicating if you add them using normal UI, could be some BR doing that as well.

Thanks

Aanchal3
Kilo Contributor

Hi 

 

HTML 

 

<div ng-if="c.data.isValid" class="panel panel-{{::c.options.color}} b">
<div class="panel-heading">
<h4 class="panel-title" ng-if="c.data.isMine && (c.data.state == 'requested')">${This {{c.data.label}} requires your approval}</h4>
<h4 class="panel-title" ng-if="!c.data.isMine && (c.data.state == 'requested')">${This {{c.data.label}} requires approval <span ng-if="c.data.approver"> by {{c.data.approver}}}</span></h4>
<h4 class="panel-title" ng-if="c.data.state == 'approved'">${Approved} <sn-time-ago timestamp="::c.data.sys_updated_on" /></h4>
<h4 class="panel-title" ng-if="c.data.state == 'rejected'">${Rejected} <sn-time-ago timestamp="::c.data.sys_updated_on" /></h4>
</div>
<div class="panel-body">
<form ng-submit="$event.preventDefault()" class="form-horizontal">
<div ng-if="c.data.fields.length > 0">
<div ng-repeat="field in c.data.fields" class="m-b-xs" ng-if="field.value">
<label class="m-n">{{field.label}}</label>
<span ng-switch="field.type">
<div ng-switch-when="glide_date_time" title="{{field.display_value}}"><sn-time-ago timestamp="::field.value" /></div>
<div ng-switch-default >{{field.display_value}}</div>
</span>
</div>
</div>
<div ng-if="c.data.isMine && (c.data.state == 'requested')" class="question">
<button type="button" name="approve" class="btn btn-success btn-question" ng-click="c.action('approved')">${Approve}</button>
<div class="spacer"></div>
<button type="button" name="reject" class="btn btn-default btn-question" ng-click="c.action('rejected')">${Reject}</button>
<textarea ng-model="c.data.comment" style="color: grey; width: 100%; margin-top: .5em;" placeholder="Comments" class="form-control" rows="5"></textarea>
</div>
</form>
</div>
</div>

 

 

Server Script

 

(function() {
var gr = $sp.getRecord();
if (gr == null || !gr.isValid()) {
data.isValid = false;
return;
}

data.isValid = true;
data.isMine = gr.getValue("approver") == gs.getUserID();

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


if (input && input.op) {
gr.state = input.op;
gr.comments = input.comment; //Code to take input comment- different from OOB
gr.update();
}


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.getValue("source_table"))
};
function checkESig(table) {
var esigRegistryGR = new GlideRecord("e_signature_registry");
if (!esigRegistryGR.isValid())
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) {
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
};

c.data.comment = "TEST"; //code to
spUIActionsExecuter.executeFormAction(ESIGNATURE[state], "sysapproval_approver" , c.data.sys_id, [] , "", requestParams).then(function(response) {
});
} else {
c.data.op = state;
c.data.state = state;
c.server.update();
}
}
}

 

 

I checked all BR, CS, UI Action, couldnt find anything.

 

 

I couldn't see buttons from your widget, but never mind. This is the widget which I use, which also does the same thing. Check and let me if that helps

HTML

<div ng-if="c.data.isValid" class="panel panel-{{::c.options.color}} b">
  <div class="panel-heading">
    <h4 class="panel-title" ng-if="c.data.isMine && (c.data.state == 'requested')">${This {{c.data.label}} requires your approval}</h4>
    <h4 class="panel-title" ng-if="!c.data.isMine && (c.data.state == 'requested')">${This {{c.data.label}} requires approval <span ng-if="c.data.approver"> by {{c.data.approver}}}</span></h4>
    <h4 class="panel-title" ng-if="c.data.state == 'approved'">${Approved} <sn-time-ago timestamp="::c.data.sys_updated_on" /></h4>
    <h4 class="panel-title" ng-if="c.data.state == 'rejected'">${Rejected} <sn-time-ago timestamp="::c.data.sys_updated_on" /></h4>
  </div>  
  <div class="panel-body">
    <form ng-submit="$event.preventDefault()" class="form-horizontal">
      <div ng-if="c.data.fields.length > 0">
        <div ng-repeat="field in c.data.fields" class="m-b-xs" ng-if="field.value">
          <label class="m-n">{{field.label}}</label>
          <span ng-switch="field.type">
            <div ng-switch-when="glide_date_time" title="{{field.display_value}}"><sn-time-ago timestamp="::field.value" /></div>
            <div ng-switch-default >{{field.display_value}}</div>
          </span>
        </div>
      </div>
      <div ng-if="c.data.isMine && (c.data.state == 'requested')" class="question">
        <button type="button" name="approve" class="btn btn-success btn-question" ng-click="c.action('approved')">${Approve}</button>
        <div class="spacer"></div>
        <button type="button" name="reject" class="btn btn-default btn-question" ng-click="c.action('rejected')">${Reject}</button>
      <textarea ng-model="c.data.comment" style="color: grey; width: 100%; margin-top: .5em;" placeholder="Rejection Comments" class="form-control" rows="5"></textarea>
      </div>
    </form>
  </div>  
</div>

css

.question {
  text-align: center;
  margin-top: 1em;
}

.spacer {
  display:inline-block;
  width:5%;
}

.btn-question {
	width: 45%;
}

Client script

function ($scope, $window) {
	var c = this;	
	
	c.action = function(state) {
		
		if( (c.data.comment ==  undefined || c.data.comment ==  '' )&& state == 'rejected'){
			$window.alert('Rejection Comments cannot be empty');
			return false;
		}
		c.data.op = state;
		c.data.state = state;
		c.server.update();		
	};	
}

Server

(function() {
	var gr = $sp.getRecord();
	if (gr == null || !gr.isValid()) {
		data.isValid = false;
		return;
	}
	
	
	
	data.isValid = true;
	//data.isMine = gr.getValue("approver") == gs.getUserID();
	//data.isMine = getMyApprovals().toString().indexOf(gr.getValue("approver") >= 0);
	data.isMine = (getMyApprovals().toString().indexOf(gr.getValue("approver")) >= 0);
	data.approvers = getMyApprovals();
	data.approval = gr.getValue("approver");
	if (!data.isMine && !gr.approver.nil())
		data.approver = gr.approver.getDisplayValue();
	if (input && input.op) { 
		gr.state = input.op;
		if (input.comment){
		gr.comments = input.comment;
		}
			
		gr.update();
	}
/*if (input.comment){
	gr.comments = input.comment;
	gr.update();
	
}*/
	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();

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

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

Pavel87
Kilo Contributor

Hi,

 

Did you had a chance to solve it? I am facing the same issue, when the approver is saving comments in SP, system is populating the comments twice every time. 

I checked that when I am performing such action from the backend perspective (and saving approval comments), system is not creating duplicates, so the issue is somewhere in the "Approval info" widget most probably.

I've used solution from below link, but still the issue persist.

https://community.servicenow.com/community?id=community_question&sys_id=bfc2a8d4dbb0f34413b5fb243996...

 

Thanks