Name

sn_hr_core.hr_BulkCaseRequestUtils

Description

No description available

Script

var hr_BulkCaseRequestUtils = Class.create();
hr_BulkCaseRequestUtils.prototype = {
  initialize: function() {},

  /**
   * Checks if 
   *  1. 'Bulk case request' status is 'requested'
   *  2. ALL `user-segment-groups` are processed and 
   *  3. has atleast one `user-segment` in `included` state
   *
   * @param {string} bulkCaseRequestID - sn_hr_core_bulk_case_request record sys_id
   *
   * @return {boolean}
   *
   * throws exception
   */
  canCreateBulkCases: function(bulkCaseRequestID) {
      try {
          if (gs.nil(bulkCaseRequestID))
              throw this.getError("canCreateBulkCases' - missing sn_hr_core_bulk_case_request sys_id.");

          //return false immediately if 'Bulk case request' state is not 'requested'
          var bulkCaseRequestGR = new GlideRecord('sn_hr_core_bulk_case_request');
          if (!bulkCaseRequestGR.get(bulkCaseRequestID))
              throw this.getError("canCreateBulkCases' - 'Bulk case record' (" + bulkCaseRequestID + ") not found.");
          var bulkCaseRequestStatus = bulkCaseRequestGR.getValue('status');
          if (bulkCaseRequestStatus != 'requested')
              return false;

          //check if 'Bulk case user segments' are ready to process
          return !this.isProcessingUserSegmentGroup(bulkCaseRequestID) && this.hasAtleastOneIncludedUserSegment(bulkCaseRequestID);

      } catch (error) {
          this.getError("'canCreateBulkCases': " + error);
      }
  },

  /**
   * Check if ALL `user-segment-groups` are processed
   *
   * @param {string} bulkCaseRequestID - sn_hr_core_bulk_case_request record sys_id
   *
   * @return {boolean}
   *
   * throws exception
   */
  isProcessingUserSegmentGroup: function(bulkCaseRequestID) {
      if (gs.nil(bulkCaseRequestID))
          throw this.getError("isProcessingUserSegmentGroup' - missing sn_hr_core_bulk_case_request sys_id.");

      var bcUserSegmentGroupGR = new GlideRecord('sn_hr_core_bulk_case_user_segment_group');
      bcUserSegmentGroupGR.addQuery('bulk_case_request', bulkCaseRequestID);
      bcUserSegmentGroupGR.addQuery('status', '!=', 'processed').addOrCondition('status', '');
      bcUserSegmentGroupGR.setLimit(1);
      bcUserSegmentGroupGR.query();

      return bcUserSegmentGroupGR.hasNext();
  },

  /**
   * Check if atleast one `user-segment` is in `included` state
   *
   * @param {string} bulkCaseRequestID - sn_hr_core_bulk_case_request record sys_id
   *
   * @return {boolean}
   *
   * throws exception
   */
  hasAtleastOneIncludedUserSegment: function(bulkCaseRequestID) {
      if (gs.nil(bulkCaseRequestID))
          throw this.getError("hasAtleastOneIncludedUserSegment' - missing sn_hr_core_bulk_case_request sys_id.");

      var bcUserSegmentGR = new GlideRecord('sn_hr_core_bulk_case_user_segment');
      bcUserSegmentGR.addQuery('user_segment_group.bulk_case_request', bulkCaseRequestID);
      bcUserSegmentGR.addQuery('user_segment_group.status', 'processed');
      bcUserSegmentGR.addQuery('status', 'included');
      bcUserSegmentGR.setLimit(1);
      bcUserSegmentGR.query();

      return bcUserSegmentGR.hasNext();
  },

  /**
   * Method to count included user-records for bulk-case-request
   *
   * @param {string} bulkCaseRequestID - sn_hr_core_bulk_case_request record sys_id
   *
   * @return {Int}  count
   *
   * throws exception
   */
  getIncludedUserCount: function(bulkCaseRequestID) {
      if (gs.nil(bulkCaseRequestID))
          throw this.getError("getIncludedUserCount' - missing sn_hr_core_bulk_case_request sys_id.");

      var bcUserSegmentGA = new GlideAggregate('sn_hr_core_bulk_case_user_segment');
      bcUserSegmentGA.addNotNullQuery('user_segment_group_revision.sys_id');
      bcUserSegmentGA.addQuery('user_segment_group_revision.bulk_case_request', bulkCaseRequestID);
      bcUserSegmentGA.addQuery('user_segment_group_revision.status', 'processed');
      bcUserSegmentGA.addQuery('status', 'included');
      bcUserSegmentGA.addAggregate('COUNT');
      bcUserSegmentGA.query();
      bcUserSegmentGA.next();

      return bcUserSegmentGA.getAggregate('COUNT');
  },

  /**
   * Method to process 'Bulk case request' and create HR cases
   *
   * @param {GlideRecord} - sn_hr_core_case_request record
   *
   * throws exception
   */
  createBulkCases: function(bulkCaseRequestGR) {
      try {
          if (!bulkCaseRequestGR.isValidRecord())
              throw this.getError("'createBulkCases': Invalid 'Bulk case request' record.");

          var bulkCaseRequestID = bulkCaseRequestGR.getUniqueValue();
          if (!this.canCreateBulkCases(bulkCaseRequestID))
              throw this.getError("'createBulkCases': Cannot create cases for 'Bulk case request' - ID: " + bulkCaseRequestID);

          //mark 'Bulk case request' - `in_progress`
          this.updateGlideRecord(bulkCaseRequestGR, {
              'status': 'in_progress',
              'start_time': new GlideDateTime()
          });

          //create parent case for bulk-case-request
          var bulkRequestCaseID = '';
          if (bulkCaseRequestGR.getValue('create_parent_case') == true) {

              //set sys_created_by as subject_person and default hr_service for parent bulk-case
              var userRecord = this.getUserRecordForName(bulkCaseRequestGR.getValue('sys_created_by'));
              bulkRequestCaseID = this.createHRCase({
                  'subject_person': {
                      'value': userRecord.sys_id
                  },
  				'opened_for': {
                      'value': userRecord.sys_id
                  },
  				'bulk_case_request': {
  					'value': bulkCaseRequestID
  				},
                  'hr_service': {
                      'value': gs.getProperty('sn_hr_core.bulk_case_parent_service', 'c980f47c3b472200705d86a734efc449')
                  } //Alternatively use OOB HR service - 'Bulk Parent Case'
              });

              if (gs.nil(bulkRequestCaseID))
                  throw this.getError("'createBulkCases': Failed to create parent case for 'Bulk case request' - " + bulkCaseRequestID + ".");
          }

          //create HR case for all user-segments
          var casesCreated = this.createHRCases(bulkCaseRequestGR, bulkRequestCaseID);

  		if (bulkRequestCaseID)
  			casesCreated++;
  		
  		//log warning if less cases created for updated criteria on HR service (after processing user groups)
  		var casesToCreate = this.getIncludedUserCount(bulkCaseRequestID) + (bulkRequestCaseID? 1 : 0); 
  		if (casesCreated < casesToCreate)
  			gs.warn("'"+ bulkCaseRequestGR.number +"': "+ casesCreated +" cases created as some user did not match the criteria on HR service.");
  		
          //update final count and mark 'Bulk case request' status - 'completed'
          this.updateGlideRecord(bulkCaseRequestGR, {
              'status': 'completed',
              'cases_created_count': casesCreated,
              'completed_time': new GlideDateTime()
          });

      } catch (error) {
  		this.updateGlideRecord(bulkCaseRequestGR, {
              'status': 'error'
  		});
          this.getError("'createBulkCases': " + error);
      }
  },

  /**
   * Method to create HR cases for sn_hr_core_bulk_case_user_segment
   *
   * @param {GlideRecord} bulkCaseRequestGR - sn_hr_core_case_request record
   * @param {string} bulkRequestCaseID (optional) - sys_id of parent HR case created for 'Bulk case request' 
   *
   * @return {int} number of HR cases created
   * 
   * throws exception
   */
  createHRCases: function(bulkCaseRequestGR, bulkRequestCaseID) {
      if (!bulkCaseRequestGR.isValidRecord())
          throw this.getError("'createHRCases': Invalid 'Bulk case request' record.");

      var bulkCaseRequestID = bulkCaseRequestGR.getUniqueValue();
  	var bulkCaseHRServiceID = bulkCaseRequestGR.getValue('hr_service');
      var casesCreated = 0;

      //create HR cases for all user-segments marked 'included'
      var userSegmentGR = new GlideRecord('sn_hr_core_bulk_case_user_segment');
      userSegmentGR.addQuery('user_segment_group.bulk_case_request', bulkCaseRequestID);
      userSegmentGR.addQuery('status', 'included');
      userSegmentGR.query();

      var curUserGroupRevisionIDs = {};
      while (userSegmentGR.next()) {

          //process user-segment only if it is the current revision of user-segment-group
          if (this._hasCurUserGroupRevision(curUserGroupRevisionIDs, userSegmentGR)) {

              //parse user-segment-data for HR case field values
              var HRCaseData = userSegmentGR.user_segment_group_revision.case_data;
              var fields = JSON.parse(HRCaseData);

              //set parent for HR case
  			if (bulkRequestCaseID)
  				fields.parent = {
  					'value': bulkRequestCaseID
  				};

              //set HR service 
              fields.hr_service = {
                  'value': bulkCaseHRServiceID
              };

              //set subject_person
              var userSegmentValue = {
                  'value': userSegmentGR.getValue('user')
              };
              fields.subject_person = userSegmentValue;
  			
              //set user as opened-for if not explicitly set on user-segment-group
              if (!fields.opened_for || !fields.opened_for.value)
  				fields.opened_for = userSegmentValue;

              //set bulk_case_request
              fields.bulk_case_request = {
                  'value': bulkCaseRequestID
              };

              //log failure to create case and continue
              if (gs.nil(this.createHRCase(fields)))
                  this.getError("'createBulkCases': Failed to create HR case for user ID - " + userSegmentGR.user + ". For 'Bulk case request' ID - " + bulkCaseRequestID + ".");
              else
                  casesCreated++;

              //update 'Bulk case request' with progress
              if ((casesCreated > 0) && (casesCreated % 100 == 0))
                  this.updateGlideRecord(bulkCaseRequestGR, {
                      'cases_created_count': casesCreated
                  });
          }
      }

      return casesCreated;
  },

  /**
   * Method to validate user-segment record for user-segment.group revision
   * 
   * @params:
   *  {Object} stores {<user-segment-group>: <current revision>}
   *  {GlideRecord} sn_hr_core_bulk_case_user_segment record
   *
   * @returns {boolean} 
   * true if user-segment.group.revision matches user-segment.group_revision
   * false otherwise
   *
   * NOTE:
   *  'user-segment' references 'user-segment-group' via 'revision' as a reference-key 
   *  After updating 'user-segment-group' new 'revision' is generated, and user-segment is never updated
   *  Thus discard user-segment with 'null' user-segment.user_segment_group_revision.sys_id. It is a 'invalid' user-segment.
   */
  _hasCurUserGroupRevision: function(curUserGroupRevisionIDs, userSegmentGR) {

      //user-segment is old and not valid
      if (gs.nil(userSegmentGR.user_segment_group_revision.sys_id))
          return false;

      //compare cached current revision of user_segment.user_segment_group
      else if (curUserGroupRevisionIDs.hasOwnProperty(userSegmentGR.user_segment_group))
          return curUserGroupRevisionIDs[userSegmentGR.user_segment_group] == userSegmentGR.user_segment_group_revision;

      //cache current valid revision for user-segment.user_segment_group
      else if (userSegmentGR.user_segment_group.revision == userSegmentGR.user_segment_group_revision) {
          curUserGroupRevisionIDs[userSegmentGR.user_segment_group] = userSegmentGR.user_segment_group.revision;
          return true;
      } else
          return false;
  },

  /**
   * Method to create HR case
   *
   * @param {Object} - Fields for HR case {'<field_name>': '<value>'}
   *
   * @return sys_id of the HR case created
   */
  createHRCase: function(fields) {
      var caseDetails = new sn_hr_core.hr_CaseCreation().createTask('sn_hr_core_case', fields, true);

      if (!gs.nil(caseDetails) && caseDetails.hasOwnProperty('sys_id'))
          return caseDetails.sys_id;
  },

  /**
   * Method to update Glide Record
   *
   * @params
   *   glideRecord {GlideRecord} - record to update
   *   fields {Object} - {'<field_name>': '<value>'}
   *
   * throws exception
   */
  updateGlideRecord: function(glideRecord, fields) {
      if (!glideRecord.isValidRecord())
          throw this.getError("'updateGlideRecord': Invalid Glide Record.");

      if (gs.nil(fields))
          throw this.getError("'updateGlideRecord': No field to update record.");

      //set field values
      for (var field in fields)
          glideRecord.setValue(field, fields[field]);

      //update 'Bulk case request'
      if (!glideRecord.update(gs.getMessage("Updated by 'hr_BulkCaseRequestUtils().updateGlideRecord()'.")))
          this.getError("'updateGlideRecord' - Failed to update Glide Record (" + bulkCaseRequestGR.getUniqueID() + ").");
  },

  /**
   * Method to fetch sys_user record
   *
   * @param {string} userName
   *
   * @return {GlideRecord} sys_user record
   */
  getUserRecordForName: function(userName) {
      var userRecord = new GlideRecord('sys_user');
      userRecord.addQuery('user_name', userName);
      userRecord.setLimit(1);
      userRecord.query();
      userRecord.next();

      return userRecord;
  },

  /**
   * Method to be used  when throwing an exception. To get an error object from the message. This method logs the
   * message and returns an Error object.
   *
   * @param {string} message - The error message.
   *
   * @return {Error} - The error object.
   */
  getError: function(message) {
      var errorMessage = 'Script include: hr_BulkCaseRequestUtils - ' + message;
      gs.error(errorMessage);

      return new Error(errorMessage);
  },

  type: 'hr_BulkCaseRequestUtils'
};

Sys ID

17d2993d0fc32010af170c3635767ecf

Offical Documentation

Official Docs: