Need to introduce withdraw case button on service portal

Sri56
Tera Contributor

Hi All,

 

We need to introduce withdraw case button as below:

Sri56_0-1781865258338.png

As of now button is visible but on click of button page is redirecting to undefined.

Ideally on click of button, subsequent case should be cancelled and its approvals should be no longer required without affecting any case state and its approvals.

 

Technical details:

widget - Request Ticket Action

 

html - <div>
<button name="withdraw" ng-disabled="c.withdraw" ng-click="c.redirectTowithdraw()" class="btn btn-primary btn-block ng-binding ng-scope">
Withdraw Request
</button>
</div>

 

server script:

(function() {
    var tableName = $sp.getParameter('table');
    var recordId = $sp.getParameter('sys_id');
    if(tableName && recordId) {
        var recordGr = new GlideRecord(tableName);
        recordGr.get(recordId);
    }
    if(input && input.withdraw) {
        data.resubmit_url = new xxxxUtils.setWithdrawReq(recordGr);
    }
})();
 
client script:
api.controller=function() {
    /* widget controller */
    var c = this;
    c.withdraw = false;
    c.redirectTowithdraw = function() {
        c.withdraw = true;
        c.server.get({
            withdraw: true
        }).then(function(r) {
            top.window.location = r.data.resubmit_url;
        });
    };
};
 
Script include:
var PANFUtils = Class.create();
PANFUtils.prototype = {
    initialize: function() {
    },
showWithdrawButton: function(xxxxGr) {
        if (xxxxGr.state == 1 || xxxxGr.state == 10 || xxxxGr.state == 18) {
            return true;
        } else {
            return false;
        }
    },
    setWithdrawReq: function(xxxxGr) {
        var sysID= xxxx.sys_id;
        var cs = new GlideRecord('xxxx_table');
        cs.addEncodedQuery('sys_id',sysID);
        cs.query();
        while(cs.next())
        {
            var grAppTask = new GlideRecord('sysapproval_approver');
                var grAppTaskencodedqur = "sysapproval=" + cs.sys_id + "^state=requested";
                grAppTask.addEncodedQuery(grAppTaskencodedqur);
                grAppTask.query();
                if (grAppTask.next()) {
                    grAppTask.state = 'not_required';
                    grAppTask.comments = "Case is withdraw from requestor.";
                    grAppTask.update();
                }
                cs.state = 7;
                cs.approval = "rejected";
                cs.comments = "Case is withdraw from requestor.";
        }
            cs.update();

       
    // var url = gs.getProperty('glide.servlet.uri') + "esc?id=my_requests";
    //     return url;
    },
    type: 'xxxxUtils'
};

 

This is somehow not working, please help if i am missing something?

 

Thanks,

Sri

1 ACCEPTED SOLUTION

mza-guille
Giga Contributor

Hi Sri,

The redirect to undefined is happening because your server call is not returning a URL.

In the widget client script you do this:

top.window.location = r.data.resubmit_url;

But in your Script Include, setWithdrawReq() does not return anything because the return URL is commented out. So r.data.resubmit_url becomes undefined.

There are also a few script issues to fix:

  • new xxxxUtils.setWithdrawReq(recordGr) is not the right way to call a Script Include method.
  • var sysID = xxxx.sys_id uses xxxx, but that variable is not defined.
  • addEncodedQuery('sys_id', sysID) is not valid usage. Use addQuery('sys_id', sysID) or build one encoded query string.
  • if (grAppTask.next()) updates only one approval. Use while (grAppTask.next()) if there can be multiple approvals.
  • cs.update() should be inside the block where the case record is actually found/changed.

A cleaner server script pattern would be:

(function() {
    var tableName = $sp.getParameter('table');
    var recordId = $sp.getParameter('sys_id');
    if (input && input.withdraw && tableName && recordId) {
        var recordGr = new GlideRecord(tableName);
        if (recordGr.get(recordId)) {
            var util = new PANFUtils();
            data.resubmit_url = util.setWithdrawReq(recordGr);
        }
    }
})();

And your Script Include method should return something:

setWithdrawReq: function(caseGr) {
    var sysID = caseGr.getUniqueValue();
    var cs = new GlideRecord('xxxx_table');
    if (!cs.get(sysID))
        return '?id=my_requests';
    var approvals = new GlideRecord('sysapproval_approver');
    approvals.addQuery('sysapproval', cs.getUniqueValue());
    approvals.addQuery('state', 'requested');
    approvals.query();
    while (approvals.next()) {
        approvals.state = 'not_required';
        approvals.comments = 'Case was withdrawn by requester.';
        approvals.update();
    }

cs.state = 7; // confirm this is the correct cancelled/withdrawn state for your table
cs.approval = 'rejected'; // confirm this is really desired
cs.comments = 'Case was withdrawn by requester.';
cs.update();

    return '?id=my_requests';
}

Then in the client script, guard the redirect:

c.redirectTowithdraw = function() {
    c.withdraw = true;
    c.server.get({ withdraw: true }).then(function(r) {
        if (r.data && r.data.resubmit_url) {
            top.window.location = r.data.resubmit_url;
        } else {
            c.withdraw = false;
            spUtil.addErrorMessage('Unable to withdraw the request. Please contact support.');
        }
    });
};

One more important point: your text says the case should be cancelled and approvals should become no longer required, but also says “without affecting case state and approvals.” Those are conflicting requirements. If the business requirement is “withdraw,” then changing the case state and approval records is expected. If the requirement is only to hide/disable the button, then you should not update the case/approval records.

So the immediate fix is: return a URL from the Script Include and call the Script Include correctly. After that, validate the business rule for whether state = 7 and approval = rejected are really the correct values for your custom table.

View solution in original post

2 REPLIES 2

Kieran Anson
Kilo Patron

You're mixing AngularJS and native HTML/JS interaction. 

 

From a user experience, what's the reason for redirecting? That can be an annoying experience and likely not preferred 

mza-guille
Giga Contributor

Hi Sri,

The redirect to undefined is happening because your server call is not returning a URL.

In the widget client script you do this:

top.window.location = r.data.resubmit_url;

But in your Script Include, setWithdrawReq() does not return anything because the return URL is commented out. So r.data.resubmit_url becomes undefined.

There are also a few script issues to fix:

  • new xxxxUtils.setWithdrawReq(recordGr) is not the right way to call a Script Include method.
  • var sysID = xxxx.sys_id uses xxxx, but that variable is not defined.
  • addEncodedQuery('sys_id', sysID) is not valid usage. Use addQuery('sys_id', sysID) or build one encoded query string.
  • if (grAppTask.next()) updates only one approval. Use while (grAppTask.next()) if there can be multiple approvals.
  • cs.update() should be inside the block where the case record is actually found/changed.

A cleaner server script pattern would be:

(function() {
    var tableName = $sp.getParameter('table');
    var recordId = $sp.getParameter('sys_id');
    if (input && input.withdraw && tableName && recordId) {
        var recordGr = new GlideRecord(tableName);
        if (recordGr.get(recordId)) {
            var util = new PANFUtils();
            data.resubmit_url = util.setWithdrawReq(recordGr);
        }
    }
})();

And your Script Include method should return something:

setWithdrawReq: function(caseGr) {
    var sysID = caseGr.getUniqueValue();
    var cs = new GlideRecord('xxxx_table');
    if (!cs.get(sysID))
        return '?id=my_requests';
    var approvals = new GlideRecord('sysapproval_approver');
    approvals.addQuery('sysapproval', cs.getUniqueValue());
    approvals.addQuery('state', 'requested');
    approvals.query();
    while (approvals.next()) {
        approvals.state = 'not_required';
        approvals.comments = 'Case was withdrawn by requester.';
        approvals.update();
    }

cs.state = 7; // confirm this is the correct cancelled/withdrawn state for your table
cs.approval = 'rejected'; // confirm this is really desired
cs.comments = 'Case was withdrawn by requester.';
cs.update();

    return '?id=my_requests';
}

Then in the client script, guard the redirect:

c.redirectTowithdraw = function() {
    c.withdraw = true;
    c.server.get({ withdraw: true }).then(function(r) {
        if (r.data && r.data.resubmit_url) {
            top.window.location = r.data.resubmit_url;
        } else {
            c.withdraw = false;
            spUtil.addErrorMessage('Unable to withdraw the request. Please contact support.');
        }
    });
};

One more important point: your text says the case should be cancelled and approvals should become no longer required, but also says “without affecting case state and approvals.” Those are conflicting requirements. If the business requirement is “withdraw,” then changing the case state and approval records is expected. If the requirement is only to hide/disable the button, then you should not update the case/approval records.

So the immediate fix is: return a URL from the Script Include and call the Script Include correctly. After that, validate the business rule for whether state = 7 and approval = rejected are really the correct values for your custom table.