Name

global.CMDBDataManagerHelper

Description

No description available

Script

var CMDBDataManagerHelper = Class.create();
CMDBDataManagerHelper.prototype = {
  initialize: function() {
      this.maxViewRecords = gs.getProperty('glide.cmdb.data_manager.db.max_view_records', 10000);
  },
  CMDB_POLICY_MANAGEMENT_POLICY: 'cmdb_data_management_policy',
  CMDB_POLICY_TYPE_CATEGORIES: 'cmdb_policy_type_categories',
  CMDB_DATA_MANAGEMENT_TASK: 'cmdb_data_management_task',
  CMDB_DATA_MANAGEMENT_POLICY_RUNTIME_ATTRIBUTES: 'cmdb_data_management_policy_runtime_attributes',
  SYS_HUB_CATEGORY: 'sys_hub_category',
  SYS_HUB_FLOW: 'sys_hub_flow',
  CMDB_POLICY_SCHEDULED_JOB: 'cmdb_policy_scheduled_job',
  DRAFT_STATUS: 'Draft',
  READY_STATUS: 'Ready',
  PUBLISHED_STATUS: 'Published',
  CALCULATING_STATUS: 'Calculating',
  PREVIEW_FAILED_STATUS: 'Preview Failed',
  EVALUATION_FAILED_STATUS: 'Evaluation Failed',
  INACTIVE_STATUS: 'Inactive',
  COMPLETED_STATE: 'Completed',
  CMDB_POLICY_CI_EXCLUSION_LIST: 'cmdb_policy_ci_exclusion_list',
  CMDB_POLICY_ARCHIVE_SYS_ID: 'b82b20d00731201017b703767cd300e1',
  CMDB_POLICY_RETIRE_SYS_ID: '66306fcb7352201026f6aa114df6a77c',
  CMDB_POLICY_DELETE_SYS_ID: '562bec900731201017b703767cd300e7',
  CMDB_POLICY_DELETE_RELATED_ITEM_SYS_ID: 'c3059c79ff920110456d766cf43bf1c6',
  ADMIN_USER_SYS_ID: '6816f79cc0a8016401c5a33be04be441',
  SYS_CHOICE: 'sys_choice',
  SYS_CREATED_ON: 'sys_created_on',
  ELEMENT: 'element',
  VALUE: 'value',
  LABEL: 'label',
  SYS_ID: 'sys_id',
  NAME: 'name',
  DESCRIPTION: 'description',
  ENCODED_QUERY: 'encoded_query',
  ARCHIVE_FOR_DAYS: 'archive_for_days',
  NEEDS_REVIEW: 'needs_review',
  TASK_MANAGEMENT_GROUP: 'task_management_group',
  STATUS: 'status',
  STATE: 'state',
  CMDB_POLICY_TYPE: 'cmdb_policy_type',
  PER_POLICY_SCHEDULE: 'per_policy_schedule',
  CONFIGURE_TASK_DUE_DATE: 'configure_task_due_date',
  TASK_DUE_IN_DAYS: 'task_due_in_days',
  POLICY_EXECUTION_JOB: 'policy_execution_job',
  ENFORCED_CONDITION: 'enforced_condition',
  IS_SUBFLOW_OPTIONAL: 'is_subflow_optional',
  DISABLE_REVIEW: 'disable_review',
  REQUIRES_CSDM_COMPLIANCE: 'requires_csdm_compliance',
  CMDB_CI: 'cmdb_ci',
  SUBFLOW: 'subflow',
  CI: 'ci',
  CATEGORY: 'category',
  POLICY_TYPE: 'policy_type',
  ON_DEMAND: 'on_demand',
  COUNT: 'COUNT',
  CMDB_POLICY_PREVIEW: 'cmdb_policy_preview',
  CMDB_POLICY_PREVIEW_RUN: 'cmdb_policy_preview_run',
  POLICY: 'policy',
  TYPE: 'type',
  RUN_AS: 'run_as',
  RUN_TYPE: 'run_type',
  RUN_DAYOFMONTH: 'run_dayofmonth',
  RUN_DAYOFWEEK: 'run_dayofweek',
  RUN_PERIOD: 'run_period',
  RUN_START: 'run_start',
  RUN_TIME: 'run_time',
  DAILY: 'daily',
  WEEKLY: 'weekly',
  MONTHLY: 'monthly',
  ONCE: 'once',
  SCRIPT: 'script',
  END_TIME: 'end_time',
  LANGUAGE: 'language',
  LANGUAGE_DEFUALT_VALUE: 'en',
  PREVIEW_CALCULATING_MESSAGE: gs.getMessage('The policy preview is being calculated. You will receive a notification when it is ready.'),
  INVALID_PREVIEW_STATE: gs.getMessage('The policy preview is not in a valid state.'),
  INCIDENT_OPEN_STATES: ['1', '2', '3'], //New, In Progress, On Hold, 6-Resolved, 7-Closed, 8-Canceled
  PROBLEM_OPEN_STATES: ['101', '102', '103', '104'], //New, Assess, RCA, FIP, 106-Resolved, 107-Closed
  CHANGE_REQUEST_OPEN_STATES: ['-1', '-2', '-3', '-4', '-5', '0'], //Implement, Scheduled, Authorize, Assess, New, Review, 3-Closed, 4-Canceled
  INCIDENT_TABLE: 'incident',
  CHANGE_REQUEST_TABLE: 'change_request',
  PROBLEM_TABLE: 'problem',
  MANAGED_BY_GROUP: 'managed_by_group',
  RETIRE_QUERY: 'life_cycle_stage!=End of Life^ORlife_cycle_stage=NULL',
  ARCHIVE_DELETE_QUERY: 'life_cycle_stage=End of Life',
  NEXT_STATUS_MAP: {
      "Draft": ["Published"],
      "Published": ["Draft", "Evaluation Failed", "Inactive"],
      "Evaluation Failed": ["Draft", "Inactive"],
      "Inactive": ["Draft", "Published"],
  },
  TABLE: 'table',
  USER_GROUP: 'user_group',
  CMDB_TASK_TO_ARCHIVE_CHUNK: 'cmdb_task_to_archive_chunk',
  SYS_ARCHIVE_RUN_CHUNK: 'sys_archive_run_chunk',
  LOG_SOURCE : 'CMDB Data Manager',


  getParamAsString: function(paramName) {
      if (request.queryParams.hasOwnProperty(paramName))
          return request.queryParams[paramName] + '';
      return '';
  },

  getSubFlows: function(policyType) {
      var subflowArr = [];
      var categorySysId = null;

      var grPolicyCat = new GlideRecord(this.CMDB_POLICY_TYPE_CATEGORIES);
      grPolicyCat.addQuery(this.CMDB_POLICY_TYPE, policyType);
      grPolicyCat.query();
      if (!grPolicyCat.next()) {
          return subflowArr;
      }
      categorySysId = grPolicyCat.getValue(this.SYS_HUB_CATEGORY);
      var grSubflow = new GlideRecord(this.SYS_HUB_FLOW);
      grSubflow.addQuery(this.CATEGORY, categorySysId);
      grSubflow.addQuery(this.TYPE, this.SUBFLOW);
      grSubflow.orderByDesc(this.SYS_CREATED_ON);
      grSubflow.setLimit(this.maxViewRecords);
      grSubflow.addActiveQuery();
      grSubflow.query();
      while (grSubflow.next()) {
          subflowArr.push({
              sys_id: grSubflow.getValue(this.SYS_ID),
              name: grSubflow.getValue(this.NAME)
          });
      }
      return subflowArr;
  },

  getPolicyTypes: function(includeOnDemandPolicyType) {
      var result = [];
      var gr = new GlideRecord(this.CMDB_POLICY_TYPE);
      if (includeOnDemandPolicyType == 'false') {
          gr.addQuery(this.ON_DEMAND, false);
      }
      gr.query();
      while (gr.next()) {
          result.push({
              name: gr.getValue(this.NAME),
              sys_id: gr.getValue(this.SYS_ID),
              enforced_condition: gr.getValue(this.ENFORCED_CONDITION),
              per_policy_schedule: gr.getValue(this.PER_POLICY_SCHEDULE),
              is_subflow_optional: gr.getDisplayValue(this.IS_SUBFLOW_OPTIONAL) === 'true' ? true : false,
              disable_review: gr.getDisplayValue(this.DISABLE_REVIEW) === 'true' ? true : false,
              configure_task_due_date: gr.getDisplayValue(this.CONFIGURE_TASK_DUE_DATE) === 'true' ? true : false,
              requires_csdm_compliance: gr.getDisplayValue(this.REQUIRES_CSDM_COMPLIANCE) === 'true' ? true : false
          });
      }
      return result;
  },

  getPolicyTaskCount: function(state) {
      var result = {};
      var gr = new GlideAggregate(this.CMDB_DATA_MANAGEMENT_TASK);
      gr.addAggregate(this.COUNT);
      gr.addQuery(this.STATE, state);
      gr.query();

      while (gr.next()) {
          result.count = parseInt(gr.getAggregate(this.COUNT));
      }
      return result;
  },

  getExcludedCisPerPolicyType: function() {
      var result = [];
      var list = [];
      var gr = this.getRecords(this.CMDB_POLICY_TYPE);

      while (gr.next()) {
          //skip Delete Related Entry policy
          if (gr.getValue(this.SYS_ID) === this.CMDB_POLICY_DELETE_RELATED_ITEM_SYS_ID)
              continue;

          result.push({
              cmdb_policy_type: gr.getValue(this.NAME),
              count: 0
          });
          list.push(gr.getValue(this.SYS_ID));
      }

      var aggr = new GlideAggregate(this.CMDB_POLICY_CI_EXCLUSION_LIST);
      aggr.addAggregate(this.COUNT);
      aggr.addQuery(this.POLICY_TYPE, 'IN', list);
      aggr.groupBy(this.POLICY_TYPE);
      aggr.query();
      while (aggr.next()) {
          var policyType = aggr.getDisplayValue(this.POLICY_TYPE);
          for (var i = 0; i < result.length; i++) {
              if (result[i].cmdb_policy_type === policyType) {
                  result[i].count = parseInt(aggr.getAggregate(this.COUNT));
              }
          }
      }
      return result;
  },

  getExcludedCisListPerPolicyType: function(policyType) {
      var ciListArr = [];
      var gr = this.getRecords(this.CMDB_CI);
      var gc = gr.addJoinQuery(this.CMDB_POLICY_CI_EXCLUSION_LIST, this.SYS_ID, this.CI);
      gc.addCondition(this.POLICY_TYPE, policyType);
      gr.query();

      while (gr.next()) {
          ciListArr.push({
              sys_id: gr.getValue('sys_id'),
              name: gr.getValue('name'),
              sys_class_name: gr.getValue('sys_class_name')
          });
      }
      return ciListArr;
  },

  getPolicyCountPerState: function() {
      var result = [];
      var list = [];
      var sysPropertyLanguage = gs.getProperty('glide.sys.language', this.LANGUAGE_DEFUALT_VALUE); // If customer has multiple languages on instance will not create dup's on list
      var gr = new GlideRecord(this.SYS_CHOICE);
      gr.addQuery(this.NAME, this.CMDB_DATA_MANAGEMENT_POLICY_RUNTIME_ATTRIBUTES);
      gr.addQuery(this.ELEMENT, this.STATUS);
      gr.addQuery(this.LANGUAGE, sysPropertyLanguage);
      gr.query();
      while (gr.next()) {
          result.push({
              state: gr.getValue(this.VALUE),
              state_label: gr.getValue(this.LABEL),
              count: 0
          });
          list.push(gr.getValue(this.VALUE));
      }

      var nativePolicyCount = 0;
      var aggr = new GlideAggregate(this.CMDB_DATA_MANAGEMENT_POLICY_RUNTIME_ATTRIBUTES);
      aggr.addAggregate(this.COUNT);
      aggr.addQuery(this.STATUS, 'IN', list);
      aggr.addQuery('policy.cmdb_policy_type.on_demand', false);
      aggr.groupBy(this.STATUS);
      aggr.query();
      while (aggr.next()) {
          var status = aggr.getValue(this.STATUS);
          for (var i = 0; i < result.length; i++) {
              if (result[i].state === status) {
                  result[i].count = parseInt(aggr.getAggregate(this.COUNT));
                  nativePolicyCount += result[i].count;
              }
          }
      }

      //left outer join `policy & runtime attribute` table to get the total count
      var importedPolicyCount = 0;
      var gAgg = new GlideAggregate('cmdb_data_manager_policy_and_attributes');
      gAgg.addQuery('cmdbpt_on_demand', false);
      gAgg.addAggregate(this.COUNT);
      gAgg.query();
      if (gAgg.next()) {
          importedPolicyCount = parseInt(gAgg.getAggregate(this.COUNT));
      }
      //diff imported with native policies
      importedPolicyCount = (importedPolicyCount - nativePolicyCount);
      importedPolicyCount = importedPolicyCount > 0 ? importedPolicyCount : 0;
      result.push({
          state: 'imported',
          state_label: gs.getMessage('Imported'),
          count: importedPolicyCount
      });

      return result;
  },

  deletePolicies: function(sysIds) {
      var policySysIds = sysIds.split(',');
      var errorSysIds = [];

      var gr = new GlideRecordSecure(this.CMDB_POLICY_MANAGEMENT_POLICY);
      for (var i = 0; i < policySysIds.length; i++) {
          gr.initialize();
          gr.addQuery(this.SYS_ID, policySysIds[i]);
          gr.query();
          if (gr.next()) {
              if (!gr.deleteRecord()) {
                  errorSysIds.push(policySysIds[i]);
              }
          } else {
              errorSysIds.push(policySysIds[i]);
          }
      }

      return errorSysIds;
  },

  getAllPolicies: function(offset, numRowsPerPage) {
      policyList = [];
      var policySysIds = [];
      var count = 0;
      var policyGr = this.getPaginatedRecords(this.CMDB_POLICY_MANAGEMENT_POLICY, offset, numRowsPerPage);

      while (policyGr.next()) {
          if (policyGr.cmdb_policy_type.on_demand) {
              continue;
          }
          policyList[count] = {};
          policyList[count].sys_id = policyGr.getValue(this.SYS_ID);
          policyList[count].name = policyGr.getValue(this.NAME);
          policyList[count].description = policyGr.getValue(this.DESCRIPTION);
          policyList[count].encoded_query = policyGr.getValue(this.ENCODED_QUERY);
          policyList[count].archive_for_days = parseInt(policyGr.getValue(this.ARCHIVE_FOR_DAYS));
          policyList[count].needs_review = policyGr.getValue(this.NEEDS_REVIEW);

          policyList[count].cmdb_policy_type = {};
          policyList[count].cmdb_policy_type.sys_id = policyGr.getValue(this.CMDB_POLICY_TYPE);
          policyList[count].cmdb_policy_type.type = policyGr.cmdb_policy_type.name;

          policyList[count].subflow = {};
          policyList[count].subflow.sys_id = policyGr.getValue(this.SUBFLOW);
          policyList[count].subflow.name = policyGr.subflow.name;
          policyList[count].table = JSUtil.nil(policyGr.getValue(this.TABLE)) ? '' : policyGr.getValue(this.TABLE);
          policyList[count].user_group = JSUtil.nil(policyGr.getValue(this.USER_GROUP)) ? '' : policyGr.getValue(this.USER_GROUP);
          policySysIds.push(policyList[count].sys_id);
          count++;
      }

      var policyStateList = [];
      var stateGr = new GlideRecordSecure(this.CMDB_DATA_MANAGEMENT_POLICY_RUNTIME_ATTRIBUTES);
      stateGr.addSetQuery(this.POLICY, policySysIds);
      stateGr.query();
      while (stateGr.next()) {
          var policyId = stateGr.getValue(this.POLICY);
          var status = stateGr.getValue(this.STATUS);
          if (!JSUtil.nil(policyId) && !JSUtil.nil(status))
              policyStateList[policyId] = status;
      }
      for (var i = 0; i < policyList.length; i++) {
          policyList[i].status = policyStateList[policyList[i].sys_id];
      }
      return policyList;
  },

  getPreviewMetadata: function(policyId, encodedQuery, table) {
      if (JSUtil.nil(policyId)) {
          // invalid policy status for a preview
          return {
              error: "Policy ID is required"
          };
      }
      var result = {};
      result.task_count = 0;
      var taskManagementGroupField = null;

      if (table === 'cmdb_ci') {
          taskManagementGroupField = this.MANAGED_BY_GROUP;
          var gr = new GlideRecord(this.CMDB_POLICY_MANAGEMENT_POLICY);
          gr.addQuery(this.SYS_ID, policyId);
          gr.query();
          if (gr.next()) {
              taskManagementGroupField = gr.task_management_group.element + '';
          }
          if (!taskManagementGroupField) {
              taskManagementGroupField = this.MANAGED_BY_GROUP;
          }
      }

      // check for all mbg (total tasks) count including empty
      var gaCi = new GlideAggregate(table);
      gaCi.addEncodedQuery(encodedQuery);
      gaCi.addAggregate(this.COUNT, taskManagementGroupField);
      gaCi.query();
      while (gaCi.next()) {
          result.task_count++;
      }
      return result;
  },

  addCIToExclusionList: function(ciList, policyType) {
      var errorSysIds = [];
      var gr = new GlideRecordSecure(this.CMDB_POLICY_CI_EXCLUSION_LIST);
      for (var i = 0; i < ciList.length; i++) {
          gr.initialize();
          gr.setValue(this.POLICY_TYPE, policyType);
          gr.setValue(this.CI, ciList[i]);
          var sys_id = gr.insert();
          if (JSUtil.nil(sys_id)) {
              errorSysIds.push(ciList[i]);
          }
      }
      return errorSysIds;
  },

  removeCIFromExclusionList: function(ciList, policyType) {
  	var gr = new GlideRecordSecure(this.CMDB_POLICY_CI_EXCLUSION_LIST);
  	gr.addEncodedQuery('ciIN' + ciList.join(',') + '^policy_type=' + policyType);
  	gr.query();
  	gr.deleteMultiple();
  },
  
  isValidTaskDueInDays: function(configureTaskDueDate, taskDueInDays) {
  	if (configureTaskDueDate && (JSUtil.nil(taskDueInDays) || taskDueInDays <= 0)) {
  		return false;
  	}
  	return true;
  },
  
  isFilterValidForCustomRetirement: function(encodedQuery, policyType) {
  	// Validate input
  	if(JSUtil.nil(encodedQuery) || JSUtil.nil(policyType))
  		return false;
  	
  	// Apply this check only for retire,archiev and delete type of policies
  	var corePolicyTypes = [this.CMDB_POLICY_RETIRE_SYS_ID, this.CMDB_POLICY_ARCHIVE_SYS_ID, this.CMDB_POLICY_DELETE_SYS_ID];
  	if(corePolicyTypes.indexOf(policyType) < 0) {
  		// Nothing to check WRT custom retirement fields
  		return true;
  	}

  	// Evaluate encoded query to get classes of all CIs it qualifies
  	var classesFromQuery = [];
  	var grCI = new GlideAggregate('cmdb_ci');
  	grCI.addEncodedQuery(encodedQuery);
  	grCI.groupBy('sys_class_name');
  	grCI.query();
  	while(grCI.next()) {
  		classesFromQuery.push(grCI.getValue('sys_class_name'));
  	}	
  		
  	if(classesFromQuery.length == 0)
  		return true;     // Qualifies no CI, but such empty policies should be valid
  	
  	// Check if any of the classes above are not defined in custom retirement definitions table or cache
  	var notFoundInRetDefCache = [];
  	for(var i=0; i < classesFromQuery.length; i++) {
  		if(sn_cmdb.CMDBRetirementScriptableApi.getSimpleEncodedQuery(classesFromQuery[i]) == '')
  			notFoundInRetDefCache.push(classesFromQuery[i]);
  	}

  	return notFoundInRetDefCache.length == 0;
  },

  createPolicy: function(requestData) {
      var policyDetails = {};
  	
  	var typeInfo = this.getPolicyTypeInfo(requestData.cmdb_policy_type);
  	if (!typeInfo) {
  		policyDetails.error = 'Cannot find policy type';
  		return policyDetails;
  	}
  	
  	if (!this.isValidTaskDueInDays(typeInfo.configureTaskDueDate, requestData.task_due_in_days)) {
  		policyDetails.error = 'Missing or invalid task due in days';
  		return policyDetails;
  	}
  	
  	if (!this.isFilterValidForCustomRetirement(requestData.encoded_query, requestData.cmdb_policy_type)) {
  		var docLink = '<a href="/api/now/v1/context_doc_url/CMDB-Life-Cycle-Rules">' + gs.getMessage("documentation") + '</a>';
  		policyDetails.error = gs.getMessage('CMDB classes covered by this policy do not have matching life-cycle rules for retirement, see {0} for reference', docLink);
  		return policyDetails;
  	}

      var gr = this.updatePolicyGlide(new GlideRecordSecure(this.CMDB_POLICY_MANAGEMENT_POLICY), requestData);
      policyDetails.policySysId = gr.insert();
      if (JSUtil.nil(policyDetails.policySysId)) {
          policyDetails.error = 'Error in creating policy record';
          return policyDetails;
      }

      if (typeInfo.perPolicySchedule) {
          if (JSUtil.nil(requestData.scheduled_job)) {
              policyDetails.error = 'Missing scheduled job info';
              this.deletePolicies([policyDetails.policySysId]);
          }

          policyDetails.policy_execution_job = this.createScheduledJob(requestData.name, policyDetails.policySysId, requestData.scheduled_job);

          if (JSUtil.nil(policyDetails.policy_execution_job)) {
              policyDetails.error = 'Error in creating policy scheduled job';
              this.deletePolicies([policyDetails.policySysId]);
              return policyDetails;
          }

          if (!this.updatePolicyScheduledJobInfo(policyDetails.policySysId, policyDetails.policy_execution_job)) {
              policyDetails.error = 'Cannot update policy scheduled job info';
              return policyDetails;
          }
      }

      policyDetails.stateSysId = this.createPolicyRuntimeAttribs(policyDetails.policySysId, gs.getUserID());
      if (JSUtil.nil(policyDetails.stateSysId)) {
          policyDetails.error = 'Error in creating policy state record';
          this.deletePolicies([policyDetails.policySysId]);
      }

      return policyDetails;
  },

  updatePolicyScheduledJobInfo: function(policySysId, jobId) {
      var policyGr = new GlideRecord(this.CMDB_POLICY_MANAGEMENT_POLICY);
      policyGr.addQuery(this.SYS_ID, policySysId);
      policyGr.query();
      if (policyGr.next()) {
          policyGr.setValue(this.POLICY_EXECUTION_JOB, jobId);
          return policyGr.update();
      }
      return false;
  },

  createScheduledJob: function(policyName, policyId, scheduledJobInfo) {
      var scheduleGr = new GlideRecordSecure(this.CMDB_POLICY_SCHEDULED_JOB);
      scheduleGr.initialize();
      scheduleGr.setValue(this.NAME, policyName + ' Policy Processor');
      scheduleGr.setValue(this.RUN_AS, this.ADMIN_USER_SYS_ID);
      scheduleGr.setValue(this.SCRIPT, 'sn_cmdb_data_manager.CMDBDataManagerScopedScriptableApis.executePolicy("' + policyId + '");');

      var scheduledJobFields = Object.keys(scheduledJobInfo);
      for (var i = 0; i < scheduledJobFields.length; i++) {
          var field = scheduledJobFields[i];
          var value = scheduledJobInfo[field];
          scheduleGr.setValue(field, value);
      }

      return scheduleGr.insert();
  },

  getPolicyTypeInfo: function(policyTypeId) {
      var info = {};
      var typeGr = new GlideRecordSecure(this.CMDB_POLICY_TYPE);
      typeGr.addQuery(this.SYS_ID, policyTypeId);
      typeGr.query();
      if (typeGr.next()) {
          info.perPolicySchedule = typeGr.getDisplayValue(this.PER_POLICY_SCHEDULE) === 'true' ? true : false;
          info.configureTaskDueDate = typeGr.getDisplayValue(this.CONFIGURE_TASK_DUE_DATE) === 'true' ? true : false;
          info.isSubflowOptional = typeGr.getDisplayValue(this.IS_SUBFLOW_OPTIONAL) === 'true' ? true : false;
          return info;
      }
      return null;
  },

  updatePolicyGlide: function(policyGr, requestData) {
      policyGr.setValue(this.NAME, requestData.name);
      policyGr.setValue(this.CMDB_POLICY_TYPE, requestData.cmdb_policy_type);
      policyGr.setValue(this.SUBFLOW, requestData.subflow);
      policyGr.setValue(this.DESCRIPTION, JSUtil.nil(requestData.description) ? '' : requestData.description);
      policyGr.setValue(this.ENCODED_QUERY, JSUtil.nil(requestData.encoded_query) ? '' : requestData.encoded_query);
      policyGr.setValue(this.ARCHIVE_FOR_DAYS, JSUtil.nil(requestData.archive_for_days) ? '' : requestData.archive_for_days);
      policyGr.setValue(this.NEEDS_REVIEW, JSUtil.nil(requestData.needs_review) ? true : requestData.needs_review); // true is considered default
      if (this.isValidTaskDueInDays(true, requestData.task_due_in_days)) {
          policyGr.setValue(this.TASK_DUE_IN_DAYS, requestData.task_due_in_days);
      }
      policyGr.setValue(this.TASK_MANAGEMENT_GROUP, requestData.task_management_group);
      policyGr.setValue(this.TABLE, JSUtil.nil(requestData.table) ? '' : requestData.table);
      policyGr.setValue(this.USER_GROUP, JSUtil.nil(requestData.user_group) ? '' : requestData.user_group);
      return policyGr;
  },

  updatePolicy: function(requestData, policySysId) {
  	if (this.isDependentTypePolicy(policySysId)) {
  		return this.updateDependentTypePolicy(requestData, policySysId);
  	}
      var policyDetails = {};
      var currentScheduledJobId = '';
      var gr = this.getRecords(this.CMDB_POLICY_MANAGEMENT_POLICY, policySysId);
      if (!gr.next()) {
          policyDetails.error = 'policy not found';
          return policyDetails;
      } else {

  		currentScheduledJobId = gr.getValue(this.POLICY_EXECUTION_JOB);
  	}
  	
  	var typeInfo = this.getPolicyTypeInfo(requestData.cmdb_policy_type);
  	if (!typeInfo) {
  		policyDetails.error = 'Cannot find policy type';
  		return policyDetails;
  	}
  	
  	if (!this.isValidTaskDueInDays(typeInfo.configureTaskDueDate, requestData.task_due_in_days)) {
  		policyDetails.error = 'Missing or invalid task due in days';
  		return policyDetails;
  	}
  	
  	if (!this.isFilterValidForCustomRetirement(requestData.encoded_query, requestData.cmdb_policy_type) &&
  			!this.isDependentTypePolicy(policySysId)) {

  		policyDetails.error = 'Check failed for retirement definition based on filter conditions specified';
  		return policyDetails;
  	}
  	
      var policyGr = this.updatePolicyGlide(gr, requestData);
      policyDetails.policySysId = policyGr.update();
      if (JSUtil.nil(policyDetails.policySysId)) {
          policyDetails.error = 'Error in updating policy record';
          return policyDetails;
      }

      if (typeInfo.perPolicySchedule) {
          if (JSUtil.nil(requestData.scheduled_job) || JSUtil.nil(requestData.policy_execution_job)) {
              policyDetails.error = 'Missing scheduled job info';
              return policyDetails;
          }

          if (!this.updateScheduledJob(requestData.policy_execution_job.sys_id, requestData.scheduled_job)) {
              policyDetails.error = 'Error in updating policy scheduled job';
              return policyDetails;
          }
      } else {
          if (currentScheduledJobId) {
              var scheduleGr = new GlideRecord(this.CMDB_POLICY_SCHEDULED_JOB);
              scheduleGr.addQuery(this.SYS_ID, currentScheduledJobId);
              scheduleGr.query();
              if (scheduleGr.next()) {
                  scheduleGr.deleteRecord();
              }
          }
      }

      policyDetails.stateSysId = this.updatePolicyRuntimeAttribs(policyDetails.policySysId, this.DRAFT_STATUS, gs.getUserID());
      if (JSUtil.nil(policyDetails.stateSysId)) {
          policyDetails.error = 'Error in updating policy state record';
      } else {
          policyDetails.status = this.getPolicyStatus(policySysId);
      }
      return policyDetails;
  },

  updateDependentTypePolicy: function(requestData, dependentPolicySysId) {
  	// for dependent type policies only update the task management group and tasks require approval flag
  	var gr = new GlideRecord(this.CMDB_POLICY_MANAGEMENT_POLICY);
  	gr.get(dependentPolicySysId);
  	gr.setValue(this.NEEDS_REVIEW, requestData.needs_review);
  	gr.setValue(this.TASK_MANAGEMENT_GROUP, requestData.task_management_group);
  	gr.update();
  	return this.getPolicy(dependentPolicySysId);
  },

  updateScheduledJob: function(jobId, scheduledJobInfo) {
      var scheduleGr = new GlideRecord(this.CMDB_POLICY_SCHEDULED_JOB);
      scheduleGr.addQuery(this.SYS_ID, jobId);
      scheduleGr.query();
      if (scheduleGr.next()) {
          var scheduledJobFields = Object.keys(scheduledJobInfo);
          for (var i = 0; i < scheduledJobFields.length; i++) {
              var field = scheduledJobFields[i];
              var value = scheduledJobInfo[field];
              scheduleGr.setValue(field, value);
          }

          return scheduleGr.update();
      }
      return false;
  },

  isMandatoryDataAvailable: function(policyDetails) {
  	if (this.isDependentTypePolicy(policyDetails.sys_id))
  		return true;

      if (JSUtil.nil(policyDetails.name) || JSUtil.nil(policyDetails.cmdb_policy_type) || JSUtil.nil(policyDetails.encoded_query))
  		return false;

      var typeInfo = this.getPolicyTypeInfo(policyDetails.cmdb_policy_type);
      if (!typeInfo) {
          return false;
      }
      if (!typeInfo.isSubflowOptional && JSUtil.nil(policyDetails.subflow)) {
          return false;
      }

      if (policyDetails.cmdb_policy_type == this.CMDB_POLICY_ARCHIVE_SYS_ID && JSUtil.nil(policyDetails.archive_for_days)) {
          return false;
      }

      if (policyDetails.cmdb_policy_type == this.CMDB_POLICY_DELETE_RELATED_ITEM_SYS_ID && JSUtil.nil(policyDetails.user_group)) {
          return false;
      }
      return true;
  },

  isNameAvailable: function(name, policySysId) {
      var ga = new GlideAggregate(this.CMDB_POLICY_MANAGEMENT_POLICY);
      ga.addAggregate(this.COUNT);
      ga.addQuery(this.NAME, name);
      if (policySysId) {
          ga.addQuery(this.SYS_ID, "!=", policySysId);
      }
      ga.query();
      if (ga.next()) {
          return parseInt(ga.getAggregate(this.COUNT)) === 0;
      }
      return true;
  },

  getPolicy: function(policySysId) {
      var gr = new GlideRecord(this.CMDB_POLICY_MANAGEMENT_POLICY);
      gr.get(policySysId);

      var policyDetails = {};
      policyDetails.sys_id = gr.getValue(this.SYS_ID);
      policyDetails.name = gr.getValue(this.NAME);
      policyDetails.description = gr.getValue(this.DESCRIPTION);
      policyDetails.encoded_query = gr.getValue(this.ENCODED_QUERY);
      policyDetails.archive_for_days = parseInt(gr.getValue(this.ARCHIVE_FOR_DAYS));
      policyDetails.needs_review = gr.getValue(this.NEEDS_REVIEW);
      policyDetails.status = this.getPolicyStatus(policyDetails.sys_id);
      policyDetails.cmdb_policy_type = {};
      policyDetails.cmdb_policy_type.id = gr.getValue(this.CMDB_POLICY_TYPE);
      policyDetails.cmdb_policy_type.type = gr.cmdb_policy_type.name;
      policyDetails.subflow = {};
      policyDetails.subflow.sys_id = gr.getValue(this.SUBFLOW);
      policyDetails.subflow.name = gr.subflow.name;
      policyDetails.task_due_in_days = parseInt(gr.getValue(this.TASK_DUE_IN_DAYS));
      policyDetails.policy_execution_job = gr.cmdb_policy_type.per_policy_schedule ? this.getScheduledJob(gr.getValue(this.POLICY_EXECUTION_JOB)) : null;
      policyDetails.task_management_group = {};
      policyDetails.task_management_group.sys_id = gr.getValue(this.TASK_MANAGEMENT_GROUP);
      policyDetails.task_management_group.name = gr.task_management_group.element + '';
      policyDetails.table = JSUtil.nil(gr.getValue(this.TABLE)) ? '' : gr.getValue(this.TABLE);
      policyDetails.user_group = JSUtil.nil(gr.getValue(this.USER_GROUP)) ? '' : gr.getValue(this.USER_GROUP);

      return policyDetails;
  },

  getScheduledJob: function(jobId) {
      var scheduledJobGR = new GlideRecordSecure(this.CMDB_POLICY_SCHEDULED_JOB);
      var scheduledJobObj = {};
      scheduledJobGR.get(jobId);
      scheduledJobObj.run_type = scheduledJobGR.getValue(this.RUN_TYPE);
      scheduledJobObj.sys_id = scheduledJobGR.getValue(this.SYS_ID);
      switch (scheduledJobObj.run_type) {
          case this.DAILY:
              return {
                  sys_id: scheduledJobObj.sys_id,
                      run_type: scheduledJobObj.run_type,
                      run_time: scheduledJobGR.getValue(this.RUN_TIME)
              };
          case this.WEEKLY:
              return {
                  sys_id: scheduledJobObj.sys_id,
                      run_type: scheduledJobObj.run_type,
                      run_dayofweek: scheduledJobGR.getValue(this.RUN_DAYOFWEEK),
                      run_time: scheduledJobGR.getValue(this.RUN_TIME)
              };
          case this.MONTHLY:
              return {
                  sys_id: scheduledJobObj.sys_id,
                      run_type: scheduledJobObj.run_type,
                      run_dayofmonth: scheduledJobGR.getValue(this.RUN_DAYOFMONTH),
                      run_time: scheduledJobGR.getValue(this.RUN_TIME)
              };
          case this.ONCE:
              return {
                  sys_id: scheduledJobObj.sys_id,
                      run_type: scheduledJobObj.run_type,
                      run_start: scheduledJobGR.getValue(this.RUN_START)
              };
      }
  },

  getRecords: function(tableName, sysId, fieldName) {
      var gr = new GlideRecord(tableName);
      if (!JSUtil.nil(sysId)) {
          var columnName = JSUtil.nil(fieldName) ? this.SYS_ID : fieldName;
          gr.addQuery(columnName, sysId);
      }

      gr.query();
      return gr;
  },

  getPaginatedRecords: function(tableName, offset, numRows) {
      if (this.maxViewRecords < numRows) {
          gs.logError('Page size specified is greater than maximum records returnable from GlideRecord query (as determined by system property glide.cmdb.data_manager.db.max_view_records). Overiding the page size to the value configured as glide.cmdb.data_manager.db.max_view_records');
          numRows = this.maxViewRecords;
      }

      var gr = new GlideRecord(tableName);
      gr.chooseWindow(offset, offset + numRows, true);
      gr.orderBy('sys_created_on');
      gr.query();
      return gr;
  },

  getPolicyStatus: function(policySysId) {
      if (JSUtil.nil(policySysId))
          return '';
      var gr = new GlideRecordSecure(this.CMDB_DATA_MANAGEMENT_POLICY_RUNTIME_ATTRIBUTES);
      gr.addQuery(this.POLICY, policySysId);
      gr.query();
      if (!gr.next())
          return '';
      return gr.getValue(this.STATUS);
  },

  createPolicyRuntimeAttribs: function(policySysId, runAsUser) {
      var gr = new GlideRecordSecure(this.CMDB_DATA_MANAGEMENT_POLICY_RUNTIME_ATTRIBUTES);
      gr.setValue(this.POLICY, policySysId);
      gr.setValue(this.STATUS, this.DRAFT_STATUS);
      gr.setValue(this.RUN_AS, runAsUser);
      return gr.insert();
  },

  updatePolicyRuntimeAttribs: function(policySysId, policyStatus, runAsUser) {
      if (JSUtil.nil(policySysId))
          return '';
      var gr = new GlideRecord(this.CMDB_DATA_MANAGEMENT_POLICY_RUNTIME_ATTRIBUTES);
      gr.addQuery(this.POLICY, policySysId);
      gr.query();
      if (!gr.next()) {
          var runtimeId = this.createPolicyRuntimeAttribs(policySysId, runAsUser);
          if (JSUtil.nil(runtimeId)) //if creating runtime attributes fails then return
              return '';
          gr.get(runtimeId); //initialize gr
      }

      // Get policy to see if scheduled job is available to mark as active/inactive, dependent upon policyStatus
      var grPolicy = new GlideRecord(this.CMDB_POLICY_MANAGEMENT_POLICY);
      grPolicy.get(policySysId);

      if (!JSUtil.nil(grPolicy) && grPolicy.cmdb_policy_type.per_policy_schedule) {
          var scheduledJobActiveState = {
              active: (policyStatus === this.PUBLISHED_STATUS) ? true : false
          };
          var jobId = grPolicy.getValue(this.POLICY_EXECUTION_JOB);
          this.updateScheduledJob(jobId, scheduledJobActiveState);
      }

      if (!JSUtil.nil(policyStatus)) {
          gr.setValue(this.STATUS, policyStatus);
      }
      if (!JSUtil.nil(runAsUser)) {
          gr.setValue(this.RUN_AS, runAsUser);
      }
      return gr.update();
  },

  setPolicyStatus: function(policySysId, status) {
      var result = {};
      if (JSUtil.nil(policySysId)) {
          result.error = gs.getMessage("The policy ID is missing from the request");
      } else if (!this.isValidStatus(status)) {
          result.error = gs.getMessage("{0} is not a valid policy status", status);
      } else if (!this.isNextStatusValid(policySysId, status)) {
          result.error = gs.getMessage("{0} is not a valid transition from the current policy status", status);
      } else {
          var policyRuntimeSysId = this.updatePolicyRuntimeAttribs(policySysId, status, gs.getUserID());
          if (!policyRuntimeSysId) {
              result.error = "There was an error updating the policy: " + statusRec.getLastErrorMessage();
          } else {
              result.sys_id = policySysId;
              result.status = this.getPolicyStatus(policySysId);
          }
      }
      return result;
  },

  isValidStatus: function(status) {
      return Object.keys(this.NEXT_STATUS_MAP).indexOf(status) >= 0;
  },

  isNextStatusValid: function(policySysId, nextStatus) {
      var currentStatus = this.getPolicyStatus(policySysId);
      return currentStatus == nextStatus || this.NEXT_STATUS_MAP[currentStatus].indexOf(nextStatus) >= 0;
  },

  getTaskToCiTableByTaskId: function(taskId) {
      var gr = new GlideRecord(this.CMDB_DATA_MANAGEMENT_TASK);
      gr.addQuery(this.SYS_ID, taskId);
      gr.query();
      if (gr.next()) {
          var taskToCiTable = gr.policy_id.cmdb_policy_type.task_to_ci_table.name + '';
          var tableGr = new GlideRecord(taskToCiTable);
          if (tableGr.isValid()) {
              return taskToCiTable;
          }
          return '';
      }
      return '';
  },

  getCiCount: function(taskSysId) {
      var taskToCiTable = this.getTaskToCiTableByTaskId(taskSysId);
      if (!taskToCiTable) {
          return -1;
      }

      var countVal = 0;
      var ga = new GlideAggregate(taskToCiTable);
      ga.addAggregate('COUNT');
      ga.addQuery('cmdb_data_management_task', taskSysId);
      ga.query();

      if (ga.next()) {
          countVal = parseInt(ga.getAggregate('COUNT'));
      }

      return countVal;
  },

  getCiSysIds: function(startIndex, endIndex, taskSysId) {
      var ciMap = {};
      var ciSysIds = [];

  	var taskToCiTable = this.getTaskToCiTableByTaskId(taskSysId);
      if (!taskToCiTable) {
          return result;
      }

      var taskToCiGr = new GlideRecord(taskToCiTable);
      taskToCiGr.addQuery('cmdb_data_management_task', taskSysId);
      taskToCiGr.orderBy('sys_id');
      taskToCiGr.chooseWindow(startIndex, endIndex);
      taskToCiGr.query();

      while (taskToCiGr.next()) {
          var ci = '' + taskToCiGr.ci;
          if (!JSUtil.nil(ci))
              ciSysIds.push(ci);
      }

      var ciGr = new GlideRecord('cmdb_ci');
      ciGr.addQuery('sys_id', 'IN', ciSysIds.join(','));
      ciGr.query();

      while (ciGr.next()) {
  		var ciClassName = ciGr.getValue('sys_class_name');
          if (ciMap[ciClassName] == undefined) {
              ciMap[ciClassName] = [];
          }
          ciMap[ciClassName].push(ciGr.getValue('sys_id'));
      }
  	return ciMap;
  },

  fetchCiCount: function(ciMap) {
      var count = 0;
  	Object.keys(ciMap).forEach(function(table) { 
  	count += ciMap[table].length;
  });
  	return count;
  },

  deleteCis: function(ciSysIds) {
      if (ciSysIds === null || ciSysIds.length === 0) {
          return;
      }

      var ciGr = new GlideRecord('cmdb_ci');
      ciGr.addQuery('sys_id', 'IN', ciSysIds.join(','));
      ciGr.query();

      ciGr.deleteMultiple();
  },

  retireCis: function(ciMap) {
      if (Object.keys(ciMap).length === 0)
          return;

      var customRetirementDefinitionMap = sn_cmdb.CMDBRetirementScriptableApi.getAllRetirementDefinitions();
      var classList = Object.keys(ciMap);

      for(var i=0; i<classList.length; i++){
  		var table = classList[i];
          var retireCondition = this.getRetirementCondition(customRetirementDefinitionMap, table);
  		this.handleRetire(table, retireCondition, ciMap[table]);
          }
  },

  getRetirementCondition: function(customRetirementDefinitionMap, table) {
   if (customRetirementDefinitionMap.hasOwnProperty(table)) {
       return String(customRetirementDefinitionMap[table]).replace("^EQ", "");
   } else {
       var parentTables = new LifeCycleUtil().getParents(table);
       for (var j = 0; j < parentTables.length; j++) {
           var parentTable = parentTables[j];
           if (customRetirementDefinitionMap.hasOwnProperty(parentTable) && customRetirementDefinitionMap[parentTable] != null) {
               return String(customRetirementDefinitionMap[parentTable]).replace("^EQ", "");
           }
       }
   }
},

  getRetiredCis: function(ciMap) {
  	var retiredCIs = [];
  	
  	if (Object.keys(ciMap).length === 0)
          return retiredCIs;

  	var tablesStr="";
  	var ciSysIds = "";

      Object.keys(ciMap).forEach(function(table) {
  		tablesStr += table+ ",";
  		ciSysIds += ciMap[table]+ "," ;
  	});
  	
  	var encodedQuery = sn_cmdb.CMDBRetirementScriptableApi.getFullEncodedQuery(tablesStr);
  	encodedQuery += '^sys_idIN' + ciSysIds;
  	retiredCIs = this.filterRetiredCis(encodedQuery);
  	
  	return retiredCIs;
  },
  
  filterRetiredCis: function(encodedQuery) {
  	var retiredCis = [];
  	var ciGr = new GlideRecord(this.CMDB_CI);
      ciGr.addEncodedQuery(encodedQuery);
      ciGr.query();
  	while(ciGr.next()){
  		retiredCis.push(ciGr.getValue(this.SYS_ID));
  	}
  	return retiredCis;
  },
  
  handleRetire: function(table, retirementCondition, cis) {
      var retirementFieldsAndValues = this.getRetirementFieldsAndValues(retirementCondition);
      this.processRetire(table, retirementFieldsAndValues, cis);
  },
  
  getRetirementFieldsAndValues: function(retirementCondition){
  	var retirementFieldsAndValues = {};
  	var elements = retirementCondition.split("^");
      for (var i = 0; i < elements.length; i++) {
          var columnConditions = elements[i].split("=");
          retirementFieldsAndValues[columnConditions[0]] = columnConditions[1];
      }
  	return retirementFieldsAndValues;
  },

  processRetire: function(table, retirementFieldsAndValues, cis) {
      var ciGr = new GlideRecord(table);
      ciGr.addQuery('sys_id', 'IN', cis.join(','));
      Object.keys(retirementFieldsAndValues).forEach(function(column) {
          ciGr.setValue(column, retirementFieldsAndValues[column]);
      });
      ciGr.updateMultiple();
  },

  getBatchCount: function(ciCount, batchSize) {
      if (ciCount === 0)
          return 0;

      return Math.ceil((ciCount / batchSize));
  },

  getBatchSize: function() {
      var DEF_BATCH_SIZE = 1000;
      var batchSize = gs.getProperty('glide.cmdb.data.manager.delete.batch.size') || DEF_BATCH_SIZE;
      return batchSize;
  },

  getArchiveBatchSize: function() {
      var def_archive_max_limit = 1000;
      var batchSize = gs.getProperty('glide.db.archive.rule.api_max_records') || def_archive_max_limit;
      return batchSize;
  },

  getArchiveDurationInDays: function() {
      var def_duartion_days = 120;
      var days = gs.getProperty('glide.cmdb.data_manager.default_archive_time') || def_duartion_days;
      return days;
  },

  chunkArray: function(inputArray, chunkSize) {
      var chunkedArray = [];
      var index = 0,
          arrLen = inputArray.length;
      while (index < arrLen) {
          chunkedArray.push(inputArray.slice(index, chunkSize + index));
          index += chunkSize;
      }
      return chunkedArray;
  },

  getFilteredCis: function(ciSysIds) {
      var result = {};
      result.validCis = ciSysIds;
      result.excludedCis = [];

      if (!ciSysIds || ciSysIds.length === 0) {
          result.validCis = [];
          return result;
      }

      var tableList = [];
      if (gs.tableExists(this.INCIDENT_TABLE)) {
          tableList.push(this.INCIDENT_TABLE);
      }

      if (gs.tableExists(this.PROBLEM_TABLE)) {
          tableList.push(this.PROBLEM_TABLE);
      }

      if (gs.tableExists(this.CHANGE_REQUEST_TABLE)) {
          tableList.push(this.CHANGE_REQUEST_TABLE);
      }

      if (tableList.length === 0) {
          return result;
      }

      var arrayUtil = new ArrayUtil();
      var gr = new GlideRecord('task');
      gr.addQuery('sys_class_name', 'IN', tableList.join(','));
      gr.addQuery('cmdb_ci', 'IN', ciSysIds.join(','));
      gr.query();

      while (gr.next()) {
          var sysClassName = '' + gr.sys_class_name;
          var state = '' + gr.state;
          var ci = '' + gr.cmdb_ci;

          if (this.filterCiFromDeletion(sysClassName, state)) {
              result.excludedCis.push(ci);
          }
      }

      // Remove excluded CIs from valid CIs
      if (result.excludedCis.length > 0) {
          result.validCis = arrayUtil.diff(result.validCis, result.excludedCis);
      }

      return result;
  },

  filterCiFromDeletion: function(sysClassName, state) {
      var result = true;

      if (sysClassName === this.INCIDENT_TABLE) {
          result = this.INCIDENT_OPEN_STATES.indexOf(state) !== -1;
      } else if (sysClassName === this.PROBLEM_TABLE) {
          result = this.PROBLEM_OPEN_STATES.indexOf(state) !== -1;
      } else if (sysClassName === this.CHANGE_REQUEST_TABLE) {
          result = this.CHANGE_REQUEST_OPEN_STATES.indexOf(state) !== -1;
      }

      return result;
  },

  archiveCis: function(ciSysIds, durationInDays) {
      if (ciSysIds === null || ciSysIds.length === 0) {
          return;
      }

      var ar = new GlideArchiver();
      if (durationInDays == 0) {
          ar.archive('cmdb_ci', ciSysIds, '', null);
      } else {
          ar.archive('cmdb_ci', ciSysIds, '', new GlideDuration(86400000 * durationInDays));
      }
      return ar.getArchiveChunkIds();
  },

  createTaskToArchiveChunk: function(taskId, chunkId) {
      var grTaskChunk = new GlideRecordSecure(this.CMDB_TASK_TO_ARCHIVE_CHUNK);
      grTaskChunk.initialize();
      grTaskChunk.setValue('cmdb_task', taskId);
      grTaskChunk.setValue('archive_run_chunk', chunkId);
      grTaskChunk.setValue('run_chunk_status', 1);
      return grTaskChunk.insert();
  },

  reflectChunkStatus: function(chunkId) {
      var updateTask = false;
  	
      // Update chunk status in CMDB Task to Archive Chunk table
      var grTaskToChunk = new GlideRecordSecure(this.CMDB_TASK_TO_ARCHIVE_CHUNK);
      if (!grTaskToChunk.get('archive_run_chunk', chunkId)) {
          gs.warn('Failed to get record with chunkId:' + chunkId + ' from CMDB Taks to Archive Chunk table', this.LOG_SOURCE);
          return;
      }

      var taskId = grTaskToChunk.getValue('cmdb_task');
      var chunk = new GlideRecord(this.SYS_ARCHIVE_RUN_CHUNK);
      if (!chunk.get(chunkId)) {
          gs.warn('Failed to get record with sys_id:' + chunkId + ' from archive run chunk', this.LOG_SOURCE);
          return;
      }
  	
      if (chunk.getDisplayValue('state') == 'Completed') {
          grTaskToChunk.setDisplayValue('run_chunk_status', 'Completed'); // Completed
      } else
          grTaskToChunk.setDisplayValue('run_chunk_status', 'Failed'); // Failed

      grTaskToChunk.update();
  	
  	this.updateArchiveTaskSuccessPercent(taskId, chunk);

      // Check if it's last chunk of this task
      var graTaskToChunk = new GlideAggregate(this.CMDB_TASK_TO_ARCHIVE_CHUNK);
      graTaskToChunk.addQuery('cmdb_task', taskId);
      graTaskToChunk.addAggregate('COUNT');
      graTaskToChunk.groupBy('run_chunk_status');
      graTaskToChunk.query();
      var statuses = {
          'Submitted': 0,
          'Completed': 0,
          'Failed': 0
      };
      while (graTaskToChunk.next()) {
          statuses[graTaskToChunk.getDisplayValue('run_chunk_status')] = graTaskToChunk.getAggregate('COUNT');
      }

      var taskStatus = 3; // 'Closed Complete'
      if (statuses['Submitted'] == 0) {
          if (statuses['Failed'] > 0)
              taskStatus = 4; // 'Closed Incomplete'
          updateTask = true;
      }

      // Update task status
      if (updateTask) {
          var grCMDBTask = new GlideRecordSecure(this.CMDB_DATA_MANAGEMENT_TASK);
          if (!grCMDBTask.get(taskId)) {
              gs.warn('Failed to get the CMDB task with sys_id:' + taskId);
              return;
          }
          grCMDBTask.setValue('state', taskStatus);
  		if(taskStatus == 3)
  			grCMDBTask.setValue('success_percent',100);
          grCMDBTask.update();
      }
  },

  updateArchiveTaskSuccessPercent : function(taskId, chunk) {

  	var ciTotalCount = this.getCiCount(taskId);
  	var chunkCis = chunk.getValue('keys').split(',');
  	var archivedCiCount = chunkCis.length;

  	var grCi = new GlideRecord(this.CMDB_CI);
  	grCi.addQuery('sys_id','IN',chunkCis);
  	grCi.query();
  	var failureCount = parseInt(grCi.getRowCount());

  	var grTask = new GlideRecordSecure(this.CMDB_DATA_MANAGEMENT_TASK);
  	if(!grTask.get(taskId)) {
  		gs.warn("Failed to get the task to update 'Success Percent' field for sys_id:" + taskId, this.LOG_SOURCE);
  		return;
  	}

  	if(failureCount > 0) {
  		archivedCiCount -= failureCount;
  		var failedCIs = [];
  		while(grCi.next()) {
  			failedCIs.push(grCi.getValue('sys_id'));
  		}
  		grTask.work_notes = 'Failed to archive CIs with following sys_ids: ' + failedCIs;
  	}	
  	grTask.success_percent += (archivedCiCount*100)/ciTotalCount;
  	grTask.update();
  },

  getTaskToDocumentSysIds: function(startIndex, endIndex, taskSysId, taskToDocumentTable) {
      var sysIds = [];
      var sysId = '';

      var gr = new GlideRecord(taskToDocumentTable);
      gr.addQuery('cmdb_data_management_task', taskSysId);
      gr.orderBy('sys_id');
      gr.chooseWindow(startIndex, endIndex);
      gr.query();

      while (gr.next()) {
          sysId = gr.getValue('related_entry_ci');
          if (!JSUtil.nil(sysId))
              sysIds.push(sysId);
      }
      return sysIds;
  },

  getRelatedTabelName: function(taskId, taskToDocumentTable) {
      var gr = new GlideRecord(taskToDocumentTable);
      gr.get("cmdb_data_management_task", taskId);

      return gr.getValue('table');
  },

  deleteRelatedTableCIs: function(relatedTableName, sysIds) {
      var gr = new GlideRecord(relatedTableName);
      gr.addQuery(this.SYS_ID, 'IN', sysIds.join(','));
      gr.query();

      gr.deleteMultiple();
  },

  getDataManagerUserGroups: function() {
      var data_manager_user = 'c627309e53722010af64ddeeff7b1232';
      var groupSysId = [];
      var userSysId = [];
      var role = 'role';

      //get the groups which has data_manager_user role associated 
      var gr = new GlideRecord('sys_group_has_role');
      gr.addQuery(role, data_manager_user);
      gr.query();
      while (gr.next()) {
          groupSysId.push(gr.getValue('group'));
      }
      //get the users who are a data_manager_user
      gr = new GlideRecord('sys_user_has_role');
      gr.addQuery(role, data_manager_user);
      gr.query();
      while (gr.next()) {
          userSysId.push(gr.getValue('user'));
      }

      gr = new GlideRecord('sys_user_grmember');
      gr.addQuery('user', 'IN', userSysId);
      gr.query();
      while (gr.next()) {
          groupSysId.push(gr.getValue('group'));
      }
      //get the group name & sys_ids (union of sys_group_has_role & sys_user_has_role)
      var groups = [];
      gr = new GlideRecord('sys_user_group');
      gr.addQuery(this.SYS_ID, 'IN', groupSysId);
      gr.addQuery('active', 'true');
      gr.orderBy('name');
      gr.query();
      while (gr.next()) {
          groups.push({
              value: gr.getUniqueValue(),
              name: gr.getValue('name')
          });
      }
      return groups;
  },

  getRelatedEntryTables: function() {
      var gr = new GlideAggregate('cmdb_related_entry');
      gr.addQuery('active', true);
      gr.groupBy('table');
      gr.query();
      var relatedEntryTables = [];
      var tableName = '';
      while (gr.next()) {
          tableName = gr.getValue('table');
          relatedEntryTables.push({
              'tableName': tableName,
              'tableLabel': GlideTableDescriptor.get(tableName).getLabel()
          });
      }
      relatedEntryTables.sort(function(left, right) {
          return (left.tableLabel === right.tableLabel ? 0 : (left.tableLabel > right.tableLabel ? 1 : -1));
      });
      return relatedEntryTables;
  },

  isDependentTypePolicy: function(policySysId) {
  	var dependentPolicySysIds = [
  		'523284e87301011026f6aa114df6a753',
  		'54618b76533130108cabddeeff7b12c2',
  		'e23d4a9973f2701026f6aa114df6a741'
  	];
  	return policySysId && dependentPolicySysIds.indexOf(policySysId) > -1;
  },

  type: 'CMDBDataManagerHelper'
};

Sys ID

4a4834d8775220108043270bba1061cb

Offical Documentation

Official Docs: