UI Action validation before process the action

gowthamanbalu
Tera Contributor

Hello All,

I would like to get some advise on validating UI policies in generic way. Let me put a scenario to make it more simpler.

In our change module, we have two UI actions in implement state. Let's call them as "Implementation Complete" and "Revert to Assess".

1. When "implementation complete" button is being hit, it asks for two mandatory fields (i.e. closure details). Upon filling the mandatory field, If user hit the SAME button, system sets a flag (implementation complete) to true which triggers the workflow to next state.

2. When "Revert to assess" is being hit, it asks for another mandatory field (reversion detail). Upon filing field,If user hit the SAME button, system sets a flag (reversion flag) to true which in turn regress the workflow.

Here, I am pressing the word "SAME" . Because at times, user hit the "Implementation complete" button, fill out the mandatory fields and hit the another button "Revert to assess". Based on our functionality, flag set up, it triggers the 1st button (Implementation complete) and processed.

My concern is the mandatory fields that are filled in remain and non empty and get stored in the DB which creates issue if the same button is being again, as it has to make field mandatory which is already filled in.

Having said that, I would get advise/suggestion to have a generic way of validating UI actions being pressed.

Regards,

GB

7 REPLIES 7

Rama Chandra D
Kilo Guru

Hi,



Can you post the snippet of your UI actions? Just to make sure, I'm understanding you, why would the user hit the 'Rever to Assess' when he/she wants to put the change in 'Implementation complete' in first place?



Regards,


Darshak


Goran WitchDoc
ServiceNow Employee
ServiceNow Employee

I agree.. This should be doable with the UI Actions and it seems to be something wrong in the code. Sharing it would make it easier to answer.



Generally, my own personal feeling is to put the checks in the UI Action as well, just to keep the same standard as OOB UI Actions has (Like resolve on incident). Having it on a onSubmit client Script would make that script run all the times, even if not the button aren't used when the record is saved. Having it in the UI Action would make the code only run when needed. But I'm kind of a performance nerd 😎 and looking for every little thing to trim it up.



//Göran


gowthamanbalu
Tera Contributor

This is more of preventing users from hitting wrong UI action, filling unintended fields and gets them saved in the data base.



Here is the script on both UI actions




Revert To Assess:



function showRevertChange(){


  //make visible reversion fields


  g_form.setDisplay('u_reversion_owner',true);


  g_form.setMandatory('u_reversion_owner',true);


  g_form.setDisplay('u_reversion_reason',true);


  g_form.setMandatory('u_reversion_reason',true);


  var answer = confirm("Are you sure you want to Revert the change?");


  if(answer)


  {


  if (g_form.getValue('u_reversion_reason') == '' || g_form.getValue('u_reversion_owner') == '' ) {


  alert('Please fill in the Reversion Reason and Reversion Owner under Assessment tab');


  return false;   // Abort submission


  }



  // Call the UI Action and skip the 'onclick' function


  gsftSubmit(null, g_form.getFormElement(), 'revert_change_emergency'); // MUST call the 'Action name' set in this UI Action


  }


  //Clear & Hide, If the revert to Assess is cancelled


  g_form.setValue('u_reversion_owner', '');


  g_form.setValue('u_reversion_reason', '');


  g_form.setMandatory('u_reversion_owner',false);


  g_form.setMandatory('u_reversion_reason',false);


  g_form.setDisplay('u_reversion_owner',false);


  g_form.setDisplay('u_reversion_reason',false);


  return false;


}




if (typeof window == 'undefined')


  serverReopen();




function serverReopen() {


  try{


  new FISChangeRequestManager().RevertToAssess(current);


  current.update();


  action.setRedirectURL(current);


  }


  catch(ex){


  FISErrors.showStandardUIError();


  action.setRedirectURL(current);


  }


}



+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++



Implementation Complete:



function markImplementationComplete(){


  //Set Implementation complete to true


  //g_form.setValue('u_implementation_complete',true);


  //g_form.save();


//}


  //make closure fields mandatory


  g_form.setMandatory('close_notes',true);


  g_form.setMandatory('close_code',true);


  var answer = confirm("Are you sure you want to mark the implementation complete?");


  if(answer)


  {


  if (g_form.getValue('close_notes') == '' || g_form.getValue('close_code') == '' ) {


  alert('Please fill in the Close notes and Close code under Closure Information tab');


  return false;   // Abort submission


  }



  // Call the UI Action and skip the 'onclick' function


  gsftSubmit(null, g_form.getFormElement(), 'implementation_complete'); // MUST call the 'Action name' set in this UI Action


  }


  //Make fields non mandatory, If the Implementation complete is cancelled


  g_form.setValue('u_reversion_owner', '');


  g_form.setValue('u_reversion_reason', '');


  g_form.setMandatory('close_notes',false);


  g_form.setMandatory('close_code',false);


  return false;


}




if (typeof window == 'undefined')


  serverReopen();




function serverReopen() {


  try{


  current.u_implementation_complete = true;


  current.update();


  action.setRedirectURL(current);


  }


  catch(ex){


  FISErrors.showStandardUIError();


  action.setRedirectURL(current);


  }


}



+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++



Generic Script include for most of the change request functionality. Currently we have been using it for revert function alone.



var FISChangeRequestManager = Class.create();


FISChangeRequestManager.prototype = {


  initialize: function() {


  },



  //function to display Revert to Assess button


  AllowRevertToAssess : function FISChangeRequestManager_AllowRevertToAssess(change){


  try{



  //Displays the UI action in Authorize/schedule/implement phase


  if(change.type == 'normal' && ((change.state == '-2' || change.state == '-3') || (change.state == '-1' && gs.getUser().hasRole('change_manager')))){


  return true;


  }



  //Displays the UI action for emergency change in schedule/implement phase


  else if(change.type=='emergency' && (change.state=='-2' || (change.state==-3 && change.u_assessment_complete == true) || (change.state == '-1' && gs.getUser().hasRole('change_manager')))){


  return true;


  }



  else {


  return false;


  }


  }


  catch(ex){


  //log error


  gs.error("Error: FISChangeRequestManager.DisplayRevertToAssess: ", ex);


  throw ex;


  }


  },



  //validate reversion fields before proceed


  ValidateRevertToAssess : function FISChangeRequestManager_ValidateRevertToAssess(change){


  try{


  if(this.AllowRevertToAssess(change)){


  if(change.u_revert_change == false && change.u_reversion_owner != '' && change.u_reversion_reason != '' && change.u_implementation_complete == false){


  return true;


  }


  else


  {


  return false;


  }


  }


  }


  catch(ex){


  //log error


  gs.error("Error: FISChangeRequestManager.AllowToRevert: ", ex);


  throw ex;


  }


  },



  //Reversion counter increment function


  RevertToAssess : function FISChangeRequestManager_RevertToAssess(change){


  try{


  if(this.ValidateRevertToAssess(change)){


  //get user & reversion details to put them in work notes


  var user = gs.getUser();


  var cur_user=user.getFullName();


  var owner=change.u_reversion_owner.getDisplayValue();



  //set the revert change flag to true


  change.u_revert_change = true;



  //Increment Reversion counter


  change.u_reversion_count = change.u_reversion_count + 1;


  var count = change.u_reversion_count;



  //Increment FIS reversion counter


  if (change.u_reversion_owner == '2'){


  change.u_fis_reversion_count = change.u_fis_reversion_count + 1;


  }


  //Increment Client reversion counter


  else if (change.u_reversion_owner == '1'){


  change.u_client_reversion_count = change.u_client_reversion_count + 1;


  }


  //Increment Vendor reversion counter


  else if (change.u_reversion_owner == '3'){


  change.u_vendor_reversion_count = change.u_vendor_reversion_count + 1;


  }



  //update the work notes with reversion details


  change.work_notes='Change Reverted by '+cur_user+'\n'+'Reversion owner - '+owner+'\n'+'Reversion Reason - '+change.u_reversion_reason+'\n'+'Reversion Count - '+count;



  gs.addInfoMessage(gs.getMessage("Change {0} has been reverted to assess state successfully",[change.number]));


  }


  else{


  gs.addErrorMessage(gs.getMessage("Invalid Update. Change {0} has not been reverted to assess state",[change.number]));


  }


  }



  catch(ex){


  //log error


  gs.error("Error: FISChangeRequestManager.IncrementReversionCounters: ", ex);


  throw ex;


  }



  },





  // This business rule clean up the madate fields which gets filled during the UI actions (Implementation complete and Revert to assess) hit


  // If UI actions is being hit and upon filling mandate fields, User must hit the same UI action to proceed. Some times, User hits some other UI action which in turn saves the date of those mandate fields in the DB


  //To prevent this case, this Business Rule clean up the value if the UI action condition is not meet (i.e. flag was not set, it clear its corresponding mandate fields)



  CleanUpMandateFields : function FISChangeRequestManager_CleanUpMandateFields(change){


  try{


  if(change.u_revert_change == false){


  change.u_reversion_owner ='';


  change.u_reversion_reason ='';


  }


  if(change.u_implementation_complete == false){


  change.close_notes = '';


  change.close_code = '';


  }


  }


  catch(ex){


  //log error


  gs.error("Error: FISChangeRequestManager.CleanUpMandateFields: ", ex);


  throw ex;


  }


  },



  type: 'FISChangeRequestManager'


  };





Regards,


GB