Name

sn_risk_advanced.RiskAssessmentUtilsBase

Description

No description available

Script

var RiskAssessmentUtilsBase = Class.create();
RiskAssessmentUtilsBase.prototype = {

  initialize: function() {},

  validateResidualAssessment: function(current) {
      return this._validateResidualAssessment(current);
  },

  triggerRiskAssessment: function(risk, ram, assessor, approver, assessorType, approverType, daysToOverdue) {
      return this._triggerRiskAssessment(risk, ram, assessor, approver, assessorType, approverType, daysToOverdue);
  },

  approveSysApprovalRecord: function(asmt) {
      return this._approveSysApprovalRecord(asmt);
  },

  rejectSysApprovalRecord: function(asmt) {
      return this._rejectSysApprovalRecord(asmt);
  },

  showInitiateAssessmentAction: function(current) {
      return this._showInitiateAssessmentAction(current);
  },

  checkRAMExistsForRisk: function(riskId) {
      return this._checkRAMExistsForRisk(riskId);
  },

  createRiskResponseTask: function(current, previous) {
      return this._createRiskResponseTask(current, previous);
  },

  updateExceptionState: function(record, table, fieldName, state) {
      return this._updateExceptionState(record, table, fieldName, state);
  },

  checkAssessorRole: function(userId) {
      return this._checkAssessorRole(userId);
  },

  checkApproverRole: function(userId) {
      return this._checkApproverRole(userId);
  },

  checkAssessorRolePresent: function(user) {
      return this._checkAssessorRolePresent(user);
  },

  checkApproverRolePresent: function(user) {
      return this._checkApproverRolePresent(user);
  },

  checkUserPresent: function(userId) {
      return this._checkUserPresent(userId);
  },

  getNextScheduleDate: function(frequency) {
      return this._getNextScheduleDate(frequency);
  },

  getAssessmentDueDate: function(dueDate) {
      return this._getAssessmentDueDate(dueDate);
  },

  checkAssessmentTypeState: function(ram) {
      return this._checkAssessmentTypeState(ram);
  },

  createRiskAssessment: function(sourceRecord, assessorId, approverId, isAssessorUser, isApproverUser) {
      return this._createRiskAssessment(sourceRecord, assessorId, approverId, isAssessorUser, isApproverUser);
  },

  getRiskAssessmentResults: function(sourceRecord) {
      return this._getRiskAssessmentResults(sourceRecord);
  },

  copyAssessmentResultsToSourceRecord: function(riskAssessmentInstance) {
      return this._copyAssessmentResultsToSourceRecord(riskAssessmentInstance);
  },

  updateRiskResponseTask: function(riskAssessmentInstance) {
      return this._updateRiskResponseTask(riskAssessmentInstance);
  },

  markAssess: function(asmtIDs, scopeID) {
      return this._markAssess(asmtIDs, scopeID);
  },

  markApproved: function(asmtIDs) {
      return this._markApproved(asmtIDs);
  },

  getEntityClassName: function(entityId) {
      return this._getEntityClassName(entityId);
  },

  //Fetches Assessment data for given Assessment Instance and Assessment Type
  getAssessmentResponseData: function(assessmentInstanceId, assessmentType, ramId) {
      return this._getAssessmentResponseData(assessmentInstanceId, assessmentType, ramId);
  },

  getAssociatedRisk: function(profileId, statementId) {
      return this._getAssociatedRisk(profileId, statementId);
  },

  createRisk: function(riskObject) {
      return this._createRisk(riskObject);
  },

  getAssessmentInstance: function(riskId, scopeId) {
      return this._getAssessmentInstance(riskId, scopeId);
  },

  getAssessmentInstanceForAnyObject: function(tableName, recordId) {
      return this._getAssessmentInstanceForAnyObject(tableName, recordId);
  },

  addAssessors: function(instance, scope, riskId) {
      return this._addAssessors(instance, scope, riskId);
  },

  createAssessmentInstance: function(instanceObject) {
      return this._createAssessmentInstance(instanceObject);
  },

  createAssessmentQuestions: function(assessmentInstanceId) {
      return this._createAssessmentQuestions(assessmentInstanceId);
  },

  hasInherentAssessment: function(ramID) {
      return this._hasInherentAssessment(ramID);
  },

  hasControlAssessment: function(ramID) {
      return this._hasControlAssessment(ramID);
  },

  hasResidualAssessment: function(ramID) {
      return this._hasResidualAssessment(ramID);
  },

  showReturnToInherentButton: function(currentAsmt) {
      return this._showReturnToInherentButton(currentAsmt);
  },

  showReturnToControlButton: function(currentAsmt) {
      return this._showReturnToControlButton(currentAsmt);
  },

  showReturnToResidualButton: function(currentAsmt) {
      return this._showReturnToResidualButton(currentAsmt);
  },

  showResidualAsmtButton: function(currentAsmt) {
      return this._showResidualAsmtButton(currentAsmt);
  },

  showControlAsmtButton: function(currentAsmt) {
      return this._showControlAsmtButton(currentAsmt);
  },

  assess: function(currentAsmt) {
      this._assess(currentAsmt);
  },

  showRespond: function(currentAsmt) {
      return this._showRespond(currentAsmt);
  },

  respond: function(currentAsmt) {
      this._respond(currentAsmt);
  },

  requestApproval: function(currentAsmt) {
      return this._requestApproval(currentAsmt);
  },

  canPerformAssessment: function(currentAsmt) {
      return this._canPerformAssessment(currentAsmt);
  },

  canAssess: function(currentAsmt) {
      return this._canAssess(currentAsmt);
  },

  canApprove: function(currentAsmt) {
      return this._canApprove(currentAsmt);
  },

  createIndividualControlAssessmentResponses: function(controlIds, ramId, assessmentInstance, entityId, riskId) {
      return this._createIndividualControlAssessmentResponses(controlIds, ramId, assessmentInstance, entityId, riskId);
  },

  createIndividualControlAssessmentResponsesFromControls: function(controlIds, ramId, assessmentInstance, entityId, riskId) {
      return this._createIndividualControlAssessmentResponsesFromControls(controlIds, ramId, assessmentInstance, entityId, riskId);
  },

  canWriteAssessmentInstance: function(assessmentInstanceId) {
      return this._canWriteAssessmentInstance(assessmentInstanceId);
  },

  createControlAndItsResponse: function(controlObject) {
      return this._createControlAndItsResponse(controlObject);
  },

  getAssociatedControls: function(assessmentInstanceId) {
      return this._getAssociatedControls(assessmentInstanceId);
  },

  getValidControls: function(assessmentInstanceId) {
      return this._getValidControls(assessmentInstanceId);
  },

  getAssociatedControlObjectives: function(assessmentInstanceId) {
      return this._getAssociatedControlObjectives(assessmentInstanceId);
  },

  removeIndividualControlAssessmentResponses: function(assessmentInstanceId, controlIds) {
      return this._removeIndividualControlAssessmentResponses(assessmentInstanceId, controlIds);
  },

  getControlClassifications: function() {
      return this._getControlClassifications();
  },

  sendAssessmentsByFrequency: function() {
      this._sendAssessmentsByFrequency();
  },

  getClosedAssessments: function(asmtIDs, scopeID) {
      return this._getClosedAssessments(asmtIDs, scopeID);
  },

  createNewAsmtInstance: function(assessmentIdsInCompletedState) {
      return this._createNewAsmtInstance(assessmentIdsInCompletedState);
  },

  getDueDate: function(asmt) {
      return this._getDueDate(asmt);
  },


  getRelatedRatingCriterias: function(ramReference, assessmentTypeName) {
      return this._getRelatedRatingCriterias(ramReference, assessmentTypeName);
  },

  generateResponsesForReTriggeredAsmts: function(prevAsmt, currAsmt) {
      this._generateResponsesForReTriggeredAsmts(prevAsmt, currAsmt);
  },

  getRecordWithSysId: function(sysId, tableName) {
      return this._getRecordWithSysId(sysId, tableName);
  },

  clearFactorResponses: function(asmt, asmtType) {
      this._clearFactorResponses(asmt, asmtType);
  },

  clearTargetAssessmentResponses: function(asmt) {
      this._clearTargetAssessmentResponses(asmt);
  },

  saveMitigationCtrlAndResidualRiskFlags: function(asmtId, state, isMitigationControlsFlagSet, isResidualRiskFlagSet) {
      this._saveMitigationCtrlAndResidualRiskFlags(asmtId, state, isMitigationControlsFlagSet, isResidualRiskFlagSet);
  },

  canReassess: function(currentAsmt) {
      return this._canReassess(currentAsmt);
  },

  filterOverriddenAssessments: function() {
      return this._filterOverriddenAssessments();
  },

  createSimilarAnyObjectAsmt: function(asmtForAnyObject) {
      this._createSimilarAnyObjectAsmt(asmtForAnyObject);
  },

  showRequestApproval: function(assessmentInstance) {
      return this._showRequestApproval(assessmentInstance);
  },

  showMarkComplete: function(assessmentInstance) {
      return this._showMarkComplete(assessmentInstance);
  },

  setAsmtStatetoCancelled: function(ramID) {
      this._setAsmtStatetoCancelled(ramID);
  },

  setAsmtStateFromMonitorToClosed: function(ramID) {
      this._setAsmtStateToClose(ramID);
  },

  cancelAssessments: function(assessmentsArray) {
      return this._cancelAssessments(assessmentsArray);
  },

  cancelAnyObjectAssessment: function(tableName, recordId) {
      return this._cancelAnyObjectAssessment(tableName, recordId);
  },

  createAssessmentInstanceFromRisks: function(riskIds, scopeId, entityId) {
      return this._createAssessmentInstanceFromRisks(riskIds, scopeId, entityId);
  },

  deleteInvalidAssessmentInstance: function() {
      return this._deleteInvalidAssessmentInstance();
  },

  getIndividualControlAssessmentFactor: function(ramId) {
      return this._getIndividualControlAssessmentFactor(ramId);
  },

  createRiskControlRelation: function(riskId, controlId) {
      return this._createRiskControlRelation(riskId, controlId);
  },

  setAssessorFromMultiple: function(asmt) {
      return this._setAssessorFromMultiple(asmt);
  },

  getAssessmentIdBasedOnApprover: function() {
      return this._getAssessmentIdBasedOnApprover();
  },

  getAssessmentIdBasedOnApprovedRecord: function() {
      return this._getAssessmentIdBasedOnApprovedRecord();
  },

  createIndividualControlChildResponses: function(groupFactor, assessmentInstanceId, control) {
      this._createIndividualControlChildResponses(groupFactor, assessmentInstanceId, control);
  },

  getInprogressStateOfRiskAssessment: function() {
      return this._getInprogressStateOfRiskAssessment();
  },

  getIncompleteStatesOfRiskAssessment: function() {
      return this._getIncompleteStatesOfRiskAssessment();
  },

  getMonitorCloseAndCancelStateOfRiskAssessment: function() {
      return this._getMonitorCloseAndCancelStateOfRiskAssessment();
  },

  getActiveRiskAssessmentState: function() {
      return this._getActiveRiskAssessmentState();
  },

  checkifRAMHasInProgressAssessments: function(ramId) {
      return this._checkifRAMHasInProgressAssessments(ramId);
  },

  _checkifRAMHasInProgressAssessments: function(ramId) {
      var asmtInstance = new GlideRecord('sn_risk_advanced_risk_assessment_instance');
      asmtInstance.addQuery('risk_assessment_methodology', ramId);
      asmtInstance.query();
      var inProgressAsmtStates = this.getIncompleteStatesOfRiskAssessment();
      while (asmtInstance.next()) {
          if (inProgressAsmtStates.indexOf(asmtInstance.getValue("state")) != -1) {
              return true;
          }
      }
      return false;
  },

  _getActiveRiskAssessmentState: function() {

      return ["2", "3", "4", "5", "6", "7", "10"];
  },

  _getInprogressStateOfRiskAssessment: function() {

      return ["2", "3", "4", "5", "10"];
  },

  _getIncompleteStatesOfRiskAssessment: function() {

      return ["2", "3", "4", "5", "6", "10"];
  },

  _getMonitorCloseAndCancelStateOfRiskAssessment: function() {
      return ["7", "8", "9"];
  },

  hasTargetAssessment: function(ramID, assessmentId) {
      return this._hasTargetAssessment(ramID, assessmentId);
  },

  _getAssessmentIdBasedOnApprover: function() {
      var asmtId = [];
      var approvalRec = new GlideRecord("sysapproval_approver");
      approvalRec.addQuery("state", "requested");
      approvalRec.addQuery("source_table", "sn_risk_advanced_risk_assessment_instance");
      approvalRec.addQuery("approver", "IN", (new sn_grc.GRCUtils().getMyApprovals() + ''));
      approvalRec.query();
      while (approvalRec.next()) {
          asmtId.push(approvalRec.getValue("document_id"));
      }

      return asmtId;
  },

  _getAssessmentIdBasedOnApprovedRecord: function() {
      var asmtId = [];
      var approvalRec = new GlideRecord("sysapproval_approver");
      approvalRec.addQuery("source_table", "sn_risk_advanced_risk_assessment_instance");
      approvalRec.addQuery("approver", "IN", (new sn_grc.GRCUtils().getMyApprovals() + ''));
      var rec = approvalRec.addQuery("state", "approved");
      rec.addOrCondition("state", "rejected");
      approvalRec.query();
      while (approvalRec.next()) {
          asmtId.push(approvalRec.getValue("document_id"));
      }

      return asmtId;
  },

  getAllSimulatedAssessments: function(ramId) {
      return this._getAllSimulatedAssessments(ramId);
  },

  checkIfRiskAssessmentExists: function(ramId, assessmentOn, assessedOn) {
      return this._checkIfRiskAssessmentExists(ramId, assessmentOn, assessedOn);
  },

  deleteIfSimulatedRiskAssessmentExists: function(assessmentId) {
      return this._deleteIfSimulatedRiskAssessmentExists(assessmentId);
  },

  deleteAllSimulatedAssessments: function(ramId) {
      return this._deleteAllSimulatedAssessments(ramId);
  },

  getSimulatedAssessmentsCount: function(ramId) {
      return this._getSimulatedAssessmentsCount(ramId);
  },

  _setAssessorFromMultiple: function(asmt) {
      var user = (asmt.assessor_user + '').split(",");
      var index = 0;
      while (index < user.length) {
          if ((new sn_grc.GRCUtils().getMyAssignments() + '').includes(user[index] + '')) {
              return user[index] + '';
          }
          index++;
      }
      return gs.getUserID();
  },

  getRiskResponseData: function(sysId) {
      var instance = new GlideRecord('sn_risk_advanced_risk_assessment_instance');
      if (instance.get(sysId) && instance.risk_assessment_methodology.enable_risk_response_workflow)
          return this._getRiskResponseData(instance);
      return null;
  },

  findFinalAsmtState: function(assessmentInstance) {
      return this._findFinalAsmtState(assessmentInstance);
  },

  addApprovers: function(assessmentInstance, scope) {
      return this._addApprovers(assessmentInstance, scope);
  },

  getAssessorManager: function(instance) {
      return this._getAssessorManager(instance);
  },

  getSupportingDataAttachmentId: function(assessmentResponseId) {
      return this._getSupportingDataAttachmentId(assessmentResponseId);
  },

  reassess: function(assessmentId) {
      return this._reassess(assessmentId);
  },

  hasOpenAssessment: function(asmt) {
      return this._hasOpenAssessment(asmt);
  },

  canReassign: function(asmt) {
      return this._canReassign(asmt);
  },

  getApprovalLevelRecords: function(riskAsmtId) {
      return this._getApprovalLevelRecords(riskAsmtId);
  },

  hasActiveAssessments: function(riskId) {
      return this._hasActiveAssessments(riskId);
  },

  _hasActiveAssessments: function(riskId) {
      var assessment = new GlideAggregate('sn_risk_advanced_risk_assessment_instance');
      assessment.addQuery('risk', riskId);
      assessment.addQuery('state', 'IN', (this._getActiveRiskAssessmentState()));
      assessment.addQuery("risk_assessment_methodology.state", "2");
      assessment.addAggregate('COUNT');
      assessment.query();
      assessment.next();
      return assessment.getAggregate('COUNT') > 0;
  },

  _getApprovalLevelRecords: function(riskAsmtId) {
      var levelInfo = "";
      var infoObject = {};
      var apprLevelRecords = [];
      var apprLevelId = [];
      var approvalLevelInfo = new GlideRecord("sn_risk_advanced_risk_assessment_instance_approval");
      approvalLevelInfo.addQuery("risk_assessment_instance", riskAsmtId);
      approvalLevelInfo.addQuery("state", "!=", "no_longer_required");
      approvalLevelInfo.orderByDesc("sys_created_on");
      approvalLevelInfo.orderBy("level");
      approvalLevelInfo.query();
      while (approvalLevelInfo.next()) {
          if (levelInfo.includes(approvalLevelInfo.getValue("level"))) {
              break;
          } else {
              levelInfo += approvalLevelInfo.getValue("level") + ',';
          }
          var recordDetails = {};
          recordDetails.name = approvalLevelInfo.getValue("name");
          recordDetails.state = approvalLevelInfo.getValue("state");
          recordDetails.level = approvalLevelInfo.getValue("level");
          apprLevelId.push(approvalLevelInfo.getUniqueValue());
          apprLevelRecords.push(recordDetails);
      }

      apprLevelRecords.sort(function(a, b) {
          return a.level == b.level ? 0 : +(a.level > b.level) || -1;
      });
      infoObject.sysIdList = apprLevelId.toString();
      infoObject.apprLevelRecordsList = apprLevelRecords;
      return infoObject;
  },

  _canReassign: function(asmt) {
      return asmt.source_record != '' && asmt.state == '0' && (!new sn_risk_advanced.RiskAssessmentUtils().checkAssessorRole(asmt.assessor_user) || (asmt.approver_user && !new sn_risk_advanced.RiskAssessmentUtils().checkApproverRole(asmt.approver_user)));
  },

  _approveSysApprovalRecord: function(asmt) {
      var approvalRec = new GlideRecord("sysapproval_approver");
      approvalRec.addQuery("document_id", asmt.getUniqueValue());
      approvalRec.addQuery("state", "requested");
      approvalRec.addQuery("approver", "IN", (new sn_grc.GRCUtils().getMyApprovals() + ''));
      approvalRec.query();
      while (approvalRec.next()) {
          approvalRec.setValue("state", "approved");
          if (asmt.getValue("approver_comments")) {
              approvalRec.setValue("comments", asmt.getValue("approver_comments"));
          }
          approvalRec.update();
      }
  },

  _rejectSysApprovalRecord: function(asmt) {

      var approvalRec = new GlideRecord("sysapproval_approver");
      approvalRec.addQuery("document_id", asmt.getUniqueValue());
      approvalRec.addQuery("state", "requested");
      approvalRec.addQuery("approver", "IN", (new sn_grc.GRCUtils().getMyApprovals() + ''));
      approvalRec.query();
      while (approvalRec.next()) {
          approvalRec.setValue("state", "rejected");
          approvalRec.update();
      }
      //To update modal window comment on risk assessment activity log.
      asmt.update();
      return true;
  },

  _reassess: function(assessmentId) {
      var newAssessmentId = null;
      var assessmentUtils = new sn_risk_advanced.RiskAssessmentUtils();
      var asmt = new GlideRecord('sn_risk_advanced_risk_assessment_instance');
      asmt.get(assessmentId);
      if (asmt.source_record != '') {
          newAssessmentId = assessmentUtils.createSimilarAnyObjectAsmt(asmt);
      } else if (asmt.entity_1 != '') {
          newAssessmentId = assessmentUtils.createNewAsmtInstance([assessmentId])[0];
          assessmentUtils.markAssess(newAssessmentId);
      }
      return newAssessmentId;
  },

  _getRiskResponseData: function(instance) {
      var checkedResponses = {};
      var uncheckedResponses = {};
      var obj, data = {};
      var userResponse = instance.getValue('risk_response');
      var choices = new sn_grc.GRCChoiceUtils().getLocalizedChoices('sn_risk_advanced_risk_assessment_instance', 'risk_response');
      for (var choiceValue in choices) {
          var choice = choices[choiceValue];
          choice.optionChecked = (gs.nil(userResponse) ? false : (userResponse.indexOf(choice.value) != '-1'));
          choice = this._getRiskResponseSysid(instance, choice);
          choice.optionChecked ? (checkedResponses[choice.value] = choice) : (uncheckedResponses[choice.value] = choice);
      }
      data.selectedResponses = checkedResponses;
      data.unselectedResponses = uncheckedResponses;
      data.savedResponse = userResponse;
      data.comments = instance.getValue('risk_response_justification');
      data.canWrite = this._canWriteAssessmentInstance(instance.getUniqueValue());
      return data;
  },

  _getRiskResponseSysid: function(instance, obj) {
      var responseType = obj.value;
      var map = {
          "Accept": "sn_risk_acceptance_task",
          "Avoid": "sn_risk_avoidance_task",
          "Mitigate": "sn_risk_mitigation_task",
          "Transfer": "sn_risk_transfer_task"
      };
      obj.taskTable = map[responseType];
      obj.taskId = -1;
      var responseTask = new GlideRecord('sn_risk_response_task');
      responseTask.addQuery('state', '!=', '7');
      responseTask.addQuery('risk_assessment_instance', instance.getUniqueValue());
      responseTask.addQuery('sys_class_name', map[responseType]);
      responseTask.orderByDesc('sys_created_on');
      responseTask.query();
      if (responseTask.next()) {
          obj.taskId = responseTask.getUniqueValue();
          var gr = new GlideRecord(responseTask.getValue('sys_class_name'));
          gr.get(responseTask.getUniqueValue());
          obj.canRead = gr.canRead();
          obj.canWrite = gr.canWrite();
          obj.canDelete = gr.canDelete();
      }
      return obj;
  },

  _deleteInvalidAssessmentInstance: function() {
      var asmt = new GlideRecord("sn_risk_advanced_risk_assessment_instance");
      asmt.addQuery("source_record", "!=", "");
      asmt.query();

      while (asmt.next()) {
          var record = new GlideRecord(asmt.table + '');
          record.addQuery('sys_id', asmt.source_record + '');
          record.query();
          if (!record.hasNext()) {
              asmt.deleteRecord();
          }
      }
  },

  _createAssessmentInstanceFromRisks: function(riskIds, scopeId, entityId) {
      var riskStatementIds = [];
      var response = {
          riskStatements: [],
          failedInstances: 0,
          asmtsInProgressCount: 0
      };
      var failedInstanceCount = 0;
      var asmtsInProgressCount = 0;
      var i;
      var scope = new GlideRecord('sn_risk_advanced_risk_assessment_scope');
      scope.get(scopeId);
      for (i = 0; i < riskIds.length; i++) {
          var risk = new GlideRecord('sn_risk_risk');
          risk.get(riskIds[i]);

          if (!risk.statement.nil() && risk.instance) {
              riskStatementIds.push(risk.statement + '');
          }
          var assessmentInstanceId = this.getAssessmentInstance(riskIds[i], scopeId);
          if (assessmentInstanceId == null) {
              var instanceObj = {};
              instanceObj.risk = riskIds[i];
              instanceObj.assessment_scope = scopeId;
              instanceObj.entity_1 = entityId;
              instanceObj.risk_assessment_methodology = scope.risk_assessment_methodology;
              this.addAssessors(instanceObj, scope, riskIds[i]);
              this.addApprovers(instanceObj, scope);
              assessmentInstanceId = this._createAssessmentInstance(instanceObj);

              if (assessmentInstanceId == null) {
                  failedInstanceCount++;
                  continue;
              }

              this._createAssessmentQuestions(assessmentInstanceId);
          } else if (assessmentInstanceId.assessment_scope == '') {
              asmtsInProgressCount++;
              assessmentInstanceId.assessment_scope = scopeId;
              assessmentInstanceId.next_schedule_date = this._getNextScheduleDate(scope.reassessment_frequency + '');
              assessmentInstanceId.update();

          }

      }

      response.riskStatements = riskStatementIds;
      response.failedInstances = failedInstanceCount;
      response.asmtsInProgressCount = asmtsInProgressCount;
      return response;
  },

  showCreateFromLibrary: function(current, parent) {
      return this._showCreateFromLibrary(current, parent);
  },

  showAdhocRisk: function(current, parent) {
      return this._showAdhocRisk(current, parent);
  },

  sendDailyNotificationReminder: function() {
      return this._sendDailyNotificationReminder();
  },

  _cancelAnyObjectAssessment: function(tableName, recordId) {
      var response = {
          errorMessage: '',
          successMessage: ''
      };
      var instanceId = this._getAssessmentInstanceForAnyObject(tableName, recordId);
      if (instanceId == null) {
          response.errorMessage = gs.getMessage('Risk assessment does not exist.');
          return response;
      }
      var assessmentInstance = new GlideRecord('sn_risk_advanced_risk_assessment_instance');
      if (assessmentInstance.get(instanceId)) {
          assessmentInstance.setValue('state', '9');
          if (assessmentInstance.update() == null) {
              response.errorMessage = gs.getMessage('Error cancelling the risk assessment.');
              return response;
          }
          this._cancelRiskResponseTasks(assessmentInstance.getUniqueValue());
      } else {
          response.errorMessage = gs.getMessage('Risk assessment does not exist.');
          return response;
      }

      response.successMessage = gs.getMessage('Risk assessment cancelled successfully.');
      return response;
  },

  _cancelAssessments: function(assessmentsArray) {
      var cancelledArray = [];
      var cancelledAsmts = 0;
      var cancellationCount = new GlideAggregate("sn_risk_advanced_risk_assessment_instance");
      cancellationCount.addQuery('sys_id', 'IN', assessmentsArray);
      cancellationCount.addQuery('state', 'NOT IN', this._getMonitorCloseAndCancelStateOfRiskAssessment());
      cancellationCount.addAggregate('COUNT');
      cancellationCount.query();
      if (cancellationCount.next()) {
          cancelledAsmts = cancellationCount.getAggregate('COUNT');
          var query = cancellationCount.getEncodedQuery();
          var asmt = new GlideRecord("sn_risk_advanced_risk_assessment_instance");
          asmt.addEncodedQuery(query);
          asmt.query();
          while (asmt.next()) {
              asmt.setValue('state', '9');
              asmt.update();
              cancelledArray.push(asmt.getUniqueValue());
          }
      }
      this._cancelRiskResponseTasks(cancelledArray);
      return cancelledAsmts;
  },

  _cancelRiskResponseTasks: function(assessmentsArray) {
      var responseTasks = new GlideRecord('sn_risk_response_task');
      responseTasks.addQuery('risk_assessment_instance.sys_id', 'IN', assessmentsArray);
      responseTasks.query();
      responseTasks.setValue('state', '7');
      responseTasks.updateMultiple();
  },

  _showMarkComplete: function(assessmentInstance) {
      return (assessmentInstance.approver_user == '' && assessmentInstance.approver_group == '' && (assessmentInstance.approver_type != '3' || this.getAssessorManager(assessmentInstance) == '')) && (assessmentInstance.state == '10' || (this._riskRespondNotRequired(assessmentInstance))) && (new sn_grc.GRCUtils().getMyAssignments() + '').includes(assessmentInstance.assessor_user + '');

  },

  _showRequestApproval: function(assessmentInstance) {
      return ((assessmentInstance.state == 5 && assessmentInstance.sub_state == "") || (assessmentInstance.sub_state == "0" && ((assessmentInstance.state >= 2 && assessmentInstance.state <= 5) || assessmentInstance.state == 10)) || this._riskRespondNotRequired(assessmentInstance)) && (new sn_grc.GRCUtils().getMyAssignments() + '').includes(assessmentInstance.assessor_user + '');
  },

  _getEntityClassName: function(entityId) {
      var gr = new GlideRecord('sn_grc_profile');
      gr.get(entityId);
      var entityClassName = gr.getDisplayValue('profile_class');
      return entityClassName;
  },

  _updateExceptionState: function(record, table, fieldName, state) {
      var gr = new sn_grc.GRCExceptionUtils();
      var exp = gr.getLatestException(table, record, fieldName, "1");
      if (!gs.nil(exp))
          gr.updateExceptionRecordState(exp.getUniqueValue(), state);
  },

  _checkAssessmentTypeState: function(ram) {
      var gr = new GlideRecord('sn_risk_advanced_assessment_type');
      gr.addQuery('state', '2');
      gr.addQuery('risk_assessment_methodology', ram.getUniqueValue());
      gr.query();
      return gr.hasNext();
  },

  _createRiskAssessment: function(sourceRecord, assessorId, approverId, isAssessorUser, isApproverUser) {
      if (gs.nil(isAssessorUser))
          isAssessorUser = true;
      if (gs.nil(isApproverUser))
          isApproverUser = true;

      var result = {};
      if (sourceRecord != '') {
          var ram = new GlideRecord('sn_risk_advanced_risk_assessment_methodology');
          ram.addQuery('table_name', sourceRecord.getTableName());
          ram.addQuery('state', '2');
          ram.query();
          if (!ram.next()) {
              result.status = 0;
              result.errorMsg = gs.getMessage('There are no published risk assessment methodologies for this table. Contact your risk administrator for details.');
              return result;
          } else {
              if (assessorId != '') {
                  var assessor;
                  if (isAssessorUser)
                      assessor = this._checkUserPresent(assessorId);
                  else
                      assessor = this._checkGroupPresent(assessorId);
                  if (!assessor) {
                      result.status = 0;
                      result.errorMsg = gs.getMessage('Cannot create risk assessment. Please provide a valid assessor.');
                      return result;
                  }
              } else {
                  result.status = 0;
                  result.errorMsg = gs.getMessage("Please provide assessor to create a risk assessment.");
                  return result;
              }

              if (approverId != '') {
                  var approver;
                  if (isApproverUser)
                      approver = this._checkUserPresent(approverId);
                  else
                      approver = this._checkGroupPresent(approverId);
                  if (!approver) {
                      result.status = 0;
                      result.errorMsg = gs.getMessage('Cannot create risk assessment. Please provide a valid approver.');
                      return result;
                  }
              }

              var asmtId = this.getAssessmentInstanceForAnyObject(sourceRecord.getTableName(), sourceRecord.getUniqueValue());
              var url = '/sn_risk_advanced_risk_assessment_instance.do?sys_id=';


              if (asmtId == null) {
                  var ramId = ram.getUniqueValue();
                  var instanceObj = {};
                  instanceObj.risk_assessment_methodology = ramId;
                  if (isAssessorUser)
                      instanceObj.assessor_user = assessorId;
                  else {
                      instanceObj.assessor_group = assessorId;
                      instanceObj.assessor_type = '2';
                  }
                  if (isApproverUser)
                      instanceObj.approver_user = approverId;
                  else {
                      instanceObj.approver_group = approverId;
                      instanceObj.approver_type = '2';
                  }
                  instanceObj.source_record = sourceRecord.getUniqueValue();
                  instanceObj.table = sourceRecord.getTableName();
                  var hasAssessorException = (!assessorId || (assessor && ((isAssessorUser && !this._checkAssessorRolePresent(assessor)) || (!isAssessorUser && !this._checkAssessorUserGroupRole(assessor)))));
                  var hasApproverException = (approver && ((isApproverUser && !this._checkApproverRolePresent(approver)) || (!isApproverUser && !this._checkApproverUserGroupRole(approver))));

                  if (!hasAssessorException && !hasApproverException) {
                      instanceObj.state = '1';
                      instanceObj.next_schedule_date = this._getNextScheduleDate(ram.getValue('reassessment_frequency'));
                      instanceObj.asmt_due_date = this._getAssessmentDueDate(ram.getValue('days_to_overdue'));
                      if (isAssessorUser)
                          instanceObj.orignal_assessor_user = assessorId;
                      else
                          instanceObj.orignal_assessor_group = assessorId;
                      if (isApproverUser)
                          instanceObj.orignal_approver_user = approverId;
                      else
                          instanceObj.orignal_approver_group = approverId;
                  } else {
                      if (hasAssessorException) {
                          result.status = 0;
                          result.errorMsg = gs.getMessage('Cannot create risk assessment. Please provide the sn_risk_advanced.ara_assessor role to the assessor of this assessment.');
                          return result;
                      }
                      if (hasApproverException) {
                          result.status = 0;
                          result.errorMsg = gs.getMessage('Cannot create risk assessment. Please provide the sn_risk_advanced.ara_approver role to the approver of this assessment.');
                          return result;
                      }
                  }

                  asmtId = this.createAssessmentInstance(instanceObj);
                  if (asmtId == null) {
                      result.status = 0;
                      result.errorMsg = gs.getMessage('Risk assessment could not be created.');
                      return result;
                  }

                  this.createAssessmentQuestions(asmtId);

                  var assessmentInstance = new GlideRecord('sn_risk_advanced_risk_assessment_instance');
                  assessmentInstance.get(asmtId);


                  var link1 = '<a target="_blank" href="' + url + asmtId + '">' + assessmentInstance.getValue('number') + '</a>';
                  result.status = 200;
                  result.asmtId = asmtId;
                  result.msg = gs.getMessage('Risk assessment created successfully. {0}', [link1]);
                  return result;
              } else {
                  var asmtInstance = new GlideRecord('sn_risk_advanced_risk_assessment_instance');
                  asmtInstance.get(asmtId);

                  var link = ' <a target="_blank" href="' + url + asmtId + '">' + asmtInstance.getValue('number') + '</a>';
                  result.status = 200;
                  result.msg = gs.getMessage('Risk assessment already exists. {0}', [link]);
                  result.asmtId = asmtId;
                  return result;
              }
          }
      } else {
          result.status = 0;
          result.errorMsg = gs.getMessage('Assessment object cannot be empty. Contact your risk administrator for more details.');
          return result;
      }
  },

  _getRiskAssessmentResults: function(sourceRecord) {
      var result = {};
      if (sourceRecord != '') {
          var ram = new GlideRecord('sn_risk_advanced_risk_assessment_methodology');
          ram.addQuery('table_name', sourceRecord.getTableName());
          ram.query();
          if (!ram.next()) {
              result.status = 0;
              result.errorMsg = gs.getMessage('Risk Assessment Methodology is not configured for this table.');
              this.createException(sourceRecord, "", result.errorMsg);
              return result;
          } else if (ram.getValue('state') == '3') {
              result.errorMsg = gs.getMessage('There are no active risk assessment methodologies for this table. Contact your risk administrator for details.');
              this.createException(sourceRecord, "", result.errorMsg);
              return result;
          } else if (ram.getValue('state') == '1') {
              result.errorMsg = gs.getMessage('There are no published risk assessment methodologies for this table. Contact your risk administrator for details.');
              this.createException(sourceRecord, "", result.errorMsg);
              return result;
          } else {
              var asmt = new GlideRecord("sn_risk_advanced_risk_assessment_instance");
              asmt.addQuery('table', sourceRecord.getTableName());
              asmt.addQuery('source_record', sourceRecord.getUniqueValue());
              asmt.addQuery('state', '7');
              asmt.query();
              if (!asmt.hasNext()) {
                  result.status = 0;
                  result.errorMsg = gs.getMessage('Either the assessment does not exist or the risk assessment is not in the Monitor state.');
                  return result;
              } else {
                  asmt.next();
                  result = {
                      inherent_risk_score: asmt.getValue('summary_inherent_risk_score'),
                      inherent_ale: asmt.final_inherent_ale.getReferenceCurrencyCode() + ';' + asmt.final_inherent_ale.getReferenceValue(),
                      control_effectiveness_score: asmt.getValue('summary_control_effectiveness_score'),
                      residual_risk_score: asmt.getValue('summary_residual_risk_score'),
                      residual_ale: asmt.final_residual_ale.getReferenceCurrencyCode() + ';' + asmt.final_residual_ale.getReferenceValue(),
                      target_risk_score: asmt.getValue('summary_target_risk_score'),
                      target_ale: asmt.final_target_ale.getReferenceCurrencyCode() + ';' + asmt.final_target_ale.getReferenceValue(),
                      status: 200
                  };

                  return result;
              }

          }
      } else {
          result.status = 0;
          result.errorMsg = gs.getMessage('Assessment object cannot be empty. Contact your risk administrator for more details.');
          return result;
      }
  },

  _copyAssessmentResultsToSourceRecord: function(asmtInstance) {

      var record = new GlideRecord(asmtInstance.getValue('table'));
      record.get(asmtInstance.getValue('source_record'));

      var asmtType = new GlideRecord('sn_risk_advanced_assessment_type');
      asmtType.addQuery('risk_assessment_methodology', asmtInstance.getValue('risk_assessment_methodology'));
      asmtType.query();
      if (asmtType.hasNext()) {
          while (asmtType.next()) {
              if (asmtType.getValue('name') == "Inherent Assessment") {

                  var inherentType = new GlideRecord('sn_risk_advanced_inherent_assessment');
                  inherentType.get(asmtType.getUniqueValue());

                  var inherentScore = inherentType.getValue('inherent_risk_rating');
                  var inherentAle = inherentType.getValue('inherent_ale');

                  if (inherentScore !== '') {
                      record.setValue(inherentScore, asmtInstance.getValue('summary_inherent_risk_score'));
                  }

                  if (inherentAle !== '') {
                      record.setValue(inherentAle, asmtInstance.final_inherent_ale.getReferenceCurrencyCode() + ';' + asmtInstance.final_inherent_ale.getReferenceValue());
                  }
              } else if (asmtType.getValue('name') == "Control Assessment") {
                  var controlType = new GlideRecord('sn_risk_advanced_control_assessment');
                  controlType.get(asmtType.getUniqueValue());

                  var controlScore = controlType.getValue('control_effectiveness_risk_rating');

                  if (controlScore !== '') {
                      record.setValue(controlScore, asmtInstance.getValue('summary_control_effectiveness_score'));
                  }
              } else if (asmtType.getValue('name') == "Residual Assessment") {
                  var residualType = new GlideRecord('sn_risk_advanced_residual_assessment');
                  residualType.get(asmtType.getUniqueValue());

                  var residualScore = residualType.getValue('residual_risk_rating');
                  var residualAle = residualType.getValue('residual_ale');

                  if (residualScore !== '') {
                      record.setValue(residualScore, asmtInstance.getValue('summary_residual_risk_score'));
                  }

                  if (residualAle !== '') {
                      record.setValue(residualAle, asmtInstance.final_residual_ale.getReferenceCurrencyCode() + ';' + asmtInstance.final_residual_ale.getReferenceValue());
                  }
              } else if (asmtType.getValue('name') == "Target Assessment") {

                  var targetType = new GlideRecord('sn_risk_advanced_target_assessment');
                  if (targetType.get(asmtType.getUniqueValue())) {
                      var targetScore = targetType.getValue('target_risk_rating');
                      var targetAle = targetType.getValue('target_ale');

                      if (targetScore !== '') {
                          record.setValue(targetScore, asmtInstance.getValue('summary_target_risk_score'));
                      }

                      if (targetAle !== '') {
                          record.setValue(targetAle, asmtInstance.final_target_ale.getReferenceCurrencyCode() + ';' + asmtInstance.final_target_ale.getReferenceValue());
                      }
                  }


              }

          }

          var result = record.update();

          if (result) {
              return gs.getMessage("Assessment results successfully copied to the {0} table.", [record.getClassDisplayValue()]);
          } else {
              return gs.getMessage("Assessment results could not be copied to the {0} table. Contact risk administrator.", [record.getClassDisplayValue()]);
          }
      }
  },


  _createRiskResponseTask: function(current, previous) {
      var responseList = current.risk_response + '';
      var oldResponseList = previous.risk_response + '';
      var response = responseList.split(",");
      var oldResponse = oldResponseList.split(",");
      var riskId = current.risk + '';

      var name = '';
      if (!gs.nil(riskId)) {
          name = current.getDisplayValue('risk');
      } else {
          name = current.getDisplayValue('source_record');
      }

      var diffFromCurrent = oldResponse.filter(function(el) {
          return response.indexOf(el) < 0;
      });

      var count = 0;
      var riskResponse = new sn_risk.RiskResponse();
      for (var i = 0; i < diffFromCurrent.length; i++) {
          if (diffFromCurrent[i] != '') {
              count++;
              riskResponse.cancelOpenResponseTasks(riskId, diffFromCurrent[i] + '', current.getUniqueValue());
          }
      }

      var diffFromPrevious = response.filter(function(el) {
          return oldResponse.indexOf(el) < 0;
      });

      var t;
      for (i = 0; i < diffFromPrevious.length; i++) {
          if (diffFromPrevious[i] != '') {
              if (diffFromPrevious[i] == 'Accept') {
                  t = new GlideRecord('sn_risk_acceptance_task');
                  t.short_description = "Accept Risk of " + name;
              } else if (diffFromPrevious[i] == 'Transfer') {
                  t = new GlideRecord('sn_risk_transfer_task');
                  t.short_description = "Transfer Risk of " + name;
              } else if (diffFromPrevious[i] == 'Mitigate') {
                  t = new GlideRecord('sn_risk_mitigation_task');
                  t.short_description = "Mitigate Risk of " + name;
              } else if (diffFromPrevious[i] == 'Avoid') {
                  t = new GlideRecord('sn_risk_avoidance_task');
                  t.short_description = "Avoid Risk of " + name;
              }

              t.assigned_to = current.getValue('assessor_user');

              if (!gs.nil(riskId))
                  t.risk = riskId;

              t.state = '1';
              t.risk_assessment_instance = current.getUniqueValue();
              if (t.insert()) {
                  count++;
              }
          }
      }

      return count;
  },

  _updateRiskResponseTask: function(riskAssessmentInstance) {
      var count = 0;
      gr = new GlideRecord('sn_risk_response_task');
      gr.addQuery('state', "1");
      gr.addQuery('risk_assessment_instance', riskAssessmentInstance);
      gr.query();
      while (gr.next()) {
          gr.setValue('state', '2');
          gr.update();
          count++;
      }

      return count;
  },

  _getAssessmentResponseData: function(assessmentInstanceId, assessmentType, ramId) {

      var result = {};
      this.referenceCurrencySymbol = new sn_risk_advanced.GRCRiskEvent().getCurrencySymbol(this._getReferenceCurrencyCode());
      this.currencyCodesSymbolArray = new sn_risk_advanced.GRCRiskEvent().getCurrencyCodesSymbolArray();
      var assessmentRecord = this._getRecordWithSysId(assessmentInstanceId, 'sn_risk_advanced_risk_assessment_instance');
      if (assessmentType == '2') {
          var controlAssessment = this._getControlAssessment(ramId);
          var controlAssessmenType = controlAssessment.control_assessment_methodology == 'individual_control_assessment' ? '2' : '1';
          var isGroupBasedControlAssessment = controlAssessment.overall_effectiveness_factor.sys_class_name == 'sn_risk_advanced_group_factor';
          var shouldConsiderControlWeightage = controlAssessment.getValue('qualitative_scoring_logic') == 'WEIGHTED-AVG';
          if (controlAssessmenType == '2') {
              result = this._getIndividualControlAssessmentResponseData(assessmentInstanceId);
              result.controlAssessmenType = controlAssessmenType;
              result.isAssessmentNotApplicable = assessmentRecord.mitigating_controls_to_assess;
              result.isGroupBasedControlAssessment = isGroupBasedControlAssessment;
              result.shouldConsiderControlWeightage = shouldConsiderControlWeightage;
              result.isAssessmentMandatory = new sn_risk_advanced.AssessmentTypeUtils().getIsAssessmentTypeMandatoryFlag(assessmentInstanceId, assessmentType);
              result.isTargetEnabled = this.hasTargetAssessment(ramId, assessmentInstanceId);
              return result;
          }
          result.controlAssessmenType = controlAssessmenType;
          result.shouldConsiderControlWeightage = shouldConsiderControlWeightage;
          result.isGroupBasedControlAssessment = isGroupBasedControlAssessment;
          result.isAssessmentNotApplicable = assessmentRecord.mitigating_controls_to_assess;
      }

      if (assessmentType == '3') {
          result.isAssessmentNotApplicable = assessmentRecord.residual_risk_not_applicable;
      }

      var groupAssessments = this._getStandAloneAssessments(assessmentInstanceId, assessmentType, true);
      var hasGroupAssessments = groupAssessments.hasNext();
      result.assessmentResponses = [];
      while (groupAssessments.next()) {
          var factor = groupAssessments.getElement('factor').getRefRecord();
          result.assessmentResponses.push(this._generateGroupAssessmentJson(factor, groupAssessments));
          var subFactorAssessments = this._getSubFactorAssessments(groupAssessments.getUniqueValue());
          while (subFactorAssessments.next()) {
              var subFactor = subFactorAssessments.factor.getRefRecord();
              result.assessmentResponses.push(this._generateFactorAssessmentJson(subFactor, subFactorAssessments));
          }
          result.assessmentResponses.push(this._generateGroupResultJson(factor, groupAssessments));
      }

      var individualAssessments = this._getStandAloneAssessments(assessmentInstanceId, assessmentType, false);
      if (hasGroupAssessments && individualAssessments.hasNext()) {
          result.assessmentResponses.push(this._generateOtherJson());
      }
      while (individualAssessments.next()) {
          factor = individualAssessments.getElement('factor').getRefRecord();
          result.assessmentResponses.push(this._generateFactorAssessmentJson(factor, individualAssessments));
      }
      result.canWrite = this._canWriteAssessmentInstance(assessmentInstanceId);
      result.isAssessmentMandatory = new sn_risk_advanced.AssessmentTypeUtils().getIsAssessmentTypeMandatoryFlag(assessmentInstanceId, assessmentType);
      result.isTargetEnabled = this.hasTargetAssessment(ramId, assessmentInstanceId);
      return result;
  },

  _getControlAssessment: function(ramId) {
      var controlAssessment = new GlideRecord('sn_risk_advanced_control_assessment');
      controlAssessment.addQuery('risk_assessment_methodology', ramId);
      controlAssessment.query();
      controlAssessment.next();
      return controlAssessment;
  },

  _getIndividualControlAssessmentResponseData: function(assessmentInstanceId) {
      var assessmentType = '2';
      var result = {};
      var groupAssessments = this._getStandAloneAssessments(assessmentInstanceId, assessmentType, true);
      result.assessmentResponses = [];
      var factor, control = "";
      while (groupAssessments.next()) {
          this._generateIndividualControlResponseObject(result, groupAssessments);
      }
      var individualAssessments = this._getStandAloneAssessments(assessmentInstanceId, assessmentType, false);
      while (individualAssessments.next()) {
          this._generateIndividualControlResponseObject(result, individualAssessments);
      }
      result.canWrite = this._canWriteAssessmentInstance(assessmentInstanceId);
      return result;
  },

  _generateIndividualControlResponseObject: function(result, response) {
      var factor = response.getElement('factor').getRefRecord();
      var control = response.getElement('control').getRefRecord();
      if (factor.sys_class_name == 'sn_risk_advanced_group_factor') {
          result.assessmentResponses.push(this._generateGroupAssessmentJsonForControls(factor, response, control));
          var childResponses = this._getSubFactorAssessments(response.getUniqueValue());
          while (childResponses.next()) {
              var childFactor = childResponses.factor.getRefRecord();
              var factorJson = this._generateFactorAssessmentJson(childFactor, childResponses);
              factorJson.controlId = control.getUniqueValue();
              result.assessmentResponses.push(factorJson);
          }
          result.assessmentResponses.push(this._generateGroupResultJsonForControls(factor, response, control));
      } else {
          result.assessmentResponses.push(this._generateIndividualControlAssessmentResponsesJson(control, factor, response));
      }
  },

  _generateGroupAssessmentJsonForControls: function(factor, assessment, control) {
      var factorJson = this._generateIndividualControlAssessmentResponsesJson(control, factor, assessment);
      factorJson.type = "group";
      factorJson.isGroup = true;
      factorJson.weightage = factorJson.controlWeighting;
      return factorJson;
  },

  _generateGroupResultJsonForControls: function(factor, assessment, control) {
      var factorJson = this._generateIndividualControlAssessmentResponsesJson(control, factor, assessment);
      factorJson.name = "Calculated control effectiveness";
      factorJson.type = "group_result";
      factorJson.weightage = factorJson.controlWeighting;
      this._setGroupFactorFormula(factor, factorJson);
      var factorContribution = factor.getValue('factor_contribution');
      if ((factorContribution == '1' || factorContribution == '3') && !isNaN(factorJson.quantScore)) {
          factorJson.quantScore = this.referenceCurrencySymbol + ' ' + factorJson.quantScore;
      }
      return factorJson;
  },

  _createIndividualControlChildResponses: function(groupFactorResponse) {
      var subFactors = new GlideRecord('sn_risk_advanced_sub_factor');
      subFactors.addQuery('parent', groupFactorResponse.getValue('factor'));
      subFactors.query();
      while (subFactors.next()) {
          var response = new GlideRecord('sn_risk_advanced_risk_assessment_instance_response');
          response.setValue('assessment_instance_id', groupFactorResponse.getValue('assessment_instance_id'));
          response.setValue('assessment_type', 2);
          response.setValue('factor', subFactors.getUniqueValue());
          response.setValue('parent_instance_response', groupFactorResponse.getUniqueValue());
          response.insert();
      }
  },


  _getIndividualControlAssessmentResponsesData: function(assessmentInstanceReponseIds) {
      var result = {};
      result.assessmentResponses = [];
      this.referenceCurrencySymbol = new sn_risk_advanced.GRCRiskEvent().getCurrencySymbol(this._getReferenceCurrencyCode());
      this.currencyCodesSymbolArray = new sn_risk_advanced.GRCRiskEvent().getCurrencyCodesSymbolArray();

      var responses = new GlideRecord('sn_risk_advanced_risk_assessment_instance_response');
      responses.addQuery('sys_id', 'IN', assessmentInstanceReponseIds);
      responses.query();

      while (responses.next()) {
          var control = responses.getElement('control').getRefRecord();
          var factor = responses.getElement('factor').getRefRecord();
          this._generateIndividualControlResponseObject(result, responses);
      }
      return result.assessmentResponses;
  },

  _generateIndividualControlAssessmentResponsesJson: function(control, factor, assessment) {
      var factorJson = {};
      factor.responseId = assessment.getUniqueValue();
      factorJson.name = control.getValue('name');
      factorJson.factorName = factor.getValue('name');
      factorJson.controlId = control.getUniqueValue();
      factorJson.controlWeighting = assessment.getValue('control_weightage');
      if (!gs.nil(factorJson.controlWeighting)) {
          factorJson.controlWeighting += '%';
      }
      factorJson.status = control.getDisplayValue('status');
      factorJson.classification = control.getDisplayValue('classification');
      if (factorJson.classification == '')
          factorJson.classification = "-- None --";
      var controlImportance = control.getValue('key_control');
      if (controlImportance == 1) {
          factorJson.controlImportance = 'Key';
      } else {
          factorJson.controlImportance = 'Non-Key';
      }
      factorJson.weightage = factor.getValue('weighting_factor');
      if (!factorJson.weightage) {
          factorJson.weightage = '100';
      }
      factorJson.weightage += '%';
      factorJson.response = assessment.getValue('factor_response');
      factorJson.responseId = assessment.getUniqueValue();
      factorJson.comments = assessment.getValue('additional_comments');
      factorJson.isMandatory = factor.getValue('mandatory_response');
      factorJson.type = factor.getValue('user_response');
      factorJson.isReadonly = false;
      factorJson.guidance = factor.getValue('guidance');
      factorJson.factorId = factor.getUniqueValue();
      factorJson.factorContribution = factor.getValue('factor_contribution');
      this._setScores(factor, assessment, factorJson);
      this._setFactorRelatedData(factorJson, factor);
      this._setAutomatedFactorInfo(factor, factorJson, assessment);
      if (factorJson.response && factorJson.isMandatory) {
          factorJson.filledClass = "is-filled";
      } else {
          factorJson.filledClass = "";
      }
      return factorJson;
  },

  _getIndividualControlAssessmentResponses: function(assessmentInstanceId) {
      var standAloneAssessments = new GlideRecord('sn_risk_advanced_risk_assessment_instance_response');
      standAloneAssessments.addNotNullQuery('control');
      standAloneAssessments.addQuery('assessment_instance_id', assessmentInstanceId);
      standAloneAssessments.addQuery('assessment_type', '2');
      standAloneAssessments.orderBy('sys_created_on');
      standAloneAssessments.query();
      return standAloneAssessments;
  },

  _canWriteAssessmentInstance: function(assessmentInstanceId) {
      var assessmentInstance = new GlideRecord('sn_risk_advanced_risk_assessment_instance');
      assessmentInstance.get(assessmentInstanceId);
      return assessmentInstance.canWrite() && (new sn_grc.GRCUtils().getMyAssignments() + '').includes(assessmentInstance.assessor_user + '');
  },

  //Fetches Group/Individual Assessments for given Assessment Instance and Assessment Type based on isGroup Parameter
  _getStandAloneAssessments: function(assessmentInstanceId, assessmentType, isGroup) {
      var standAloneAssessments = new GlideRecord('sn_risk_advanced_risk_assessment_instance_response');
      standAloneAssessments.addNullQuery('parent_instance_response');
      if (isGroup) {
          standAloneAssessments.addQuery('factor.sys_class_name', 'sn_risk_advanced_group_factor');
      } else {
          standAloneAssessments.addQuery('factor.sys_class_name', '!=', 'sn_risk_advanced_group_factor');
      }
      standAloneAssessments.addQuery('assessment_instance_id', assessmentInstanceId);
      standAloneAssessments.addQuery('assessment_type', assessmentType);
      standAloneAssessments.orderBy('factor.display_order');
      standAloneAssessments.query();
      return standAloneAssessments;
  },

  //Fetches all sub factor Assessments for a given group Assessment
  _getSubFactorAssessments: function(groupAssessmentId) {
      var subFactorAssessments = new GlideRecord('sn_risk_advanced_risk_assessment_instance_response');
      subFactorAssessments.addQuery('parent_instance_response', groupAssessmentId);
      subFactorAssessments.orderBy('factor.display_order');
      subFactorAssessments.query();
      return subFactorAssessments;
  },

  _retrieveChoices: function(factor) {
      var gr = new GlideRecord("sn_risk_advanced_factor_choice");
      gr.addQuery('factor', factor.getUniqueValue());
      gr.orderBy('score');
      gr.query();
      var choices = [];
      while (gr.next()) {
          var choiceJson = {};
          choiceJson.name = gr.getDisplayValue('display_value');
          choiceJson.value = gr.getValue('score');
          choices.push(choiceJson);
      }
      return choices;
  },

  _generateAssessmentJson: function(factor, assessment) {
      var factorJson = {};
      factorJson.name = factor.getDisplayValue('name');
      factorJson.response = assessment.getValue('factor_response');
      factorJson.responseId = assessment.getUniqueValue();
      factorJson.comments = assessment.getValue('additional_comments');
      factorJson.parent = assessment.getValue('parent_instance_response');
      factorJson.isMandatory = factor.getValue('mandatory_response');
      factorJson.weightage = factor.getValue('weighting_factor') + '%';
      factorJson.factorContribution = factor.getValue('factor_contribution');
      this._setScores(factor, assessment, factorJson);
      return factorJson;
  },

  _setScores: function(factor, assessment, factorJson) {
      factorJson.hasValidQualScore = true;
      factorJson.hasValidQuantScore = true;
      var factorContribution = factor.getValue('factor_contribution');
      if (factorContribution == 1) {
          this._setAssessmentScore(assessment, factorJson, 'quantitative_response', 'quantScore');
          factorJson.qualScore = 'n/a';
          factorJson.weightage = 'n/a';
          factorJson.hasValidQualScore = false;
      } else if (factorContribution == 2) {
          this._setAssessmentScore(assessment, factorJson, 'qualitative_response', 'qualScore');
          factorJson.quantScore = 'n/a';
          factorJson.hasValidQuantScore = false;
      } else {
          this._setAssessmentScore(assessment, factorJson, 'quantitative_response', 'quantScore');
          this._setAssessmentScore(assessment, factorJson, 'qualitative_response', 'qualScore');
      }
      factorJson.hasScore = factorJson.hasValidQualScore || factorJson.hasValidQuantScore;
  },

  _setAssessmentScore: function(assessment, factorJson, columnName, key) {
      var score = assessment.getValue(columnName);
      if (score) {
          if (key == 'qualScore' && assessment.transformation_criteria.display_text) {
              factorJson.qualTransformationDisplayText = assessment.transformation_criteria.display_text;
              factorJson[key] = factorJson.qualTransformationDisplayText + " (" + parseFloat(score).toFixed('2') + ")";
          } else {
              factorJson[key] = parseFloat(score).toFixed('2');
          }
      } else {
          factorJson[key] = '-';
          if (key == "qualScore")
              factorJson.hasValidQualScore = false;
          else
              factorJson.hasValidQuantScore = false;
      }
  },


  _generateGroupAssessmentJson: function(factor, assessment) {
      var factorJson = this._generateAssessmentJson(factor, assessment);
      factorJson.type = "group";
      factorJson.isGroup = true;
      return factorJson;
  },

  _generateFactorAssessmentJson: function(factor, assessment) {
      var factorJson = this._generateAssessmentJson(factor, assessment);
      factorJson.type = factor.getValue('user_response');
      if (factorJson.response && factorJson.isMandatory) {
          factorJson.filledClass = "is-filled";
      } else {
          factorJson.filledClass = "";
      }
      this._setFactorRelatedData(factorJson, factor);
      factorJson.guidance = factor.getValue('guidance');
      factorJson.description = factor.getValue("description");
      factorJson.factorId = factor.getUniqueValue();
      factorJson.isReadonly = false;
      this._setAutomatedFactorInfo(factor, factorJson, assessment);
      var factorContribution = factor.getValue('factor_contribution');
      if (factorJson.type == '4' && (factorContribution == '1' || factorContribution == '3') && !isNaN(factorJson.quantScore))
          factorJson.quantScore = this.referenceCurrencySymbol + ' ' + factorJson.quantScore;
      return factorJson;
  },

  _setAutomatedFactorInfo: function(factor, factorJson, assessment) {
      factorJson.autoamtedFactorData = {};
      var autoamtedFactorData = factorJson.autoamtedFactorData;
      autoamtedFactorData.tableName = factor.getTableName();
      factorJson.isAutomated = this._isAutomatedFactor(factor);
      if (factorJson.isAutomated) {
          factorJson.placeHolder = "";
          if (autoamtedFactorData.tableName == 'sn_risk_advanced_automated_query_factor') {
              autoamtedFactorData.querySource = factor.getValue('table_name');
              if (!gs.nil(autoamtedFactorData.querySource))
                  autoamtedFactorData.querySourceLabel = this._getTableLabel(autoamtedFactorData.querySource);
              else
                  autoamtedFactorData.querySourceLabel = '';
              autoamtedFactorData.filteredByEntity = factor.getValue('filter_by_entity');
              autoamtedFactorData.filteredByRisk = factor.getValue('filter_by_risk');
              autoamtedFactorData.filteredByControl = factor.getValue('filter_by_control');
              autoamtedFactorData.filteredBySource = factor.getValue('filter_by_source');
              if (autoamtedFactorData.filteredByEntity)
                  autoamtedFactorData.filteredByEntityMessage = new sn_grc.GRCUtils().getMessage('automated_popover_content');
              if (!gs.nil(factor.getValue('condition')))
                  autoamtedFactorData.isHavingFilterConditions = true;
          }
          autoamtedFactorData.isSupportingDataEnabled = (factor.getValue('supporting_data') == '1');
          if (autoamtedFactorData.isSupportingDataEnabled)
              autoamtedFactorData.supportingDataAttachmentId = this._getSupportingDataAttachmentId(assessment.getUniqueValue());

          var exceptionUtils = new sn_grc.GRCExceptionUtils();
          var exception;
          if (autoamtedFactorData.tableName == 'sn_risk_advanced_automated_query_factor')
              exception = exceptionUtils.getLatestException('sn_risk_advanced_automated_query_factor', factor.getUniqueValue(), null, '1');
          else
              exception = exceptionUtils.getLatestException('sn_risk_advanced_risk_assessment_instance_response', assessment.getUniqueValue(), null, '1');

          if (gs.nil(exception)) {
              factorJson.isReadonly = true;
              factorJson.hasError = false;
          } else {
              factorJson.isReadonly = false;
              factorJson.hasError = true;
              factorJson.errorId = exception.getValue('number');
              factorJson.exceptionSysId = exception.getUniqueValue();
              factorJson.exceptionTable = "sn_grc_exception";
              var url = '/sn_grc_exception.do?sys_id=' + exception.getUniqueValue();
              var link = '<a target="_blank" class="automated-error-link" href="' + url + '">' + factorJson.errorId + '</a>';
              factorJson.automatedException = gs.getMessage('There was an error ({0}) in automatically calculating the response. Contact risk administrator to resolve the error.', [link]);
          }

      }
  },

  _getTableLabel: function(tableName) {
      var gr = new GlideRecord(tableName);
      return gr.getClassDisplayValue();
  },

  _getSupportingDataAttachmentId: function(assessmentResponseId) {
      var attachment = new GlideSysAttachment();
      var attachments = attachment.getAttachments('sn_risk_advanced_risk_assessment_instance_response', assessmentResponseId);
      if (attachments.next())
          return attachments.getUniqueValue();
      return null;
  },

  _isAutomatedFactor: function(factor) {
      return factor.getTableName() == 'sn_risk_advanced_automated_query_factor' || factor.getTableName() == 'sn_risk_advanced_automated_scripted_factor';
  },

  _setFactorRelatedData: function(factorJson, factor) {
      if (factorJson.type == '1') {
          //Choice
          factorJson.choices = this._retrieveChoices(factor);
      } else if (factorJson.type == '2') {
          //Number
          factorJson.placeHolder = "0";
      } else if (factorJson.type == '3') {
          //Text
          factorJson.qualScore = 'n/a';
          factorJson.quantScore = 'n/a';
          factorJson.weightage = 'n/a';
          factorJson.placeHolder = "Provide response";
      } else if (factorJson.type == '4') {
          //Currency
          factorJson.currencies = this.currencyCodesSymbolArray;
          if (factorJson.response && factorJson.response.length != 0) {
              var cur = factorJson.response.split(";");
              factorJson.responseCurCode = cur[0];
              factorJson.responseCurVal = cur[1];
          } else {
              factorJson.responseCurCode = this._getSessionCurrencyCode();
              factorJson.responseCurVal = null;
          }
          factorJson.placeHolder = "0.00";
      } else if (factorJson.type == '5') {
          //Percentage
          factorJson.placeHolder = "0%";
      }
  },

  _generateGroupResultJson: function(factor, assessment) {
      var factorJson = this._generateAssessmentJson(factor, assessment);
      factorJson.name = "Calculated " + factor.getValue('name');
      factorJson.type = "group_result";
      this._setGroupFactorFormula(factor, factorJson);
      var factorContribution = factor.getValue('factor_contribution');
      if ((factorContribution == '1' || factorContribution == '3') && !isNaN(factorJson.quantScore)) {
          factorJson.quantScore = this.referenceCurrencySymbol + ' ' + factorJson.quantScore;
      }
      return factorJson;
  },


  _setGroupFactorFormula: function(factor, factorJson) {
      var factorContribution = factor.getValue('factor_contribution');
      if (factorContribution == 1) {
          factorJson.quantFormula = this._getGroupFactorFormulaTollTip(factor, 'quantitative_formula');
      } else if (factorContribution == 2) {
          factorJson.qualFormula = this._getGroupFactorFormulaTollTip(factor, 'qualitative_formula');
      } else {
          factorJson.quantFormula = this._getGroupFactorFormulaTollTip(factor, 'quantitative_formula');
          factorJson.qualFormula = this._getGroupFactorFormulaTollTip(factor, 'qualitative_formula');
      }
  },

  _getGroupFactorFormulaTollTip: function(factor, column) {
      if (factor.getValue(column) == 'SCRIPT') {
          return 'Computed Score';
      } else {
          return factor.getDisplayValue(column) + ' of scores';
      }
  },

  _generateOtherJson: function() {
      var factorJson = {};
      factorJson.name = "Other factors";
      factorJson.type = "group";
      return factorJson;
  },

  _getSessionCurrencyCode: function() {
      var gr = new GlideRecord('sn_risk_advanced_risk_assessment_instance');
      gr.initialize();
      return gr.inherent_computed_ale.getSessionCurrencyCode();
  },

  _getReferenceCurrencyCode: function() {
      var gr = new GlideRecord('sn_risk_advanced_risk_assessment_instance');
      gr.initialize();
      return gr.inherent_computed_ale.getReferenceCurrencyCode();
  },

  _getAssociatedControls: function(assessmentInstanceId) {
      var controlIds = [];
      var gr = new GlideRecord('sn_risk_advanced_risk_assessment_instance_response');
      gr.addQuery('assessment_instance_id', assessmentInstanceId);
      gr.addQuery('assessment_type', '2');
      gr.addNotNullQuery('control');
      gr.query();
      while (gr.next()) {
          controlIds.push(gr.getValue('control'));
      }
      return controlIds;
  },

  _getValidControls: function(assessmentInstanceId) {
      var invalidControlIds = this._getAssociatedControls(assessmentInstanceId);
      var instanceRef = new GlideRecord('sn_risk_advanced_risk_assessment_instance');
      instanceRef.get(assessmentInstanceId);
      var controlRef = new GlideRecord('sn_compliance_control');
      controlRef.addQuery('profile', instanceRef.entity_1);
      controlRef.addQuery('sys_id', 'NOT IN', invalidControlIds);
      controlRef.addQuery('state', '!=', 'retired');
      controlRef.query();
      var validControlIds = [];
      while (controlRef.next()) {
          validControlIds.push(controlRef.getUniqueValue());
      }
      return validControlIds;
  },

  _getAssociatedControlObjectives: function(assessmentInstanceId) {
      var controlObjectives = [];
      var gr = new GlideRecord('sn_risk_advanced_risk_assessment_instance_response');
      gr.addQuery('assessment_instance_id', assessmentInstanceId);
      gr.addQuery('assessment_type', '2');
      gr.addNotNullQuery('control');
      gr.addQuery('control.instance', 'true');
      gr.query();
      while (gr.next()) {
          controlObjectives.push(gr.control.content + '');
      }
      return controlObjectives;
  },

  _removeIndividualControlAssessmentResponses: function(assessmentInstanceId, controlIds) {
      var gr = new GlideRecord('sn_risk_advanced_risk_assessment_instance_response');
      gr.addQuery('assessment_instance_id', assessmentInstanceId);
      gr.addQuery('assessment_type', '2');
      gr.addQuery('control', 'IN', controlIds);
      gr.query();
      gr.deleteMultiple();
      return;
  },

  _createIndividualControlAssessmentResponses: function(contentIds, ramId, assessmentInstance, entityId, riskId) {
      var factorId = this._getIndividualControlAssessmentFactor(ramId);
      var responseIds = [];
      var result = {};
      if (factorId) {
          var assessmentInstanceResponse = new GlideRecord('sn_risk_advanced_risk_assessment_instance_response');
          result.newResponsesCount = 0;
          result.existingResponsesCount = 0;
          result.failedResponsesCount = 0;
          result.ignoredResponsesCount = 0;
          for (var i = 0; i < contentIds.length; i++) {
              var controlObjective = this._getRecordWithSysId(contentIds[i], "sn_compliance_policy_statement");
              if (controlObjective.getValue('active') == 0) {
                  result.ignoredResponsesCount++;
                  continue;
              }
              var control = this._getAssociatedControl(contentIds[i], entityId);
              if (!control)
                  control = this._createControl(controlObjective, entityId);
              if (!control) {
                  result.failedResponsesCount++;
                  continue;
              }
              this._createControlObjectiveEntityRelation(contentIds[i], entityId);
              this._createRiskControlRelation(riskId, control.getUniqueValue());
              if (!this._isControlResponseAlreadyExists(control.getUniqueValue(), factorId, '2', assessmentInstance)) {
                  assessmentInstanceResponse.initialize();
                  assessmentInstanceResponse.setValue('control', control.getUniqueValue());
                  assessmentInstanceResponse.setValue('factor', factorId);
                  assessmentInstanceResponse.setValue('assessment_type', '2');
                  assessmentInstanceResponse.setValue('assessment_instance_id', assessmentInstance);
                  var responseId = assessmentInstanceResponse.insert();
                  if (responseId) {
                      result.newResponsesCount++;
                      responseIds.push(responseId);
                  } else
                      result.failedResponsesCount++;
              } else {
                  result.existingResponsesCount++;
              }
          }
          result.assessmentResponses = this._getIndividualControlAssessmentResponsesData(responseIds);
      } else {
          result.error = gs.getMessage('Factor is missing in control assessment');
      }
      return result;
  },


  _createIndividualControlAssessmentResponsesFromControls: function(controlIds, ramId, assessmentInstance, entityId, riskId) {
      var factorId = this._getIndividualControlAssessmentFactor(ramId);
      var responseIds = [];
      var result = {};
      if (factorId) {
          var assessmentInstanceResponse = new GlideRecord('sn_risk_advanced_risk_assessment_instance_response');
          result.newResponsesCount = 0;
          result.existingResponsesCount = 0;
          result.failedResponsesCount = 0;
          result.ignoredResponsesCount = 0;
          var i;
          for (i = 0; i < controlIds.length; i++) {
              var controlReference = new GlideRecord('sn_compliance_control');
              controlReference.get(controlIds[i]);
              var controlObjectiveIds = [];
              controlObjectiveIds.push(controlReference.content + '');

              this._createRiskControlRelation(riskId, controlIds[i]);
              if (!this._isControlResponseAlreadyExists(controlIds[i], factorId, '2', assessmentInstance)) {
                  assessmentInstanceResponse.initialize();
                  assessmentInstanceResponse.setValue('control', controlIds[i]);
                  assessmentInstanceResponse.setValue('factor', factorId);
                  assessmentInstanceResponse.setValue('assessment_type', '2');
                  assessmentInstanceResponse.setValue('assessment_instance_id', assessmentInstance);
                  var responseId = assessmentInstanceResponse.insert();
                  if (responseId) {
                      result.newResponsesCount++;
                      responseIds.push(responseId);
                  } else
                      result.failedResponsesCount++;
              } else {
                  result.existingResponsesCount++;
              }
          }

          for (i = 0; i < controlObjectiveIds.length; ++i) {
              this._createControlObjectiveEntityRelation(controlObjectiveIds[i], entityId);
          }

          result.assessmentResponses = this._getIndividualControlAssessmentResponsesData(responseIds);
      } else {
          result.error = gs.getMessage('Factor is missing in control assessment');
      }
      return result;
  },


  _createControlAndItsResponse: function(controlObject) {
      var result = {};
      var factorId = this._getIndividualControlAssessmentFactor(controlObject.ramId);
      var controlId = this._createStandaloneControl(controlObject);
      if (!controlId) {
          result.success = false;
          return result;
      }
      this._createRiskControlRelation(controlObject.riskId, controlId);
      var assessmentInstanceResponse = new GlideRecord('sn_risk_advanced_risk_assessment_instance_response');
      assessmentInstanceResponse.setValue('control', controlId);
      assessmentInstanceResponse.setValue('factor', factorId);
      assessmentInstanceResponse.setValue('assessment_type', '2');
      assessmentInstanceResponse.setValue('assessment_instance_id', controlObject.assessmentInstance);
      var responseId = assessmentInstanceResponse.insert();
      if (responseId) {
          result.success = true;
          result.assessmentResponses = this._getIndividualControlAssessmentResponsesData([responseId]);
      } else
          result.success = false;
      return result;
  },

  _createStandaloneControl: function(controlObject) {
      var gr = new GlideRecord('sn_compliance_control');
      gr.setValue('name', controlObject.name);
      gr.setValue('profile', controlObject.entityId);
      gr.setValue('owner', controlObject.controlOwner);
      gr.setValue('key_control', controlObject.keyControl);
      gr.setValue('classification', controlObject.classification);
      gr.setValue('description', controlObject.description);
      gr.setValue('instance', false);
      return gr.insert();
  },

  _isControlResponseAlreadyExists: function(controlId, factorId, assessmentType, assessmentInstance) {
      var assessmentInstanceResponse = new GlideRecord('sn_risk_advanced_risk_assessment_instance_response');
      assessmentInstanceResponse.addQuery('control', controlId);
      assessmentInstanceResponse.addQuery('factor', factorId);
      assessmentInstanceResponse.addQuery('assessment_type', '2');
      assessmentInstanceResponse.addQuery('assessment_instance_id', assessmentInstance);
      assessmentInstanceResponse.query();
      return assessmentInstanceResponse.hasNext();
  },

  _getAssociatedControl: function(controlObjectiveId, entityId) {
      var control = new GlideRecord('sn_compliance_control');
      control.addQuery('profile', entityId);
      control.addQuery('content', controlObjectiveId);
      control.query();
      return control.next() ? control : null;
  },

  _getRecordWithSysId: function(sysId, tableName) {
      var record = new GlideRecord(tableName);
      record.get(sysId);
      return record;
  },

  _createControl: function(controlObjective, entityId) {
      var entity = this._getRecordWithSysId(entityId, "sn_grc_profile");
      var control = new GlideRecord('sn_compliance_control');
      control.setValue('profile', entityId);
      control.setValue('content', controlObjective.getUniqueValue());
      control.setValue('classification', controlObjective.getValue('classification'));
      control.setValue('name', controlObjective.getValue('name'));
      control.setValue('owner', entity.getValue('owned_by'));
      control.insert();
      return control;
  },

  _createControlObjectiveEntityRelation: function(controlObjectiveId, entityId) {
      var gr = new GlideRecord('sn_grc_m2m_content_profile');
      gr.addQuery('sn_grc_profile', entityId);
      gr.addQuery('sn_grc_content', controlObjectiveId);
      gr.query();
      if (!gr.next()) {
          gr.initialize();
          gr.setValue('sn_grc_profile', entityId);
          gr.setValue('sn_grc_content', controlObjectiveId);
          return gr.insert();
      }
      return gr.getUniqueValue();
  },

  _createRiskControlRelation: function(riskId, controlId) {
      var gr = new GlideRecord('sn_risk_m2m_risk_control');
      gr.addQuery('sn_risk_risk', riskId);
      gr.addQuery('sn_compliance_control', controlId);
      gr.query();
      if (!gr.next()) {
          gr.setValue('sn_risk_risk', riskId);
          gr.setValue('sn_compliance_control', controlId);
          return gr.insert();
      }
      return gr.getUniqueValue();
  },

  _getControlClassifications: function() {
      var classifications = [];
      var choice = new GlideRecord('sn_grc_choice');
      choice.addQuery('set', 'control_policy_statement');
      choice.addQuery('choice_category', 'Classification');
      choice.orderBy('order');
      choice.query('choice_category', 'Classification');
      while (choice.next()) {
          var classification = {};
          classification.name = choice.getValue('label');
          classification.value = choice.getUniqueValue();
          classifications.push(classification);
      }
      return classifications;
  },

  _createRisk: function(riskObject) {
      var risk = new GlideRecord('sn_risk_risk');
      risk.setValue('profile', riskObject.entityId);
      risk.setValue('statement', riskObject.risk_statement);

      /* name is mandatory to report risk from UI*/
      if (riskObject.name) {
          risk.setValue('name', riskObject.name);
          risk.setValue('owner', riskObject.risk_owner);
          risk.setValue('description', riskObject.description);
      }
      if (riskObject.instance == false) {
          risk.setValue('instance', false);
      }

      return risk.insert();
  },

  _getAssociatedRisk: function(profileId, statementId) {
      var gr = new GlideRecord('sn_risk_risk');
      gr.addQuery('profile', profileId);
      gr.addQuery('content', statementId);
      gr.addQuery('instance', true);
      gr.query();

      if (gr.next())
          return gr.getUniqueValue();
      else
          return null;
  },

  _getAssessmentInstance: function(riskId, scopeId) {
      var scope = new GlideRecord("sn_risk_advanced_risk_assessment_scope");
      scope.get(scopeId);
      var assessmentInstance = new GlideRecord('sn_risk_advanced_risk_assessment_instance');
      assessmentInstance.addQuery('risk', riskId);
      assessmentInstance.addQuery('risk_assessment_methodology', scope.risk_assessment_methodology);
      assessmentInstance.addQuery('state', 'NOT IN', this._getMonitorCloseAndCancelStateOfRiskAssessment());
      assessmentInstance.query();

      if (assessmentInstance.next())
          return assessmentInstance;
      else
          return null;
  },

  _getAssessmentInstanceForAnyObject: function(tableName, recordId) {
      var assessmentInstance = new GlideRecord('sn_risk_advanced_risk_assessment_instance');
      assessmentInstance.addQuery('table', tableName);
      assessmentInstance.addQuery('source_record', recordId);
      assessmentInstance.addQuery('state', 'NOT IN', this._getMonitorCloseAndCancelStateOfRiskAssessment());
      assessmentInstance.query();

      if (assessmentInstance.hasNext()) {
          assessmentInstance.next();
          return assessmentInstance.getUniqueValue();
      } else {
          return null;
      }
  },

  _createAssessmentInstance: function(instanceObject) {
      var assessmentInstance = new GlideRecord('sn_risk_advanced_risk_assessment_instance');
      for (var i in instanceObject) {
          assessmentInstance.setValue(i + '', instanceObject[i] + '');
      }

      var assessmentInstanceId = assessmentInstance.insert();
      return assessmentInstanceId;
  },

  _createAssessmentQuestions: function(assessmentInstanceId) {
      var assessmentInstance = new GlideRecord('sn_risk_advanced_risk_assessment_instance');
      assessmentInstance.get(assessmentInstanceId);

      if (assessmentInstance.risk_assessment_methodology.inherent_risk)
          this._generateAssessment(assessmentInstance, 'sn_risk_advanced_inherent_assessment', '1');

      if (assessmentInstance.risk_assessment_methodology.control_effectiveness)
          this._generateAssessment(assessmentInstance, 'sn_risk_advanced_control_assessment', '2');

      if (assessmentInstance.risk_assessment_methodology.residual_risk)
          this._generateAssessment(assessmentInstance, 'sn_risk_advanced_residual_assessment', '3');
      if (assessmentInstance.risk_assessment_methodology.target_risk)
          this._generateAssessment(assessmentInstance, 'sn_risk_advanced_target_assessment', '4');
  },

  _generateAssessment: function(assessmentInstance, table, assessmentType) {
      var assessment = new GlideRecord(table);
      assessment.addQuery('risk_assessment_methodology', assessmentInstance.risk_assessment_methodology);
      assessment.query();

      if (assessment.next() && this._canCreateFactorResponses(table, assessment)) {
          var m2mFactors = new GlideRecord('sn_risk_advanced_asmt_type_m2m_factor');
          m2mFactors.addQuery('sn_risk_advanced_assessment_type', assessment.getUniqueValue());
          m2mFactors.query();
          while (m2mFactors.next()) {
              if (m2mFactors.sn_risk_advanced_factor.sys_class_name == 'sn_risk_advanced_group_factor') {
                  this._generateGroupFactorResponses(assessmentInstance.getUniqueValue(), m2mFactors, assessmentType);
              } else
                  this._generateSubFactorResponses(assessmentInstance.getUniqueValue(), m2mFactors.sn_risk_advanced_factor, assessmentType);
          }
          //If asmt is based on Individual assessment of controls, get controls associated to the risk and generate responses
      } else if (assessment.control_assessment_methodology == "individual_control_assessment") {
          var m2m = new GlideRecord('sn_risk_m2m_risk_control');
          m2m.addQuery('sn_risk_risk', assessmentInstance.risk);
          m2m.query();
          var controlIds = [];
          var factorId = this._getIndividualControlAssessmentFactor(assessmentInstance.risk_assessment_methodology);
          while (m2m.next()) {
              if (m2m.sn_compliance_control.state != 'retired')
                  this._generateIndividualControlAssessmentResponses(m2m.getValue('sn_compliance_control'), factorId, assessmentInstance.getUniqueValue());
          }
      }
  },

  _canCreateFactorResponses: function(table, assessment) {
      if (table == 'sn_risk_advanced_control_assessment') {
          return assessment.control_assessment_methodology == "control_env_assessment";
      } else if (table == 'sn_risk_advanced_target_assessment') {
          return assessment.state == '2' && (assessment.calculate_based_on == "factor_responses" || assessment.calculate_based_on == "factor_same_as_inherent" || assessment.calculate_based_on == "factor_same_as_residual");
      } else {
          return assessment.calculate_based_on == "factor_responses";
      }
  },

  _generateGroupFactorResponses: function(instanceId, m2mFactors, assessmentType) {
      var response = new GlideRecord('sn_risk_advanced_risk_assessment_instance_response');
      response.setValue('factor', m2mFactors.sn_risk_advanced_factor);
      response.setValue('assessment_instance_id', instanceId);
      response.setValue('assessment_type', assessmentType);
      var groupResponseId = response.insert();
      if (groupResponseId) {
          var subFactors = new GlideRecord('sn_risk_advanced_sub_factor');
          subFactors.addQuery('parent', m2mFactors.sn_risk_advanced_factor);
          subFactors.query();
          while (subFactors.next()) {
              this._generateSubFactorResponses(instanceId, subFactors.getUniqueValue(), assessmentType, groupResponseId);
          }

      }
  },
  _generateSubFactorResponses: function(instanceId, factorId, assessmentType, groupResponse) {
      var response = new GlideRecord('sn_risk_advanced_risk_assessment_instance_response');
      response.setValue('factor', factorId);
      response.setValue('assessment_instance_id', instanceId);

      if (groupResponse)
          response.setValue('parent_instance_response', groupResponse);
      response.setValue('assessment_type', assessmentType);
      response.insert();
  },

  //Generate Responses for Control Assessment if asmt is based on Individual assessment of controls
  _generateIndividualControlAssessmentResponses: function(controlId, factorId, assessmentInstance) {
      if (factorId) {
          var assessmentInstanceResponse = new GlideRecord('sn_risk_advanced_risk_assessment_instance_response');
          if (!this._isControlResponseAlreadyExists(controlId, factorId, '2', assessmentInstance)) {
              assessmentInstanceResponse.initialize();
              assessmentInstanceResponse.setValue('control', controlId);
              assessmentInstanceResponse.setValue('factor', factorId);
              assessmentInstanceResponse.setValue('assessment_type', '2');
              assessmentInstanceResponse.setValue('assessment_instance_id', assessmentInstance);
              assessmentInstanceResponse.insert();
          }
      }
  },

  _addAssessors: function(instance, scope, riskId) {
      if (scope.assessor_type == 1) {
          instance.assessor_user = scope.entity.owned_by;
      } else if (scope.assessor_type == 2) {
          var risk = new GlideRecord('sn_risk_risk');
          risk.get(riskId);
          instance.assessor_user = risk.owner;
      } else if (scope.assessor_type == 3) {
          instance.assessor_user = scope.assessor;
      } else if (scope.assessor_type == 4) {
          instance.assessor_type = 2;
          instance.assessor_group = scope.assessor_group;
      }
  },

  _addApprovers: function(instance, scope) {
      if (scope) {
          if (scope.approver_type == 1) {
              var entityGr = new GlideRecord("sn_grc_profile");
              entityGr.get(instance.entity_1 + '');
              instance.approver_user = entityGr.owned_by;
          } else if (scope.approver_type == 2) {
              instance.approver_type = '3';
          } else if (scope.approver_type == 3) {
              instance.approver_user = scope.approver;
          } else if (scope.approver_type == 4) {
              instance.approver_type = '2';
              instance.approver_group = scope.approver_group;
          }
      }
  },

  _getAssessorManager: function(instance) {
      var user = new GlideRecord("sys_user");
      user.get(instance.assessor_user + '');
      return user.manager + '';
  },

  //This method has to be called with scope or set of assessments from same scope
  _markAssess: function(asmtIDs, scopeID) {
      var asmt = new GlideRecord("sn_risk_advanced_risk_assessment_instance");
      if (scopeID)
          asmt.addQuery('assessment_scope', scopeID);
      else
          asmt.addQuery('sys_id', 'IN', asmtIDs);
      asmt.addQuery('state', '0');
      asmt.query();
      asmt.next();
      var count = asmt.getRowCount();
      var dueDate = '';
      var nextDate = '';
      if (asmt.assessment_scope != '') {
          var frequency = '1';
          if (asmt.isValidRecord())
              frequency = asmt.assessment_scope.reassessment_frequency + '';
          nextDate = this._getNextScheduleDate(frequency);
      }
      // When assessment is created from API, then due date is already computed
      if (asmt.asmt_due_date != '')
          dueDate = asmt.asmt_due_date;
      else
          dueDate = this._getDueDate(asmt);
      //Check if there is assessment in monitor state with next_schedule_date not empty and > Today, if yes set next_schedule_date of current asmt from that asmt else consider recomputed value from scope
      var nextScheduleDate = nextDate;
      var nextScheduleDateOfPrevAsmt = this._getNextScheduleDateOfPrevAsmt(asmt);
      if (nextScheduleDateOfPrevAsmt != '')
          nextScheduleDate = nextScheduleDateOfPrevAsmt;
      this._setValuesToAsmtInReadyToAssessState(asmt, nextScheduleDate, dueDate);
      while (asmt.next()) {
          nextScheduleDate = nextDate;
          nextScheduleDateOfPrevAsmt = this._getNextScheduleDateOfPrevAsmt(asmt);
          if (nextScheduleDateOfPrevAsmt != '')
              nextScheduleDate = nextScheduleDateOfPrevAsmt;
          this._setValuesToAsmtInReadyToAssessState(asmt, nextScheduleDate, dueDate);
      }
      return count;
  },

  _getNextScheduleDateOfPrevAsmt: function(asmtToBeAssessed) {
      //Returns next_schedule_date of prev assessment in Monitor state
      var asmt = new GlideRecord('sn_risk_advanced_risk_assessment_instance');
      asmt.addQuery('active', true);
      asmt.addQuery('risk', asmtToBeAssessed.risk);
      asmt.addQuery('assessment_scope', asmtToBeAssessed.assessment_scope);
      asmt.addQuery('state', '7');
      asmt.addNotNullQuery('next_schedule_date');
      asmt.addQuery('next_schedule_date', '>', new GlideDateTime());
      asmt.query();
      if (asmt.next()) {
          return asmt.next_schedule_date;
      }
      return '';
  },

  _hasInherentAssessment: function(ramID) {
      return this._hasAssessment(ramID, "sn_risk_advanced_inherent_assessment");
  },

  _hasControlAssessment: function(ramID) {
      return this._hasAssessment(ramID, "sn_risk_advanced_control_assessment");
  },

  _hasResidualAssessment: function(ramID) {
      return this._hasAssessment(ramID, "sn_risk_advanced_residual_assessment");
  },

  _hasTargetAssessment: function(ramID, assessmentId) {
      var ram = new GlideRecord('sn_risk_advanced_risk_assessment_methodology');
      ram.get(ramID);
      if (ram.getValue('target_risk') == true) {
          var target = new GlideRecord("sn_risk_advanced_target_assessment");
          target.addQuery("risk_assessment_methodology", ram.getUniqueValue());
          target.query();
          if (target.next()) {
              if (target.state == '2') {
                  if (target.getValue("calculate_based_on") == "overall_assessment")
                      return true;
                  else {
                      var factorResponses = new GlideRecord("sn_risk_advanced_risk_assessment_instance_response");
                      factorResponses.addQuery("assessment_instance_id", assessmentId);
                      factorResponses.addQuery('assessment_type', 4);
                      factorResponses.setLimit(1);
                      factorResponses.query();
                      return factorResponses.hasNext();
                  }
              }
          }
      }
      return false;
  },

  _hasAssessment: function(ramID, asmtClass) {
      var asmtTypes = new GlideRecord("sn_risk_advanced_assessment_type");
      asmtTypes.addQuery("risk_assessment_methodology", ramID);
      asmtTypes.addQuery("sys_class_name", asmtClass);
      asmtTypes.query();
      return asmtTypes.hasNext();
  },

  _showReturnToInherentButton: function(currentAsmt) {
      var hasInherentAsmt = this._hasInherentAssessment(currentAsmt.risk_assessment_methodology);
      var hasControlAsmt = this._hasControlAssessment(currentAsmt.risk_assessment_methodology);
      return hasInherentAsmt && (currentAsmt.state == '3' || (currentAsmt.state == '4' && !hasControlAsmt) || (currentAsmt.state == '5' && !hasControlAsmt && !this._hasResidualAssessment(currentAsmt.risk_assessment_methodology)));
  },

  _showReturnToControlButton: function(currentAsmt) {
      var hasControlAsmt = this._hasControlAssessment(currentAsmt.risk_assessment_methodology);
      return hasControlAsmt && ((currentAsmt.state == '4') || (currentAsmt.state == '5' && !this._hasResidualAssessment(currentAsmt.risk_assessment_methodology)));
  },

  _showReturnToResidualButton: function(currentAsmt) {
      var hasResidualAsmt = this._hasResidualAssessment(currentAsmt.risk_assessment_methodology);
      return currentAsmt.state == '5' && hasResidualAsmt;
  },

  _showResidualAsmtButton: function(currentAsmt) {
      var hasResidualAsmt = this._hasResidualAssessment(currentAsmt.risk_assessment_methodology);
      return hasResidualAsmt && (currentAsmt.state == '3' || (currentAsmt.state == '2' && !this._hasControlAssessment(currentAsmt.risk_assessment_methodology)));
  },

  _showControlAsmtButton: function(currentAsmt) {
      var hasControlAsmt = this._hasControlAssessment(currentAsmt.risk_assessment_methodology);
      return hasControlAsmt && currentAsmt.state == '2';
  },

  _assess: function(currentAsmt) {
      var hasInherentAsmt = this._hasInherentAssessment(currentAsmt.risk_assessment_methodology);
      if (hasInherentAsmt) {
          currentAsmt.state = '2';
      } else {
          var hasControlAsmt = this._hasControlAssessment(currentAsmt.risk_assessment_methodology);
          if (hasControlAsmt) {
              currentAsmt.state = '3';
          } else {
              currentAsmt.state = '4';
          }
      }
      currentAsmt.update();
  },

  _showRespond: function(currentAsmt) {
      return currentAsmt.state == this._findFinalAsmtState(currentAsmt) && currentAsmt.risk_assessment_methodology.enable_risk_response_workflow;
  },

  _findFinalAsmtState: function(currentAsmt) {
      var finalAsmtstate = '';
      var hasTargetAsmt = this._hasTargetAssessment(currentAsmt.getValue('risk_assessment_methodology'), currentAsmt.getUniqueValue());
      if (hasTargetAsmt) {
          finalAsmtstate = '10';
          return finalAsmtstate;
      }
      var hasResidualAsmt = this._hasResidualAssessment(currentAsmt.risk_assessment_methodology);
      if (hasResidualAsmt) {
          finalAsmtstate = '4';
      } else {
          var hasControlAsmt = this._hasControlAssessment(currentAsmt.risk_assessment_methodology);
          if (hasControlAsmt) {
              finalAsmtstate = '3';
          } else {
              finalAsmtstate = '2';
          }
      }
      return finalAsmtstate;
  },

  _riskRespondNotRequired: function(assessmentInstance) {
      return !assessmentInstance.risk_assessment_methodology.enable_risk_response_workflow && this._findFinalAsmtState(assessmentInstance) == assessmentInstance.state;
  },

  _respond: function(currentAsmt) {
      currentAsmt.state = '5';
      currentAsmt.update();
  },

  _requestApproval: function(currentAsmt) {
      currentAsmt.state = "6";
      currentAsmt.update();
      return true;
  },

  _canPerformAssessment: function(currentAsmt) {
      return ((new sn_grc.GRCUtils().getMyAssignments() + '').includes(currentAsmt.assessor_user + ''));

  },

  _canAssess: function(currentAsmt) {

      if (currentAsmt.assessor_user + '' != '') {
          var user = (currentAsmt.assessor_user + '').split(",");
          var index = 0;
          while (index < user.length) {
              if ((new sn_grc.GRCUtils().getMyAssignments() + '').includes(user[index] + '')) {
                  return true;
              }
              index++;
          }
      }
      return (gs.getUser().isMemberOf(currentAsmt.assessor_group + ''));
  },

  _canApprove: function(currentAsmt) {
      var approvalRec = new GlideRecord("sysapproval_approver");
      approvalRec.addQuery("document_id", currentAsmt.getUniqueValue());
      approvalRec.addQuery("state", "requested");
      approvalRec.addQuery("approver", "IN", (new sn_grc.GRCUtils().getMyApprovals() + ''));
      approvalRec.query();
      if (approvalRec.next()) {
          return true;
      }

      return false;
  },

  _getIndividualControlAssessmentFactor: function(ramId) {
      var controlAssessment = new GlideRecord('sn_risk_advanced_control_assessment');
      controlAssessment.addQuery('risk_assessment_methodology', ramId);
      controlAssessment.addQuery('control_assessment_methodology', "individual_control_assessment");
      controlAssessment.query();
      if (controlAssessment.next()) {
          return controlAssessment.getValue('overall_effectiveness_factor');
      } else {
          return null;
      }
  },

  _markApproved: function(asmtIDs) {
      var asmt = new GlideRecord("sn_risk_advanced_risk_assessment_instance");
      asmt.addQuery('sys_id', 'IN', asmtIDs);
      asmt.addQuery('state', '6');
      asmt.query();
      var count = asmt.getRowCount();

      var approvalRec = new GlideRecord("sysapproval_approver");
      approvalRec.addQuery("document_id", "IN", asmtIDs);
      approvalRec.addQuery("state", "requested");
      approvalRec.addQuery("approver", "IN", (new sn_grc.GRCUtils().getMyApprovals() + ''));
      approvalRec.query();
      while (approvalRec.next()) {
          approvalRec.setValue("state", "approved");
          approvalRec.update();
      }
      return count;
  },

  _sendAssessmentsByFrequency: function() {
      var asmts = {};
      var now = new GlideDateTime();
      var asmt = new GlideRecord('sn_risk_advanced_risk_assessment_instance');
      asmt.addQuery('next_schedule_date', '<=', new GlideDateTime());
      asmt.addQuery('risk_assessment_methodology.state', '!=', '3');
      asmt.addQuery('state', 'IN', '7,9');
      asmt.addQuery('table', '');
      asmt.addQuery('source_record', '');
      asmt.addQuery('active', true);
      asmt.query();
      while (asmt.next()) {

          if (this._checkIfLatestAssessment(asmt, asmts)) {
              var assessmentInstanceId = this._createNewAsmtInstance([asmt.getUniqueValue()]);
              this._markAssess(assessmentInstanceId, null);
          }

      }

      var riskAcceptanceTasks = new GlideRecord('sn_risk_acceptance_task');
      riskAcceptanceTasks.addQuery('state', '3');
      riskAcceptanceTasks.addNotNullQuery('risk_assessment_instance');
      riskAcceptanceTasks.addQuery('acceptance_end_date', '<=', new GlideDate());
      riskAcceptanceTasks.addQuery('risk_assessment_instance.risk_assessment_methodology.state', '!=', '3');
      riskAcceptanceTasks.addQuery('risk_assessment_instance.state', '7');
      riskAcceptanceTasks.addQuery('risk_assessment_instance.table', '');
      riskAcceptanceTasks.addQuery('risk_assessment_instance.source_record', '');
      riskAcceptanceTasks.addQuery('risk_assessment_instance.active', true);
      riskAcceptanceTasks.query();
      while (riskAcceptanceTasks.next()) {
          var gr = new GlideRecord('sn_risk_advanced_risk_assessment_instance');
          gr.get(riskAcceptanceTasks.risk_assessment_instance + '');
          if (!this._hasOpenAssessment(gr)) {
              var assessmentInstanceSysId = this._createNewAsmtInstance([riskAcceptanceTasks.risk_assessment_instance + '']);
              this._markAssess(assessmentInstanceSysId, null);
          }
      }

      var asmtForAnyObject = new GlideRecord('sn_risk_advanced_risk_assessment_instance');
      asmtForAnyObject.addQuery('next_schedule_date', '<=', new GlideDateTime());
      asmtForAnyObject.addQuery('risk_assessment_methodology.state', '!=', '3');
      asmtForAnyObject.addQuery('state', 'IN', '7,9');
      asmtForAnyObject.addQuery('table', "!=", "");
      asmtForAnyObject.addQuery('source_record', "!=", '');
      asmtForAnyObject.addQuery('active', true);
      asmtForAnyObject.query();
      while (asmtForAnyObject.next()) {

          if (this._checkIfLatestAnyObjectAssessment(asmtForAnyObject, asmts)) {
              this._createSimilarAnyObjectAsmt(asmtForAnyObject);
          }

      }
  },

  _checkIfLatestAssessment: function(asmt, asmts) {
      var key = asmt.risk + '_' + asmt.risk_assessment_methodology;
      if (key in asmts) {
          if (asmts[key] == asmt.getUniqueValue())
              return true;
      } else {
          var instance = new GlideRecord("sn_risk_advanced_risk_assessment_instance");
          instance.addQuery('risk_assessment_methodology', asmt.risk_assessment_methodology);
          instance.addQuery('risk', asmt.risk);
          instance.orderByDesc('sys_created_on');
          instance.setLimit(1);
          instance.query();
          if (instance.next()) {
              asmts[key] = instance.getUniqueValue();
              if (instance.getUniqueValue() == asmt.getUniqueValue())
                  return true;
          }
      }
      return false;
  },

  _checkIfLatestAnyObjectAssessment: function(asmt, asmts) {
      var key = asmt.source_record + '_' + asmt.risk_assessment_methodology;
      if (key in asmts) {
          if (asmts[key] == asmt.getUniqueValue())
              return true;
      } else {
          var instance = new GlideRecord("sn_risk_advanced_risk_assessment_instance");
          instance.addQuery('source_record', asmt.getValue('source_record'));
          instance.addQuery('table', asmt.getValue('table'));
          instance.addQuery('risk_assessment_methodology', asmt.risk_assessment_methodology);
          instance.orderByDesc('sys_created_on');
          instance.setLimit(1);
          instance.query();
          if (instance.next()) {
              asmts[key] = instance.getUniqueValue();
              if (instance.getUniqueValue() == asmt.getUniqueValue())
                  return true;

          }
      }
      return false;
  },


  _createSimilarAnyObjectAsmt: function(asmtForAnyObject) {
      var ram = new GlideRecord('sn_risk_advanced_risk_assessment_methodology');
      ram.get(asmtForAnyObject.getValue('risk_assessment_methodology'));

      var instanceObj = {};
      instanceObj.risk_assessment_methodology = asmtForAnyObject.getValue('risk_assessment_methodology');
      if (asmtForAnyObject.orignal_assessor_user) {
          instanceObj.assessor_user = asmtForAnyObject.orignal_assessor_user;
          instanceObj.orignal_assessor_user = asmtForAnyObject.orignal_assessor_user;
      } else {
          instanceObj.assessor_group = asmtForAnyObject.orignal_assessor_group;
          instanceObj.orignal_assessor_group = asmtForAnyObject.orignal_assessor_group;
          instanceObj.assessor_type = '2';
      }
      if (asmtForAnyObject.orignal_approver_user) {
          instanceObj.approver_user = asmtForAnyObject.orignal_approver_user;
          instanceObj.orignal_approver_user = asmtForAnyObject.orignal_approver_user;
      } else {
          instanceObj.approver_group = asmtForAnyObject.orignal_approver_group;
          instanceObj.orignal_approver_group = asmtForAnyObject.orignal_approver_group;
          instanceObj.approver_type = '2';
      }
      instanceObj.source_record = asmtForAnyObject.source_record;
      instanceObj.table = asmtForAnyObject.getValue('table');
      instanceObj.state = '1';
      instanceObj.next_schedule_date = this._getNextScheduleDate(ram.getValue('reassessment_frequency'));
      instanceObj.asmt_due_date = this._getAssessmentDueDate(ram.getValue('days_to_overdue'));
      var asmtId = this._createAssessmentInstance(instanceObj);
      this._createAssessmentQuestions(asmtId);

      var assessment = new GlideRecord('sn_risk_advanced_risk_assessment_instance');
      assessment.get(asmtId);
      var assessor;
      if (instanceObj.orignal_assessor_user) {
          assessor = this._checkUserPresent(instanceObj.orignal_assessor_user);
      } else if (instanceObj.orignal_assessor_group) {
          assessor = this._checkGroupPresent(instanceObj.orignal_assessor_group);
      }

      if ((!gs.nil(assessor) && ((instanceObj.orignal_assessor_user && !this._checkAssessorRolePresent(assessor)) || (instanceObj.orignal_assessor_group && !this._checkAssessorUserGroupRole(assessor))))) {
          var expMsg = "To perform the risk assessment, the assessor must have the sn_risk_advanced.ara_assessor role. You can also reassign the assessment to a user with the sn_risk_advanced.ara_assessor role.";
          if (instanceObj.orignal_assessor_user)
              this.createException(assessment, "assessor_user", expMsg);
          else
              this.createException(assessment, "assessor_group", expMsg);
      }
      var approver;
      if (instanceObj.orignal_approver_user) {
          approver = this._checkUserPresent(instanceObj.orignal_approver_user);
      } else if (instanceObj.orignal_approver_group) {
          approver = this._checkGroupPresent(instanceObj.orignal_approver_group);
      }

      if ((!gs.nil(approver) && ((instanceObj.orignal_approver_user && !this._checkApproverRolePresent(approver)) || (instanceObj.orignal_approver_group && !this._checkApproverUserGroupRole(approver))))) {
          var expMsgs = "To perform the risk assessment, the approver must have the sn_risk_advanced.ara_approver role. You can also reassign the assessment to a user with the sn_risk_advanced.ara_approver role.";
          if (instanceObj.orignal_approver_user)
              this.createException(assessment, "approver_user", expMsgs);
          else
              this.createException(assessment, "approver_group", expMsgs);
      }

      return asmtId;
  },

  _getClosedAssessments: function(asmtIDs, scopeID) {
      var riskArray = [];
      var assessmentIds = [];
      var asmt = new GlideRecord('sn_risk_advanced_risk_assessment_instance');
      asmt.addQuery('active', true);
      if (scopeID) {
          asmt.addQuery('assessment_scope', scopeID);
      } else {
          asmt.addQuery('sys_id', 'IN', asmtIDs);
      }
      asmt.addQuery('state', 'IN', this._getMonitorCloseAndCancelStateOfRiskAssessment());
      asmt.query();
      while (asmt.next()) {
          if (!this._hasOpenAssessment(asmt) && this._notDuplicate(riskArray, asmt))
              assessmentIds.push(asmt.getUniqueValue());
      }
      return assessmentIds;
  },

  _notDuplicate: function(riskArray, instance) {
      var risk = instance.getValue('risk');
      if (riskArray.indexOf(risk) == -1) {
          riskArray.push(risk);
          return true;
      }
      return false;
  },

  _getDueDate: function(asmt) {
      var daysToOverdue = 5;
      if (asmt.isValidRecord() && asmt.assessment_scope != '') {
          daysToOverdue = asmt.assessment_scope.days_to_overdue + '';
      }
      var currentDate = new GlideDateTime();
      currentDate.addDaysUTC(daysToOverdue);
      return currentDate;
  },

  _createNewAsmtInstance: function(assessmentIdsInCompletedState) {
      var newAssesments = [];
      if (assessmentIdsInCompletedState != '') {
          for (var i = 0; i < assessmentIdsInCompletedState.length; i++) {
              var asmt = new GlideRecord('sn_risk_advanced_risk_assessment_instance');
              asmt.get(assessmentIdsInCompletedState[i] + '');
              if (asmt.risk.active) {
                  var instanceObj = {};
                  instanceObj.risk = asmt.risk;
                  instanceObj.assessment_scope = asmt.assessment_scope;
                  instanceObj.entity_1 = asmt.entity_1;
                  instanceObj.risk_assessment_methodology = asmt.risk_assessment_methodology;
                  if (asmt.assessment_scope != '') {
                      var scope = new GlideRecord("sn_risk_advanced_risk_assessment_scope");
                      scope.get(asmt.assessment_scope);
                      this.addAssessors(instanceObj, scope, asmt.risk);
                      this.addApprovers(instanceObj, scope);
                  } else {
                      if (asmt.orignal_assessor_user) {
                          instanceObj.assessor_user = asmt.orignal_assessor_user;
                          instanceObj.orignal_assessor_user = asmt.orignal_assessor_user;
                      } else {
                          instanceObj.assessor_group = asmt.orignal_assessor_group;
                          instanceObj.orignal_assessor_group = asmt.orignal_assessor_group;
                          instanceObj.assessor_type = '2';
                      }
                      if (asmt.orignal_approver_user) {
                          instanceObj.approver_user = asmt.orignal_approver_user;
                          instanceObj.orignal_approver_user = asmt.orignal_approver_user;
                      } else {
                          instanceObj.approver_group = asmt.orignal_approver_group;
                          instanceObj.orignal_approver_group = asmt.orignal_approver_group;
                          instanceObj.approver_type = '2';
                      }
                  }
                  var assessmentInstanceId = this._createAssessmentInstance(instanceObj);
                  this._createAssessmentQuestions(assessmentInstanceId);
                  newAssesments.push(assessmentInstanceId);
              }
          }
      }
      return newAssesments;
  },

  //Generate responses for re triggered assessments
  _generateResponsesForReTriggeredAsmts: function(previousAsmt, currentAsmt) {
      var previousAsmtResponse = new GlideRecord('sn_risk_advanced_risk_assessment_instance_response');
      previousAsmtResponse.addQuery('assessment_instance_id', previousAsmt);
      previousAsmtResponse.addQuery('factor.sys_class_name', 'sn_risk_advanced_manual_factor');
      previousAsmtResponse.query();

      /* Store Previous assessment responses in object,
       key is factor plus control plus a constant factorResponse if assesment response is individual control asmt response
       else key is factor plus assessment type plus constant factorResponse. Similar is the case with storing comments */
      var responses = {};
      while (previousAsmtResponse.next()) {
          this._storeResponsesOfPreviousAsmt(previousAsmtResponse, responses);
      }

      var currentAsmtResponse = new GlideRecord('sn_risk_advanced_risk_assessment_instance_response');
      currentAsmtResponse.addQuery('assessment_instance_id', currentAsmt);
      currentAsmtResponse.addQuery('factor.sys_class_name', 'sn_risk_advanced_manual_factor');
      currentAsmtResponse.query();

      //Copy previous assesment responses to current re triggered assessment
      while (currentAsmtResponse.next()) {
          this._copyResponsesToCurrentAsmt(currentAsmtResponse, responses);
      }

      //Copy opt out flags
      this._copyOptOutFlags(previousAsmt, currentAsmt);
  },

  //Check if assessment type for response is control and assessed based on individual controls
  _isIndividualControlAsmtResponse: function(assessmentResponse) {
      if (assessmentResponse.getValue('assessment_type') != '2') {
          return false;
      } else {
          if (assessmentResponse.getValue('control')) {
              return true;
          }
      }
  },

  _generateKey: function(asmtResponse) {
      var factorResponseKey;
      var commentsKey;
      var keyObj = {};
      if (!this._isIndividualControlAsmtResponse(asmtResponse)) {
          keyObj.factorResponseKey = asmtResponse.getValue('factor') + '_' + asmtResponse.getValue('assessment_type') + '_factorResponse';
          if (asmtResponse.getValue('additional_comments') != '') {
              keyObj.commentsKey = asmtResponse.getValue('factor') + '_' + asmtResponse.getValue('assessment_type') + '_comments';
          }
      } else {
          keyObj.factorResponseKey = asmtResponse.getValue('factor') + '_' + asmtResponse.getValue('control') + '_factorResponse';
          if (asmtResponse.getValue('additional_comments') != '') {
              keyObj.commentsKey = asmtResponse.getValue('factor') + '_' + asmtResponse.getValue('control') + '_comments';
          }
      }
      return keyObj;
  },

  _storeResponsesOfPreviousAsmt: function(previousAsmtResponse, responses) {
      var keyObj = this._generateKey(previousAsmtResponse);
      responses[keyObj.factorResponseKey] = previousAsmtResponse.getValue('factor_response');
      if (previousAsmtResponse.getValue('additional_comments'))
          responses[keyObj.commentsKey] = previousAsmtResponse.getValue('additional_comments');
  },

  _copyResponsesToCurrentAsmt: function(currentAsmtResponse, responses) {
      var keyObj = this._generateKey(currentAsmtResponse);
      if (responses[keyObj.factorResponseKey]) {
          currentAsmtResponse.setValue('factor_response', responses[keyObj.factorResponseKey]);
      }
      if (responses[keyObj.commentsKey]) {
          currentAsmtResponse.setValue('additional_comments', responses[keyObj.commentsKey]);
      }
      currentAsmtResponse.update();
  },

  _copyOptOutFlags: function(previousAsmt, currentAsmt) {
      var prevAsmt = new GlideRecord('sn_risk_advanced_risk_assessment_instance');
      prevAsmt.get(previousAsmt);
      var currAsmt = new GlideRecord('sn_risk_advanced_risk_assessment_instance');
      currAsmt.get(currentAsmt);
      var fields = ['mitigating_controls_to_assess', 'residual_risk_not_applicable'];
      //Copy not applicable flags
      for (var i = 0; i < fields.length; i++) {
          currAsmt.setValue(fields[i], prevAsmt.getValue(fields[i]));
      }

      //Copy justifications to new assessment
      var justifcationFields = ['inherent_justification', 'control_justification', 'residual_justification', 'risk_response_justification', 'target_justification'];
      for (var j = 0; j < justifcationFields.length; j++) {
          if (prevAsmt.getValue(justifcationFields[j]))
              currAsmt.setValue(justifcationFields[j], prevAsmt.getValue(justifcationFields[j]));
      }
      currAsmt.update();
  },

  _setValuesToAsmtInReadyToAssessState: function(asmt, asmtStartDate, dueDate) {
      if (asmt.isValidRecord()) {
          asmt.next_schedule_date = asmtStartDate;
          asmt.setValue('state', '1');
          asmt.asmt_due_date = dueDate;
          var scopeId = asmt.getValue('assessment_scope');
          //This condition is required for assessments created from risk assessment scope playbook workflow
          //In risk assessment scope playbook workflow we add assessors and approvers during initiation of the assessment and not during creation of assessment
          if (gs.nil(asmt.getValue('assessor_user')) && gs.nil(asmt.getValue('assessor_group')) && !gs.nil(scopeId)) {
              var scope = new GlideRecord("sn_risk_advanced_risk_assessment_scope");
              scope.get(scopeId);
              var instanceObj = {};
              instanceObj.risk = asmt.getValue('risk');
              instanceObj.assessment_scope = scopeId;
              instanceObj.entity_1 = asmt.getValue("entity_1");
              instanceObj.risk_assessment_methodology = scope.risk_assessment_methodology;
              this.addAssessors(instanceObj, scope, asmt.risk);
              this.addApprovers(instanceObj, scope);
              for (var i in instanceObj) {
                  asmt.setValue(i + '', instanceObj[i] + '');
              }
          }
          asmt.update();
      }
  },

  _getRelatedRatingCriterias: function(ramReference, assessmentTypeName) {
      var assessmentTypeReference = new GlideRecord('sn_risk_advanced_assessment_type');
      assessmentTypeReference.addQuery('risk_assessment_methodology', ramReference);
      assessmentTypeReference.addQuery('name', assessmentTypeName);
      assessmentTypeReference.query();

      if (assessmentTypeReference.hasNext()) {
          assessmentTypeReference.next();
          var ratingCriteriaReference = new GlideRecord('sn_risk_advanced_rating_criteria');
          ratingCriteriaReference.addQuery('assessment_type', assessmentTypeReference.getUniqueValue());
          ratingCriteriaReference.query();
          var ratingCriteriasSysId = [];
          while (ratingCriteriaReference.next()) {
              ratingCriteriasSysId.push(ratingCriteriaReference.getUniqueValue());
          }
          return 'sys_idIN' + ratingCriteriasSysId;
      }
  },

  filterAssessments: function(scope) {
      return this._filterAssessments(scope);
  },

  _filterAssessments: function(scope) {
      var asmtIds = [];
      var instance = new GlideRecord("sn_risk_advanced_risk_assessment_instance");
      instance.addQuery('assessment_scope', scope);
      instance.addQuery('active', true);
      instance.query();
      while (instance.next()) {
          if (instance.state != '7' && instance.state != '8' && instance.state != '9') {
              asmtIds.push(instance.getUniqueValue());
          } else if (instance.state == '7') {
              if (!this._hasOpenAssessment(instance) && !this._getAssessmentByState(instance, '9')) {
                  asmtIds.push(instance.getUniqueValue());
              }
          } else if (instance.state == '9' || instance.state == '8') {
              if (!this._getAssessmentByState(instance, null)) {
                  asmtIds.push(instance.getUniqueValue());
              }
          }

      }
      return asmtIds.toString();
  },

  _getAssessmentByState: function(asmt, state) {
      var instance = new GlideRecord("sn_risk_advanced_risk_assessment_instance");
      if (!gs.nil(state))
          instance.addQuery('state', state);
      instance.addQuery('assessment_scope', asmt.assessment_scope);
      instance.addQuery('risk', asmt.risk);
      instance.addQuery('sys_created_on', '>', asmt.getValue('sys_created_on'));
      instance.query();
      return instance.hasNext();
  },

  _hasOpenAssessment: function(asmt) {
      var instance = new GlideRecord("sn_risk_advanced_risk_assessment_instance");
      instance.addQuery('state', 'NOT IN', this._getMonitorCloseAndCancelStateOfRiskAssessment());
      instance.addQuery('risk_assessment_methodology', asmt.risk_assessment_methodology);
      instance.addQuery('risk', asmt.risk);
      instance.query();
      return instance.hasNext();
  },

  _hasOpenAssessmentForAnyObject: function(asmt) {
      var instance = new GlideRecord("sn_risk_advanced_risk_assessment_instance");
      instance.addQuery('state', 'NOT IN', this._getMonitorCloseAndCancelStateOfRiskAssessment());
      instance.addQuery('source_record', asmt.getValue('source_record'));
      instance.addQuery('table', asmt.getValue('table'));
      instance.query();
      return instance.hasNext();
  },

  _checkUserPresent: function(userId) {
      var user = new GlideRecord('sys_user');
      if (user.get(userId)) {
          return user;
      }
      return null;
  },

  _checkGroupPresent: function(groupId) {
      var group = new GlideRecord('sys_user_group');
      if (group.get(groupId)) {
          return group;
      }
      return null;
  },

  _checkRole: function(user, roleTocheck) {
      var hasRole = new GlideRecord("sys_user_has_role");
      hasRole.addEncodedQuery('user=' + user.getUniqueValue() + '^role.name=' + roleTocheck);
      hasRole.query();
      return hasRole.hasNext();
  },

  _checkAssessorRolePresent: function(user) {
      return this._checkRole(user, "sn_risk_advanced.ara_assessor^ORrole.name=sn_grc.business_user_lite");
  },

  _checkApproverRolePresent: function(user) {
      return this._checkRole(user, "sn_risk_advanced.ara_approver");
  },

  _checkGroupRole: function(group, roles) {
      var hasRole = new GlideRecord("sys_group_has_role");
      hasRole.addQuery('role.name', 'IN', roles);
      hasRole.addQuery('group', group.getUniqueValue());
      hasRole.query();
      return hasRole.hasNext();
  },

  _checkAssessorUserGroupRole: function(group) {
      return this._checkGroupRole(group, 'sn_risk_advanced.ara_assessor, sn_grc.business_user_lite, sn_risk.user, sn_risk.manager, sn_risk.admin');
  },

  _checkApproverUserGroupRole: function(group) {
      return this._checkGroupRole(group, 'sn_risk_advanced.ara_approver, sn_grc.business_user_lite, sn_risk.user, sn_risk.manager, sn_risk.admin');
  },

  createException: function(assessmentInstance, fieldName, expMsg) {
      var fetchException = new GlideRecord("sn_grc_exception_category");
      fetchException.addQuery("category", "1");
      fetchException.query();

      if (!fetchException.hasNext()) {
          fetchException.initialize();
          fetchException.setValue('category', "1");
          var exceptionId = fetchException.insert();
      }

      var exp = {};
      exp.table = assessmentInstance.getTableName();
      exp.sourceRecordId = assessmentInstance.getUniqueValue();
      exp.exceptionCategory = "1";
      exp.fieldName = fieldName;
      exp.exceptionMessage = expMsg;
      exp.application = gs.getCurrentApplicationId();
      var grcExp = new sn_grc.GRCExceptionUtils();
      var result = grcExp.createException(exp);
      return result.exceptionId;
  },

  _getNextScheduleDate: function(frequency) {
      var asmtStartDate = new GlideDateTime();
      switch (frequency) {
          case '1':
              asmtStartDate = '';
              break;
          case '2':
              asmtStartDate.addWeeksUTC(1);
              break;
          case '3':
              asmtStartDate.addMonthsUTC(1);
              break;
          case '4':
              asmtStartDate.addMonthsUTC(3);
              break;
          case '5':
              asmtStartDate.addMonthsUTC(6);
              break;
          case '6':
              asmtStartDate.addYearsUTC(1);
              break;
      }

      return asmtStartDate;
  },

  _getAssessmentDueDate: function(dueDate) {
      var asmtDueDate = new GlideDateTime();
      asmtDueDate.addDaysUTC(dueDate);
      return asmtDueDate;
  },


  _clearFactorResponses: function(asmt, asmtType) {
      var responses = new GlideRecord('sn_risk_advanced_risk_assessment_instance_response');
      responses.addQuery('assessment_instance_id', asmt.getUniqueValue());
      if (asmtType === 'controlAsmt')
          responses.addQuery('assessment_type', '2');
      else if (asmtType === 'residualAsmt')
          responses.addQuery('assessment_type', '3');
      else if (asmtType === 'targetAsmt')
          responses.addQuery('assessment_type', '4');
      responses.query();
      while (responses.next()) {
          responses.setValue('factor_response', '');
          responses.setValue('additional_comments', '');
          responses.update();
      }
  },

  _clearTargetAssessmentResponses: function(asmt) {
      var targetAsmt = new GlideRecord('sn_risk_advanced_target_assessment');
      targetAsmt.addQuery('risk_assessment_methodology', asmt.risk_assessment_methodology + '');
      targetAsmt.query();
      if (targetAsmt.next()) {
          if (targetAsmt.getValue('calculate_based_on') == 'overall_assessment') {
              asmt.target_computed_risk = '';
              asmt.target_computed_score = '';
              asmt.target_computed_ale = '';
          } else {
              this._clearFactorResponses(asmt, 'targetAsmt');
          }
      }
  },

  _saveMitigationCtrlAndResidualRiskFlags: function(asmtId, state, isMitigationControlsFlagSet, isResidualRiskFlagSet) {
      var gr = new GlideRecord("sn_risk_advanced_risk_assessment_instance");
      gr.get(asmtId);
      if (state == '3') {
          gr.mitigating_controls_to_assess = isMitigationControlsFlagSet;
      }
      if (state == '4') {
          gr.residual_risk_not_applicable = isResidualRiskFlagSet;
      }
      if (isMitigationControlsFlagSet == "true" && gr.override_calculated_control_effectiveness) {
          gr.override_calculated_control_effectiveness = false;
      }
      if (isResidualRiskFlagSet == "true" && gr.override_calculated_residual_score) {
          gr.override_calculated_residual_score = false;
      }
      gr.update();
  },

  //check user has sn_risk_advanced.assessor role or not
  _checkAssessorRole: function(userId) {
      if (userId) {
          var user = this._checkUserPresent(userId);
          if (user) {
              return this._checkAssessorRolePresent(user);
          }
      }
      return false;
  },

  _checkApproverRole: function(userId) {
      if (userId) {
          var user = this._checkUserPresent(userId);
          if (user) {
              return this._checkApproverRolePresent(user);
          }
      }
      return false;
  },

  _canReassess: function(currentAsmt) {
      var reassess = currentAsmt.state == '7' && currentAsmt.active && ((new sn_grc.GRCUtils().getMyAssignments() + '').includes(currentAsmt.assessor_user + '') || (currentAsmt.entity_1 != '' && (currentAsmt.entity_1.owned_by + '').includes(gs.getUserID())));
      if (reassess) {
          reassess = this._canReassessAsmt(currentAsmt);
      }
      return reassess;
  },

  _canReassessAsmt: function(currentAsmt) {
      var hasOpenAsmt = false;
      if (currentAsmt.source_record != '') {
          hasOpenAsmt = this._hasOpenAssessmentForAnyObject(currentAsmt);
      } else {
          hasOpenAsmt = this._hasOpenAssessment(currentAsmt);
      }
      if (!hasOpenAsmt) {
          if ((((currentAsmt.inherent_risk_score_when_overriden != currentAsmt.inherent_computed_risk_score) ||
                  (currentAsmt.inherent_ale_when_overridden.getReferenceValue() != currentAsmt.inherent_computed_ale.getReferenceValue())) && currentAsmt.override_calculated_inherent_score) || ((currentAsmt.control_effectiveness_score_when_overridden != currentAsmt.control_computed_effectiveness_score) && currentAsmt.override_calculated_control_effectiveness) || (((currentAsmt.residual_risk_score_when_overridden != currentAsmt.residual_computed_risk_score) ||
                  (currentAsmt.residual_ale_when_overridden.getReferenceValue() != currentAsmt.residual_computed_ale.getReferenceValue())) && currentAsmt.override_calculated_residual_score)) {
              return true;
          }
      }
      return false;

  },

  _filterOverriddenAssessments: function() {
      var asmts = [];
      var currentAsmt = new GlideRecord("sn_risk_advanced_risk_assessment_instance");
      currentAsmt.addQuery('state', '7');
      currentAsmt.addQuery('active', true);
      currentAsmt.addEncodedQuery('entity_1.owned_by=' + gs.getUserID() + '^ORassessor_userLIKE' + gs.getUserID());
      currentAsmt.addEncodedQuery('override_calculated_control_effectiveness=true^ORoverride_calculated_inherent_score=true^ORoverride_calculated_residual_score=true^ORoverride_calculated_target_score=true');
      currentAsmt.query();
      while (currentAsmt.next()) {
          if (this._canReassessAsmt(currentAsmt)) {
              asmts.push(currentAsmt.number + '');
          }
      }
      return asmts.toString();
  },

  _setAsmtStatetoCancelled: function(ramID) {
      var asmt = new GlideRecord("sn_risk_advanced_risk_assessment_instance");
      asmt.addQuery('risk_assessment_methodology', ramID);
      asmt.addQuery('state', 'NOT IN', '7,8');
      asmt.query();
      asmt.setValue('state', '9');
      asmt.updateMultiple();
  },

  _setAsmtStateToClose: function(ramID) {
      var asmt = new GlideRecord("sn_risk_advanced_risk_assessment_instance");
      asmt.addQuery('risk_assessment_methodology', ramID);
      asmt.addQuery('state', 'IN', '7');
      asmt.query();
      asmt.setValue('state', '8');
      asmt.updateMultiple();
  },

  _showCreateFromLibrary: function(current, parent) {
      return parent.getTableName() == 'sn_risk_advanced_risk_assessment_scope' && parent.risk_assessment_methodology.state == 2 && (gs.getUser().hasRole("sn_risk.manager") || parent.entity.owned_by == gs.getUserID()) && (parent.risk_assessment_methodology.risk_identification == 1 || parent.risk_assessment_methodology.risk_identification == 3);

  },

  _showAdhocRisk: function(current) {
      return current.getTableName() == 'sn_risk_advanced_risk_assessment_scope' && current.risk_assessment_methodology.state == 2 && (gs.getUser().hasRole("sn_risk.manager") || current.entity.owned_by == gs.getUserID()) && (current.risk_assessment_methodology.risk_identification == 2 || current.risk_assessment_methodology.risk_identification == 3);
  },

  _sendDailyNotificationReminder: function() {
      var currentDate = new GlideDateTime();
      // Iterate over the RAM's and find the reminding day variable
      var ram = new GlideRecord("sn_risk_advanced_risk_assessment_methodology");
      ram.addQuery("state", "2");
      ram.query();

      var ramMap = {};
      while (ram.next()) {
          ramMap[ram.getUniqueValue()] = {
              "passedDueDays": ram.getValue("days_passed_due_date"),
              "leftDueDays": ram.getValue("days_left_to_due_date")
          };
      }

      // get those assessments which are not in closed or cancelled state
      var assmt_instance = new GlideRecord("sn_risk_advanced_risk_assessment_instance");
      assmt_instance.addEncodedQuery("assessor_userISNOTEMPTY^asmt_due_dateISNOTEMPTY^stateNOT IN" + this._getMonitorCloseAndCancelStateOfRiskAssessment() + "^final_notification_sent=false");
      assmt_instance.query();

      while (assmt_instance.next()) {

          var daysLeftToDueDate = ramMap[assmt_instance.getValue("risk_assessment_methodology")].leftDueDays;
          var daysToRepeat = ramMap[assmt_instance.getValue("risk_assessment_methodology")].passedDueDays;

          // This is done to disable the feature from ram level
          if (daysLeftToDueDate == 0)
              continue;

          var date = new GlideDateTime();
          date.addDaysUTC(daysLeftToDueDate);

          var pendingDueDate = new GlideDateTime(assmt_instance.getValue("asmt_due_date"));
          var startDate = new GlideDateTime(date.getDate() + " 00:00:00");
          var endDate = new GlideDateTime(date.getDate() + " 23:59:59");

          var recepient = assmt_instance.getValue("assessor_user") + '';

          if (pendingDueDate.compareTo(startDate) == 1 && pendingDueDate.compareTo(endDate) == -1) { // check before due date   

              gs.eventQueue("sn_risk_advanced.report_due_date_ahead", assmt_instance, recepient, assmt_instance.getUniqueValue());

          } else if (pendingDueDate.compareTo(currentDate) == -1) { // check after due date

              if (daysToRepeat == 0) // check if reminder is disabled after due date is passed
                  continue;

              var lastDate = pendingDueDate;
              lastDate.addDaysLocalTime(daysToRepeat) + " 00:00:00";

              if (currentDate.compareTo(new GlideDateTime(lastDate.getDate())) == -1) // days before final reminder
              {
                  gs.eventQueue("sn_risk_advanced.report_past_due_date", assmt_instance, recepient, assmt_instance.getUniqueValue());

              } else if (currentDate.compareTo(new GlideDateTime(lastDate.getDate() + " 00:00:00")) == 1 && currentDate.compareTo(new GlideDateTime(lastDate.getDate() + " 23:59:59")) == -1) // Final day of reminder
              {
                  var user = new GlideRecord("sys_user");
                  user.get(recepient);

                  var manager = user.getValue("manager");
                  if (manager)
                      gs.eventQueue("sn_risk_advanced.report_final_due_date_p", assmt_instance, manager, "manager");

                  gs.eventQueue("sn_risk_advanced.report_final_due_date_p", assmt_instance, recepient, "user");

                  assmt_instance.setValue("final_notification_sent", true);
                  assmt_instance.update();
              }
          }
      }
  },

  _triggerRiskAssessment: function(risk, ramId, assessor, approver, assessorType, approverType, daysToOverdue) {
      var result = {};
      if (!this._isRiskValid(risk)) {
          result.status = 0;
          result.errorMsg = gs.getMessage("Risk does not exist or is inactive.");
          return result;
      }

      var entityId = this._getEntityForRisk(risk);

      if (entityId) {
          return this._createRiskAssessmentFromEntity(entityId, risk, assessor, approver, ramId, assessorType, approverType, daysToOverdue);
      } else {
          result.status = 0;
          result.errorMsg = gs.getMessage("Risk does not have an entity associated.");
          return result;
      }

  },

  _createRiskAssessmentFromEntity: function(entityId, riskId, assessorId, approverId, ramId, assessorType, approverType, daysToOverdue) {
      var isAssessorUser = true;
      if (!gs.nil(assessorType) && assessorType == "group")
          isAssessorUser = false;
      if (gs.nil(approverType))
          approverType = "user";
      if (daysToOverdue == '')
          daysToOverdue = 0;
      var result = {};
      if (daysToOverdue < 0 || !(typeof(daysToOverdue) === 'number')) {
          result.status = 0;
          result.errorMsg = gs.getMessage("Please provide a valid DaysToOverdue to create risk assessment.");
          return result;
      }
      //Get RAM info from entity
      var entityRecord = new GlideRecord("sn_grc_profile");
      entityRecord.get(entityId);
      if (entityRecord.getValue("active")) {
          var entityClass = entityRecord.getValue("profile_class");
          if (entityClass) {
              var ram = new GlideRecord("sn_risk_advanced_risk_assessment_methodology");
              if (ramId) {
                  ram.addQuery("assessed_on", "0");
                  ram.addQuery("entity_classesLIKE" + entityClass);
                  ram.addQuery("sys_id", ramId);
                  ram.addQuery("state", "2");
              } else {
                  var primaryRam = new RiskAssessmentMethodologyUtils().getPrimaryRAMForEntityClass(entityClass, true);
                  ram.addQuery("sys_id", primaryRam);
              }
              ram.query();
              if (ram.next()) {

                  //Check if assessment doesn't exist
                  if (this._riskAssessmentAlreadyExists(ram.getUniqueValue(), entityId, riskId)) {
                      result.status = 200;
                      result.msg = gs.getMessage("Risk assessment already exists.");
                      return result;
                  }

                  //Check assessor and approver are present
                  if (assessorId) {
                      var assessor;
                      if (isAssessorUser)
                          assessor = this._checkUserPresent(assessorId);
                      else
                          assessor = this._checkGroupPresent(assessorId);
                      if (!assessor) {
                          result.status = 0;
                          if (isAssessorUser) {
                              result.errorMsg = gs.getMessage('Cannot create risk assessment. Please provide a valid assessor.');
                          } else {
                              result.errorMsg = gs.getMessage('Cannot create risk assessment. Please provide a valid assessor group.');
                          }
                          return result;
                      }
                  } else {
                      result.status = 0;
                      result.errorMsg = gs.getMessage("Please provide assessor to create a risk assessment.");
                      return result;
                  }

                  if (approverId && approverType != "assessor_manager") {
                      var approver;
                      if (approverType == "user")
                          approver = this._checkUserPresent(approverId);
                      else if (approverType == "group")
                          approver = this._checkGroupPresent(approverId);
                      if (!approver) {
                          result.status = 0;
                          if (approverType == "user") {
                              result.errorMsg = gs.getMessage('Cannot create risk assessment. Please provide a valid approver.');
                          } else if (approverType == "group") {
                              result.errorMsg = gs.getMessage('Cannot create risk assessment. Please provide a valid approver group.');
                          }
                          return result;
                      }
                  }

                  //Create risk assessment instance based on ram, risk and assessor.
                  var instanceObj = {};
                  instanceObj.risk = riskId;
                  instanceObj.entity_1 = entityId;
                  instanceObj.risk_assessment_methodology = ram.getUniqueValue() + '';
                  if (assessorId != '') {
                      if (isAssessorUser) {
                          instanceObj.assessor_user = assessorId;
                      } else {
                          instanceObj.assessor_group = assessorId;
                          instanceObj.assessor_type = '2';
                      }
                  }
                  if (approverId != '') {
                      if (approverType == "user") {
                          instanceObj.approver_user = approverId;
                          instanceObj.approver_type = '1';
                      } else if (approverType == "group") {
                          instanceObj.approver_group = approverId;
                          instanceObj.approver_type = '2';
                      }
                  } else if (approverType == "assessor_manager") {
                      instanceObj.approver_type = '3';
                  }
                  var hasAssessorException = (!assessorId || (assessor && ((isAssessorUser && !this._checkAssessorRolePresent(assessor)) || (!isAssessorUser && !this._checkAssessorUserGroupRole(assessor)))));
                  var hasApproverException = (approver && ((approverType == "user" && !this._checkApproverRolePresent(approver)) || (approverType == "group" && !this._checkApproverUserGroupRole(approver))));

                  if (hasAssessorException) {
                      result.status = 0;
                      if (isAssessorUser) {
                          result.errorMsg = gs.getMessage('Cannot create a risk assessment. Please provide the sn_risk_advanced.ara_assessor role to the assessor of this assessment.');
                      } else {
                          result.errorMsg = gs.getMessage('Cannot create a risk assessment. Please provide the sn_risk_advanced.ara_assessor role to the assessor group of this assessment.');
                      }
                      return result;
                  }
                  if (hasApproverException) {
                      result.status = 0;
                      if (approverType == "user") {
                          result.errorMsg = gs.getMessage('Cannot create a risk assessment. Please provide the sn_risk_advanced.ara_approver role to the approver of this assessment.');
                      } else if (approverType == "group") {
                          result.errorMsg = gs.getMessage('Cannot create a risk assessment. Please provide the sn_risk_advanced.ara_approver role to the approver group of this assessment.');
                      }
                      return result;
                  }
                  instanceObj.asmt_due_date = this._getAssessmentDueDate(daysToOverdue);
                  if (isAssessorUser)
                      instanceObj.orignal_assessor_user = assessorId;
                  else
                      instanceObj.orignal_assessor_group = assessorId;
                  if (approverType == "user")
                      instanceObj.orignal_approver_user = approverId;
                  else if (approverType == "group")
                      instanceObj.orignal_approver_group = approverId;

                  //Attach scope if Risk part of scope
                  var scope = this._getScope(instanceObj.risk, instanceObj.risk_assessment_methodology);
                  if (scope != '') {
                      instanceObj.state = '0';
                      instanceObj.assessment_scope = scope;
                  } else {
                      instanceObj.state = '1';
                      instanceObj.asmt_initiated_date = new GlideDateTime();
                  }
                  var assessmentInstanceId = this._createAssessmentInstance(instanceObj);
                  if (assessmentInstanceId == null) {
                      result.status = 0;
                      result.errorMsg = gs.getMessage('Risk assessment could not be created.');
                      return result;
                  }
                  this._createAssessmentQuestions(assessmentInstanceId);
                  if (scope != '') {
                      this._markAssess(assessmentInstanceId, null);
                  }
                  var assessmentInstance = new GlideRecord('sn_risk_advanced_risk_assessment_instance');
                  assessmentInstance.get(assessmentInstanceId);
                  var url = '/sn_risk_advanced_risk_assessment_instance.do?sys_id=';
                  var link1 = '<a target="_blank" href="' + url + assessmentInstanceId + '">' + assessmentInstance.getValue('number') + '</a>';
                  result.status = 201;
                  result.asmtId = assessmentInstanceId;
                  result.asmtNumber = assessmentInstance.getValue('number');
                  result.msg = gs.getMessage('Risk assessment created successfully. {0}', [link1]);
                  return result;
              } else {
                  result.status = 0;
                  if (!ramId) {
                      result.errorMsg = gs.getMessage('There are no published risk assessment methodologies for the entity related to this risk. Contact your risk administrator for details.');
                  } else {
                      result.errorMsg = gs.getMessage('The risk assessment methodology provided is not associated to the entity related to this risk. Contact your risk administrator for details.');
                  }
                  return result;
              }
          } else {
              result.status = 0;
              result.errorMsg = gs.getMessage("Entity associated to risk does not have entity class associated.");
              return result;
          }
      } else {
          result.status = 0;
          result.errorMsg = gs.getMessage("Entity associated to risk is inactive.");
          return result;
      }
  },

  _getScope: function(riskId, ramId) {
      var asmt = new GlideRecord('sn_risk_advanced_risk_assessment_instance');
      asmt.addQuery('risk', riskId);
      asmt.addQuery('risk_assessment_methodology', ramId);
      asmt.addNotNullQuery('assessment_scope');
      asmt.orderByDesc("sys_created_on");
      asmt.setLimit(1);
      asmt.query();
      if (asmt.next())
          return asmt.assessment_scope + '';
      else
          return '';

  },

  _riskAssessmentAlreadyExists: function(ram, entity, risk) {
      var rasmt = new GlideRecord("sn_risk_advanced_risk_assessment_instance");
      rasmt.addQuery("risk_assessment_methodology", ram);
      rasmt.addQuery("entity_1", entity);
      rasmt.addQuery("risk", risk);
      rasmt.addQuery('state', 'NOT IN', this._getMonitorCloseAndCancelStateOfRiskAssessment());
      rasmt.query();
      return rasmt.next();
  },

  _isRiskValid: function(risk) {
      var riskRecord = new GlideRecord("sn_risk_risk");
      riskRecord.addQuery('sys_id', risk);
      riskRecord.addQuery('active', true);
      riskRecord.query();
      if (riskRecord.next()) {
          return true;
      } else {
          return false;
      }
  },

  _getEntityForRisk: function(risk) {
      var riskRecord = new GlideRecord("sn_risk_risk");
      riskRecord.get(risk);
      return riskRecord.getValue('profile');
  },

  _showInitiateAssessmentAction: function(current) {
      return ((current.source_record != '' || (current.assessment_scope == '' && current.risk != '' && current.entity_1 != '')) && current.state == '0' && new sn_risk_advanced.RiskAssessmentUtils().checkAssessorRole(current.assessor_user) && (!current.approver_user || new sn_risk_advanced.RiskAssessmentUtils().checkApproverRole(current.approver_user)));
  },

  _checkRAMExistsForRisk: function(riskId) {

      var entityId = this._getEntityForRisk(riskId);
      if (entityId) {
          var entityRecord = new GlideRecord("sn_grc_profile");
          entityRecord.get(entityId);
          if (entityRecord.getValue("active")) {
              var entityClass = entityRecord.getValue("profile_class");
              if (entityClass) {
                  var ram = new GlideRecord("sn_risk_advanced_risk_assessment_methodology");
                  ram.addQuery("assessed_on", "0");
                  ram.addQuery("entity_classesLIKE" + entityClass);
                  ram.addQuery("state", "2");
                  ram.setLimit(1);
                  ram.query();
                  if (ram.next()) {
                      return true;
                  }
              }
          }
      }
      return false;
  },

  _validateResidualAssessment: function(current) {
      var result = {};
      var isValid = true;

      //Check RAM has both inherent and residual asmts
      var ramId = current.risk_assessment_methodology;
      var ram = new GlideRecord("sn_risk_advanced_risk_assessment_methodology");
      ram.get(ramId);

      //If both Inherent and Residual asmts are there 
      if (ram.getValue("inherent_risk") == true && ram.getValue("residual_risk") == true) {

          //Get contributions of both inherent and residual
          var inherentContribution = this._getAssessmentContribution(ramId, "sn_risk_advanced_inherent_assessment");
          var residualContribution = this._getAssessmentContribution(ramId, "sn_risk_advanced_residual_assessment");

          // If contributions are same, check the fields based on contribution. Else check the common fields
          if (inherentContribution == residualContribution) {

              //As both asmt contributions are same, we can pass either of contribution to compare the fields
              return this._validateResidualScores(current, residualContribution);

          } else {
              //Check Qualitative score if its the common contribution between inherent and residual assessments
              if ((residualContribution == "1" || residualContribution == "3") && (inherentContribution == "1" || inherentContribution == "3")) {
                  return this._validateResidualScores(current, "1");
              }

              //Check Quantitative score if its the common contribution between inherent and residual assessments
              else if ((residualContribution == "2" || residualContribution == "3") && (inherentContribution == "2" || inherentContribution == "3")) {
                  return this._validateResidualScores(current, "2");
              }

              // Skip if no common contribution between inherent and residual
          }
      }

      result.isValid = isValid;
      return result;
  },

  _getAssessmentContribution: function(ramId, table) {
      var assessmentRecord = new GlideRecord(table);
      assessmentRecord.addQuery("risk_assessment_methodology", ramId);
      assessmentRecord.query();
      if (assessmentRecord.next()) {
          return assessmentRecord.getValue("assessment_contribution");
      }
  },

  _validateResidualScores: function(assessment, assessmentType) {
      var result = {};
      var isValid = true;
      var errorMsg;
      switch (assessmentType) {

          //Validate quantitative score of inherent > qualitative score of residual
          case "1":
              if (parseFloat(assessment.final_inherent_ale.getSessionValue()) < parseFloat(assessment.final_residual_ale.getSessionValue())) {
                  isValid = false;
                  errorMsg = gs.getMessage("The residual annual loss expectancy cannot be greater than the inherent annual loss expectancy.");
              }
              break;

              //Validate qualitative score of inherent > qualitative score of residual
          case "2":
              if (assessment.final_inherent_score < assessment.final_residual_score) {
                  isValid = false;
                  errorMsg = gs.getMessage("The residual score cannot be greater than the inherent score.");
              }
              break;

              //Validate both qualitative and quantitative score of inherent > qualitative and quantitative score residual
          case "3":
              var error = false;
              if (assessment.final_inherent_score < assessment.final_residual_score) {
                  error = true;
                  isValid = false;
                  errorMsg = gs.getMessage("The residual score cannot be greater than the inherent score.");
              }

              if (parseFloat(assessment.final_inherent_ale.getSessionValue()) < parseFloat(assessment.final_residual_ale.getSessionValue())) {
                  isValid = false;
                  if (error) {
                      errorMsg = gs.getMessage("The residual annual loss expectancy and residual score cannot be greater than the inherent annual loss expectancy and inherent score.");
                  } else {
                      errorMsg = gs.getMessage("The residual annual loss expectancy cannot be greater than the inherent annual loss expectancy.");
                  }

              }

              break;

      }

      result.isValid = isValid;
      result.errorMsg = errorMsg;
      return result;
  },

  _getAllSimulatedAssessments: function(ramId) {

      var assessmentIds = [];
      if (ramId == null)
          return assessmentIds;

      var instanceRecord = new GlideRecord('sn_risk_advanced_risk_assessment_instance');
      instanceRecord.addQuery('risk_assessment_methodology', ramId);
      instanceRecord.addQuery('risk_assessment_methodology.state', '1');
      instanceRecord.query();
      while (instanceRecord.next()) {
          assessmentIds.push(instanceRecord.getValue('sys_id'));
      }
      return assessmentIds;
  },

  _checkIfRiskAssessmentExists: function(ramId, assessmentOn, assessedOn) {

      var assessmentId = "";
      var instanceRecord = new GlideRecord('sn_risk_advanced_risk_assessment_instance');
      instanceRecord.addQuery('risk_assessment_methodology', ramId);
      instanceRecord.addQuery('risk_assessment_methodology.state', "1");
      if (assessedOn == '0') {
          instanceRecord.addQuery('risk', assessmentOn);
      } else if (assessedOn == '1') {
          instanceRecord.addQuery('source_record', assessmentOn);
      }
      instanceRecord.query();
      if (instanceRecord.next()) {
          assessmentId = instanceRecord.sys_id;
      }
      return assessmentId;
  },

  _deleteIfSimulatedRiskAssessmentExists: function(assessmentId) {

      new sn_risk.RiskResponse().deleteSimulatedRiskResponseTasks([assessmentId]);
      var instanceRecord = new GlideRecord('sn_risk_advanced_risk_assessment_instance');
      instanceRecord.addQuery('sys_id', assessmentId);
      instanceRecord.query();
      if (instanceRecord.next()) {
          instanceRecord.setWorkflow(false);
          instanceRecord.deleteRecord();
      }
      return;
  },
  _deleteAllSimulatedAssessments: function(ramId) {

      if (ramId == null)
          return;
      var assessmentIds = [];
      assessmentIds = this.getAllSimulatedAssessments(ramId);
      new sn_risk.RiskResponse().deleteSimulatedRiskResponseTasks(assessmentIds);
      var gr = new GlideRecord('sn_risk_advanced_risk_assessment_instance');
      gr.addQuery('sys_id', 'IN', assessmentIds);
      gr.query();
      gr.setWorkflow(false);
      gr.deleteMultiple();
      return;

  },

  type: 'RiskAssessmentUtilsBase'
};

Sys ID

9fe3af3e534100101bfbddeeff7b12e7

Offical Documentation

Official Docs: