Issue with the Approvals Widget failing in Service Portal

ssswetha13
Tera Contributor

Hi All,

Did anyone of you have faced any issue with respect to the cloning of the "Approvals" widget? I have cloned the approvals widget, and had created certain approvals to check whether the data is being reflected in the portal or not. However, the data was not getting populated. Also, I haven't made any customizations to the widget. It is throwing the error as failing widget.Let me how to proceed ahead with this. Please refer the screenshot:

find_real_file.png

1 ACCEPTED SOLUTION

Hi kammila,



I did found a solution to this issue. This was occurring because in the server side script last line (return gr.document_id.getRefRecord();) it is asking for the valid document id.


if you have directly created the approval in the sysapprovals_approval table (ie. the My Approval under Self-service module in navigation) by clicking on the new button then the id wouldn't be generated (you can check the xml file of the record where the document id will be empty).



Since, the widget is not getting the required document id, it will throw this error in the portal page.



If you delete the record that you have created manually, the widget will work as expected.


View solution in original post

6 REPLIES 6

Melghi
Kilo Expert

If you have a knowledge in scripting you have to check your line number 95 of the script of the widget. Else share the script of you widgte


Hello i am having the same problem , i just cloned the Out of box widget and renames it here is the code for reference




Html ---



<div class="panel panel-{{::options.color}} b">


  <div class="panel-heading">


      <h4 class="panel-title"><fa ng-if="::options.glyph.length" name="{{::options.glyph}}" class="m-r-sm" />${My Approvals}</h4>


  </div>


  <div class="panel-body">


      <div ng-if="data.approvals.length == 0">


          ${You have no pending approvals}


      </div>


      <div ng-repeat="approval in data.approvals" class="sp-approval m-b">


          <div class="row">


              <div ng-class="contentColClass">


                  <div ng-if="approval.task.number || approval.task.short_description">


                      <a ng-href="?id=approval&table=sysapproval_approver&sys_id={{::approval.sys_id}}" title="{{data.ViewApprovalPageMsg}}">


                          <span ng-if="approval.task.number">{{::approval.task.number}}</span>


                          <span ng-if="approval.task.number && approval.task.short_description"> - </span>


                          <span ng-if="approval.task.short_description">{{::approval.task.short_description}}</span>


                      </a>


                  </div>


                  <div ng-if="approval.task.opened_by"><label>${Requestor}</label> {{::approval.task.opened_by}}</div>


                  <div ng-if="approval.task.start_date"><label>${Start}</label> {{::approval.task.start_date}}</div>


                  <div ng-if="approval.task.end_date"><label>${End}</label> {{::approval.task.end_date}}</div>


                  <div ng-if="approval.task.price"><label>${Price}</label> {{::approval.task.price}}


                      <span ng-if="approval.task.recurring_price"><label>${Recurring price}</label> {{::approval.task.recurring_price}} {{::approval.task.recurring_frequency}}</span>


                  </div>


                  <div ng-if="approval.items.length == 1">


                      <div ng-repeat="item in approval.items">


                          <div ng-if="item.variables.length > 0" ng-init="variable_toggle=false">


                              <a href="javascript:void(0)" ng-click="variable_toggle = !variable_toggle">


                                  <span class="glyphicon"


                                              ng-class="{'glyphicon-chevron-down': !variable_toggle, 'glyphicon-chevron-up': variable_toggle}">


                                  </span>


                                  ${Options}


                              </a>


                              <div ng-repeat="variable in item.variables" ng-if="variable_toggle">


                                  <label class="text-muted">{{::variable.label}}</label>


                                  <div>{{::variable.display_value}}</div>


                              </div>


                          </div>


                      </div>


                  </div>




                  <div ng-if="approval.variables.length > 0" ng-init="variable_toggle=false">


                      <a href="javascript:void(0)" ng-click="variable_toggle = !variable_toggle">


                          <span class="glyphicon"


                                      ng-class="{'glyphicon-chevron-down': !variable_toggle, 'glyphicon-chevron-up': variable_toggle}">


                          </span>


                          ${Options}


                      </a>


                      <div ng-repeat="variable in approval.variables" ng-if="variable_toggle">


                          <label>{{::variable.label}}</label>


                          <div>{{::variable.display_value}}</div>


                      </div>


                  </div>


              </div>




              <div ng-if="!options.portal" class="col-sm-3">


                  <button name="approve" ng-if="approval.state == 'requested'" class="btn btn-primary btn-block" style="border-width:1px;" ng-click="approve(approval.sys_id);">${Approve}</button>


                  <button name="reject" ng-if="approval.state == 'requested'" class="btn btn-default btn-block" ng-click="reject(approval.sys_id);">${Reject}</button>


                  <button ng-if="approval.state == 'approved'" class="btn btn-success btn-block">{{approval.stateLabel}}</button>


                  <button ng-if="approval.state == 'rejected'" class="btn btn-danger btn-block">{{approval.stateLabel}}</button>


                  <button ng-if="approval.state != 'requested'" class="btn btn-default btn-block" style="visibility:hidden">{{approval.stateLabel}}</button>


              </div>


              <div ng-if="options.portal && approval.state == 'requested'" class="col-xs-6">


                  <button name="reject" class="btn btn-default btn-block" ng-click="reject(approval.sys_id);">${Reject}</button>


              </div>


              <div ng-if="options.portal && approval.state == 'requested'" class="col-xs-6">


                  <button name="approve" class="btn btn-primary btn-block" ng-click="approve(approval.sys_id);">${Approve}</button>


              </div>


              <div ng-if="options.portal && approval.state != 'requested'" class="col-xs-12">


                  <button ng-if="approval.state == 'approved'" class="btn btn-success btn-block">{{approval.stateLabel}}</button>


                  <button ng-if="approval.state == 'rejected'" class="btn btn-danger btn-block">{{approval.stateLabel}}</button>


              </div>


          </div>


      </div>


  </div>




server script --



if (input && input.op) {


  var app = new GlideRecord("sysapproval_approver");


  if (app.get(input.target)) {


      app.state = input.op;


      app.update();


  }


}




data.ViewApprovalPageMsg = gs.getMessage("View approval page");




var gr = new GlideRecord('sysapproval_approver');


gr.setLimit(50);


var qc1 = gr.addQuery("state", "requested");


if (input)


  qc1.addOrCondition("sys_id", "IN", input.ids);




gr.addQuery("approver", gs.getUserID());


gr.orderBy("sys_created_on");


gr.query();




var approvals = [];


var ids = [];


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 (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.toString();


  t.end_date = task.end_date.toString();


  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 = $sp.getRecordVariablesArray(itemsGR);


          t.short_description = itemsGR.short_description.toString();


      }




      items[idx] = item;


      idx++;


  }




  var j = {};


  j.sys_id = gr.getUniqueValue();


  j.table = gr.getRecordClassName();


  j.task = t;


  if (task)


      j.variables = $sp.getRecordVariablesArray(task);




  j.items = items;


  j.state = gr.getValue("state");


  j.stateLabel = gr.state.getDisplayValue();


  approvals.push(j);


}


data.ids = ids;


data.approvals = approvals;




function getRecordBeingApproved(gr) {


  if (!gr.sysapproval.nil())


      return gr.sysapproval.getRefRecord();




  return gr.document_id.getRefRecord();


}




client controller ----------



function ($scope, spUtil, snRecordWatcher) {


 


  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-9";


  }




  $scope.data.op = "";


  snRecordWatcher.initList("sysapproval_approver", "state=requested^approver=" + window.NOW.user_id);




  function get() {


      spUtil.update($scope);


  }




  $scope.$on('record.updated', function(name, data) {


  get();


  })




  $scope.approve = function(id) {


      $scope.data.op = "approved";


      $scope.data.target = id;


      get();


  }




  $scope.reject = function(id) {


  $scope.data.op = "rejected";


  $scope.data.target = id;


  get();


  }


}





find_real_file.png


Hi kammila,



I did found a solution to this issue. This was occurring because in the server side script last line (return gr.document_id.getRefRecord();) it is asking for the valid document id.


if you have directly created the approval in the sysapprovals_approval table (ie. the My Approval under Self-service module in navigation) by clicking on the new button then the id wouldn't be generated (you can check the xml file of the record where the document id will be empty).



Since, the widget is not getting the required document id, it will throw this error in the portal page.



If you delete the record that you have created manually, the widget will work as expected.


3 years later and I experienced this exact issue. This post was the only information I could find on it. Thank you!