Name

global.TriggerRuleSNC

Description

Use the TriggerRule script-include if you would like to make changes to this script by overriding the function in TriggerRuleSNC.

Script

var TriggerRuleSNC = Class.create();

TriggerRuleSNC.prototype = {

  ASSIGNMENT_GROUP: "assignment_group",
  ASSIGNED_TO: "assigned_to",
  DOCUMENT: "document",
  DOCUMENT_TABLE: "document_table",
  GROUP: "group",
  SYS_CREATED_ON: "sys_created_on",
  TABLE: "table",
  TRIGGER_GROUP_FIELD: "trigger_group_field",
  TRIGGER_RULE: "trigger_rule",
  TRIGGER_RULES_LOG_LEVEL: "com.snc.trigger_rules.log.level",
  TRIGGER_RULE_PROCESS: "trigger_rule.process",
  TRIGGER_RULE_REASSIGNMENT: "trigger_rule.reassignment",
  TRIGGER_RULE_TABLE_CFG: "trigger_rule_table_cfg",
  TRIGGER_RULE_WF_CONTEXT: "trigger_rule_wf_context",
  TRIGGER_USER_FIELD: "trigger_user_field",
  TRIGGER_SCRIPT: "trigger_script",
  WF_CONTEXT: "wf_context",
  JOURNAL_FIELD: "journal_field",
  WORK_NOTES: "work_notes",
  PARENT_WF_CONTEXT: "parent_wf_context",


  initialize: function() {
  	this.eventName = null;
  	this.triggerRuleGR = null;
  	this.recordGR = null;
  	this.workflowVars = {};
  	this._log = new GSLog(this.TRIGGER_RULES_LOG_LEVEL, this.type);

  	if (this._log.atLevel(GSLog.DEBUG))
  		this._log.logDebug("[initialize] ");
  },
  
  setEventName: function(eventName) {
  	this.eventName = eventName;
  	return this;
  },

  setRule: function(triggerRule) {
  	if (typeof triggerRule === "string") {
  		this.triggerRuleGR = new GlideRecord(this.TRIGGER_RULE);
  		this.triggerRuleGR.get(triggerRule);
  	} else
  		this.triggerRuleGR = triggerRule;
  	return this;
  },

  setRecord: function(record) {
  	this.recordGR = record;
  	return this;
  },

  setWorkflowVars: function(workflowVars) {
  	this.workflowVars = workflowVars;
  	return this;
  },

  process: function() {
  	if (!this.triggerRuleGR || !this.recordGR || !this.triggerRuleGR.isValidRecord() || !this.recordGR.isValidRecord()) {
  		if (this._log.atLevel(GSLog.DEBUG))
  			this._log.logDebug("[process] Trigger rule record or current record is invalid");
  		return;
  	}

  	var groupField = this.ASSIGNMENT_GROUP;
  	var userField = this.ASSIGNED_TO;

  	var triggerRuleTableGR = new TriggerRuleTableConfigUtil().getTriggerRuleTableConfigRecord(this.triggerRuleGR.getValue(this.TABLE));
  	if (triggerRuleTableGR) {
  		groupField = triggerRuleTableGR.getValue(this.TRIGGER_GROUP_FIELD);
  		userField = triggerRuleTableGR.getValue(this.TRIGGER_USER_FIELD);
  	}

  	if (this._log.atLevel(GSLog.DEBUG))
  		this._log.logDebug("[process] Trigger rule: " + this.triggerRuleGR.getUniqueValue() + ", group field: " + groupField + ", user field: " + userField);

  	if (!this.recordGR.isValidField(groupField) || !this.recordGR.isValidField(userField)) {
  		if (this._log.atLevel(GSLog.DEBUG))
  			this._log.logDebug("[process] Trigger rule group or user field not valid for table: " + this.recordGR.getRecordClassName());
  		return;
  	}

  	// Must be a GlideElement as existing workflows used by customers expect the variable to be of type element
  	var triggeredGroupElement = null;

  	// Use group defined in trigger rule when performing initial assignment (original behavior)
  	if (this.TRIGGER_RULE_PROCESS === this.eventName)
  		triggeredGroupElement = this.triggerRuleGR[this.GROUP];

  	// Use provided group as record changes may not be saved to DB
  	if (this.TRIGGER_RULE_REASSIGNMENT === this.eventName)
  		triggeredGroupElement = this.recordGR[groupField];

  	if (JSUtil.nil(triggeredGroupElement + "")) {
  		if (this._log.atLevel(GSLog.DEBUG))
  			this._log.logDebug("[process] Group cannot be found for record table: " + this.recordGR.getRecordClassName() + ", sys_id: " + this.recordGR.getUniqueValue());
  		return;
  	}

  	// Check if the assigned user is valid for the group
  	var userSysId = this.recordGR.getValue(userField);
  	if (!JSUtil.nil(userSysId) && this._isUserMemberOfGroup(userSysId, triggeredGroupElement + "")) {
  		if (this._log.atLevel(GSLog.DEBUG))
  			this._log.logDebug("[process] User field: " + userField + " is already populated with the member: " + userSysId + " of the group: " + triggeredGroupElement);
  		return;
  	}

  	var triggerAction = this.triggerRuleGR.getValue("trigger_action");

  	if (triggerAction === "script")
  		this._executeTriggerScript();

  	if (triggerAction === "workflow")
  		this._startTriggerWorkflow(triggeredGroupElement);
  },

  cleanTriggerRuleWorkflowContextTable: function() {
  	var daysAgo = gs.getProperty("com.snc.trigger_rules.wf_context_flush_days_ago", "3");
  	var triggerWFContextGR = new GlideRecord("trigger_rule_wf_context");
  	triggerWFContextGR.addEncodedQuery("sys_created_on<javascript:gs.daysAgo(" + daysAgo + ")");
  	triggerWFContextGR.query();
  	triggerWFContextGR.deleteMultiple();
  },

  abortActionIfDefaultTriggerRuleExists: function(triggerRuleGR) {
  	var gr = new GlideRecord(this.TRIGGER_RULE);
  	gr.addQuery(this.TABLE, triggerRuleGR.getValue(this.TABLE));
  	gr.addQuery("trigger_group_assigned", true);
  	gr.addQuery("trigger_when", "default");
  	gr.addQuery("sys_id", "!=", triggerRuleGR.getUniqueValue());
  	gr.query();
  	if (!gr.next())
  		return;
  	triggerRuleGR.setAbortAction(true);
  	var ruleLink = "<a href='" + gr.getLink() + "'>" + gr.getDisplayValue() + "</a>";
  	gs.addInfoMessage(gs.getMessage("Only one default trigger rule per table can be defined when triggering on group assignment. Trigger rule: {0} is the default rule for the {1} table", [ruleLink, triggerRuleGR.getDisplayValue(this.TABLE)]));
  },

  getTriggerRuleWhenToActivateAnnotation: function() {
  	return gs.getMessage("Enable 'trigger when group assigned changes' to only process this trigger rule when there is a group assigned and the value changes. Use the 'Trigger when' field to define the default behavior for this table or to make it conditional");
  },

  cancelWorkflows: function() {
  	var workflowUtil = new Workflow();
  	var existingWFContextGR = this._getWorkflowsContext(this.recordGR.getRecordClassName(), this.recordGR.getUniqueValue());
  	while (existingWFContextGR.next()) {
  		workflowUtil.cancelContext(existingWFContextGR.wf_context.getRefRecord());
  	}
  },

  _getWorkflowsContext: function(documentTable, documentId) {
  	var gr = new GlideRecord(this.TRIGGER_RULE_WF_CONTEXT);
  	gr.addQuery(this.DOCUMENT_TABLE, documentTable);
  	gr.addQuery(this.DOCUMENT, documentId);
  	gr.query();
  	return gr;
      },

  _isUserMemberOfGroup: function(userSysId, groupSysId) {
  	var user = GlideUser.getUserByID(userSysId);
  	if (!user) {
  		if (this._log.atLevel(GSLog.DEBUG))
  			this._log.logDebug("[isUserMemberOfGroup] User: " + userSysId + " not found");
  		return false;
  	}

  	return user.isMemberOf(groupSysId);
  },

  _groupHasRota: function(groupSysId) {
  	var rotaGR = new GlideRecord("cmn_rota");
  	rotaGR.addActiveQuery();
  	rotaGR.addQuery(this.GROUP, groupSysId);
  	rotaGR.setLimit(1);
  	rotaGR.query();
  	return rotaGR.hasNext();
  },

  _getTriggerGroupField: function() {
  	var triggerGroupField = "";
  	if (this.triggerRuleGR && this.triggerRuleGR.trigger_rule_table_cfg)
  		triggerGroupField = this.triggerRuleGR.trigger_rule_table_cfg[this.TRIGGER_GROUP_FIELD] + "";

  	return JSUtil.nil(triggerGroupField) ? this.ASSIGNMENT_GROUP : triggerGroupField;
  },

  _getTriggerUserField: function() {
  	var triggerUserField = "";
  	if (this.triggerRuleGR && this.triggerRuleGR.trigger_rule_table_cfg)
  		triggerUserField = this.triggerRuleGR.trigger_rule_table_cfg[this.TRIGGER_USER_FIELD] + "";

  	return JSUtil.nil(triggerUserField) ? this.ASSIGNED_TO : triggerUserField;
  },

  _getJournalField: function() {
  	var journalField = "";
  	if (this.triggerRuleGR && this.triggerRuleGR.trigger_rule_table_cfg)
  		journalField = this.triggerRuleGR.trigger_rule_table_cfg[this.JOURNAL_FIELD] + "";

  	return JSUtil.nil(journalField) ? this.WORK_NOTES : journalField;
  },

  _executeTriggerScript: function() {
  	var triggerScript = this.triggerRuleGR.getValue(this.TRIGGER_SCRIPT);

  	if (JSUtil.nil(triggerScript)) {

  		if (this._log.atLevel(GSLog.DEBUG))
  			this._log.logDebug("[executeTriggerScript] Trigger rule action is set to script but trigger_script field is empty");

  		return;
  	}

  	var evaluator = new GlideScopedEvaluator();
  	evaluator.putVariable("current", this.recordGR);
  	evaluator.putVariable("rule", this.triggerRuleGR);
  	evaluator.putVariable(this.TRIGGER_GROUP_FIELD, this._getTriggerGroupField());
  	evaluator.putVariable(this.TRIGGER_USER_FIELD, this._getTriggerUserField());
  	evaluator.putVariable(this.JOURNAL_FIELD, this._getJournalField());
  	var result = evaluator.evaluateScript(this.triggerRuleGR, this.TRIGGER_SCRIPT);

  	if (this._log.atLevel(GSLog.DEBUG))
  		this._log.logDebug("[_executeTriggerScript] script result: " + result);
  },

  _startTriggerWorkflow: function(triggeredGroupElement) {
  	var triggerWorkflow = this.triggerRuleGR.getValue("trigger_workflow");
  	if (JSUtil.nil(triggerWorkflow)) {
  		if (this._log.atLevel(GSLog.DEBUG))
  			this._log.logDebug("[startWorkflow] Trigger rule action is set to workflow but trigger_workflow field is empty");
  		return;
  	}

  	var workflowUtil = new Workflow();
  	//Cancel all existing workflows on this record initiated from On-Call Trigger Rule.
  	this.cancelWorkflows();

  	this.workflowVars.assignment_group = triggeredGroupElement;
  	this.workflowVars.trigger_group_field = this._getTriggerGroupField();
  	this.workflowVars.trigger_user_field = this._getTriggerUserField();
  	this.workflowVars.journal_field = this._getJournalField();

  	if (this._log.atLevel(GSLog.DEBUG))
  		this._log.logDebug("[startWorkflow] workflowVars: " + JSON.stringify(this.workflowVars));

  	var runInRecordDomain = GlidePluginManager.isActive("com.glide.domain.msp_extensions") && gs.getProperty("com.snc.on_call_rotation.trigger_workflows_in_record_domain", "false") == "true";
  	var currentDomain = gs.getSession().getCurrentDomainID(); // always the value will be 'global', as async events are processed as admin in global domain.
  	
  	/* Workflow should start from task domain - so it will have access to workflows created in both global and task domain */
  	if (runInRecordDomain)
  		gs.getSession().setDomainID(this.recordGR.getValue("sys_domain"));
  	
  	var wfContextGR = workflowUtil.startFlow(triggerWorkflow, this.recordGR, this.recordGR.operation(), this.workflowVars);
  	
  	/* Reset domain */
  	if (runInRecordDomain)
  		gs.getSession().setDomainID(currentDomain);
  	
  	if (!wfContextGR) {
  		if (this._log.atLevel(GSLog.DEBUG))
  			this._log.logDebug("[startWorkflow] Trigger rule workflow: " + triggerWorkflow + " did not attach to the record table: " + this.recordGR.getRecordClassName() + ", sys_id: " + this.recordGR.getUniqueValue());
  		return;
  	}

  	this.logWorkflowContext(this.recordGR.getRecordClassName(), this.recordGR.getUniqueValue(), wfContextGR.getUniqueValue(), this.triggerRuleGR.getUniqueValue());

  	this.recordGR.update();
  },

  _getWorkflowContext: function(documentTable, documentId) {
  	var gr = new GlideRecord(this.TRIGGER_RULE_WF_CONTEXT);
  	gr.addQuery(this.DOCUMENT_TABLE, documentTable);
  	gr.addQuery(this.DOCUMENT, documentId);
  	gr.orderByDesc(this.SYS_CREATED_ON);
  	gr.setLimit(1);
  	gr.query();
  	if (gr.next())
  		return gr;
  	return null;
  },

  logWorkflowContext: function(documentTable, documentId, workflowContextId, triggerRuleSysId, parentWFContextId) {

  	if (this._log.atLevel(GSLog.DEBUG))
  		this._log.logDebug("[logWorkflowContext] documentTable: " + documentTable + " documentId: " + documentId + " workflowContextId: " + workflowContextId + " triggerRuleSysId: " + triggerRuleSysId + " parentWFContextId: " + parentWFContextId);

  	var gr = new GlideRecord(this.TRIGGER_RULE_WF_CONTEXT);
  	gr.setValue(this.DOCUMENT_TABLE, documentTable);
  	gr.setValue(this.DOCUMENT, documentId);
  	gr.setValue(this.WF_CONTEXT, workflowContextId);
  	gr.setValue(this.TRIGGER_RULE, triggerRuleSysId);
  	if (parentWFContextId)
  		gr.setValue(this.PARENT_WF_CONTEXT, parentWFContextId);

  	var sysId = gr.insert();

  	if (this._log.atLevel(GSLog.DEBUG))
  		this._log.logDebug("[logWorkflowContext] trigger_rule_wf_context sysId: " + sysId);

  	return sysId;
  },

  type: 'TriggerRuleSNC'
};

Sys ID

57891886732220102eb52d2b04f6a729

Offical Documentation

Official Docs: