Name

global.StateFlow

Description

No description available

Script

var StateFlow = Class.create();
StateFlow.prototype = {
  initialize: function() {
  },
  
  rebuildFlows: function(table) {
  	table = table || null;
  	var gr = new GlideRecord("sf_state_flow");
  	gr.addQuery('active', true);
  	if (table)
  		gr.addQuery('table', table);
  	gr.query();
  	
  	while (gr.next()) {
  		if (gr.start_text != "") {
  			var choice = new GlideRecord("sys_choice");
  			choice.addQuery("name", gr.table);
  			choice.addQuery("element", "state");
  			choice.addQuery("value", gr.start_text);
  			choice.query();
  			if (choice.next()) {
  				gr.starting_state = choice.sys_id;
  				gr.translated_starting_state = choice.label;
  			}
  		}
  		if (gr.end_text != "") {
  			var choice = new GlideRecord("sys_choice");
  			choice.addQuery("name", gr.table);
  			choice.addQuery("value", gr.end_text);
  			choice.addQuery("element", "state");
  			choice.query();
  			if (choice.next()) {
  				gr.ending_state = choice.sys_id;
  				gr.translated_ending_state = choice.label;
  			}
  		}
  		gr.update();
  	}
  },
  
  getValidStates: function(sys_class, table, state) {
  	var labels = [];
  	var values = [];
  	var sequence = [];
  	var languageValue = gs.getSession().getLanguage();
  	
  	var gr = new GlideRecord("sys_choice");
  	gr.addQuery("inactive", false);
  	gr.addQuery("element", "state");
  	gr.addQuery("value", state);
  	gr.addQuery("name", table);
  	gr.orderBy("sequence");
  	gr.query();
  	if (gr.next()) {
  		labels.push(this._getChoiceLabel(gr, languageValue));
  		values.push(gr.value);
  		sequence.push(gr.sequence);
  	}
  			
  	gr = new GlideRecord(sys_class);
  	gr.addQuery("start_text", state);
  	gr.addQuery("table", table);
  	gr.addQuery("active", true);
  	gr.query();
  		
  	var stateArray = [];
  	//Now push all the ending states
  	while (gr.next()) {
  		var stGr = new GlideRecord("sys_choice");
  		stGr.addQuery("inactive", false);
  		stGr.addQuery("element", "state");
  		stGr.addQuery("value", gr.end_text);
  		stGr.addQuery("name", table);
  		stGr.query();
  		if (stGr.next()) {
  			stateArray.push({label: this._getChoiceLabel(stGr, languageValue), value: stGr.value, sequence: stGr.sequence});
  		}
  	}
  	
  	stateArray.sort(function(x,y) {
  		if (x.sequence < y.sequence) {
  			return -1;
  		}
  		if (x.sequence > y.sequence) {
  			return 1;
  		}
  		return 0;	
  	});
  	
  	for	(var i = 0; i < stateArray.length; i++) {
  		labels.push(stateArray[i].label);
  		values.push(stateArray[i].value);
  		sequence.push(stateArray[i].sequence);
  	}

  	// Get field requirements
  	var fieldReq = this.getFieldRequirements(sys_class, table, state, "");
  	return {labels:labels, values:values, sequence:sequence,
  	mandatory:fieldReq.mandatory, notmandatory:fieldReq.notmandatory, readonly:fieldReq.readonly,
  	notreadonly:fieldReq.notreadonly, visible:fieldReq.visible, notvisible:fieldReq.notvisible};
  },
  
  _getChoiceLabel: function(grChoice, languageValue) { 
  	if (grChoice.language == languageValue) 
  		return grChoice.label;
  	
  	var gr = new GlideRecord("sys_choice");
  	gr.addQuery("inactive", false);
  	gr.addQuery("element", grChoice.element);
  	gr.addQuery("value", grChoice.value);
  	gr.addQuery("name", grChoice.name);
  	gr.addQuery("language", languageValue);
  	gr.query();
  	if (gr.next())
  		return gr.label;
  		
  	// en is the default, don't just pick a random one, go get EN
  	if (languageValue != 'en')
  		return this._getChoiceLabel(grChoice, 'en');
  	return grChoice.label;
  },
  
  getFieldRequirements: function(sys_class, table, state, oldState) {
  	var mandatory = "";
  	var notmandatory = "";
  	var readonly = "";
  	var notreadonly = "";
  	var visible = "";
  	var notvisible = "";
  	var isLoad = true;
  	if (oldState)
  		isLoad = (state == oldState);
  	var gr = new GlideRecord(sys_class);
  	if (isLoad)
  		gr.addQuery("start_text", "");
  	else
  		gr.addQuery("start_text", "").addOrCondition("start_text", oldState);
  	gr.addQuery("end_text", state);
  	gr.addQuery("table", table);
  	gr.addQuery("active", true);
  	gr.query();
  	
  	// Combine all field requirements that fit this state transition
  	while (gr.next()) {
  		if (gr.mandatory_fields)
  			mandatory += this._translateFields(gr.mandatory_fields);
  		if (gr.visible_fields)
  			visible += this._translateFields(gr.visible_fields);
  		if (gr.read_only_fields)
  			readonly += this._translateFields(gr.read_only_fields);
  		if (gr.not_mandatory)
  			notmandatory += this._translateFields(gr.not_mandatory);
  		if (gr.not_visible)
  			notvisible += this._translateFields(gr.not_visible);
  		if (gr.not_read_only)
  			notreadonly += this._translateFields(gr.not_read_only);
  	}
  	return {mandatory:mandatory, notmandatory:notmandatory, readonly:readonly, notreadonly:notreadonly,
  	visible:visible, notvisible:notvisible};
  },
  
  _translateFields: function(fieldList) {
  	if (fieldList) {
  		var fields = fieldList.split(",");
  		var dict = new GlideRecord("sys_dictionary");
  		var converted = "";
  		for (var i=0; i < fields.length; i++) {
  			if (dict.get(fields[i]))
  				converted += dict.element + ",";
  		}
  		return converted;
  	}
  	return "";
  },
  
  validateMandatory: function(current, previous, tableName) {
  	var returnValue = true;
  	var table = new GlideRecord(tableName);
  	var defaultValue = table.getElement('state').getED().getDefault();
  	if (defaultValue.indexOf('javascript:') == 0) {
  		table.putCurrent();
  		defaultValue = GlideEvaluator.evaluateString(defaultValue);
  		table.popCurrent();
  	}
  	
  	var gr = new GlideRecord("sf_state_flow");
  	gr.addQuery("table", tableName);
  	gr.addQuery("mandatory_fields", "!=", "");
  	gr.addQuery("end_text", current.state);
  	var cond = gr.addQuery("start_text", "");
  	
  	if (!current.isNewRecord())
  		cond.addOrCondition("start_text", previous.state);
  	else
  		cond.addOrCondition("start_text", defaultValue);
  	
  	gr.addQuery("active", "true");
  	gr.query();
  	while (gr.next()) {
  		var mandatoryFields = this._translateFields(gr.mandatory_fields);
  		if (!mandatoryFields)
  			continue;
  		var mandatoryList = mandatoryFields.split(",");
  		for (var i=0; i < mandatoryList.length; i++) {
  			// if empty, fail
  			if (mandatoryList[i]) {
  				if (!current.getValue(mandatoryList[i])) {
  					gs.addErrorMessage(gs.getMessage('Mandatory field not filled in for {0}', this._getDisplay(mandatoryList[i], tableName, current)));
  					returnValue = false;
  				}
  			}
  		}
  	}
  	return returnValue;
  },
  
  _getDisplay: function(columnName, tableName, current) {
  	var label = current[columnName].getLabel();
  	return label;
  },
  
  processFlow: function(current, flow_id, type) {
  	type = type || null;
  	var gr = this._getFlow(flow_id);
  	if (!gr.isValid())
  		return;
  	
  	if (gr.active == true) {
  		if (!gr.end_text.nil())
  			current.setValue("state", gr.end_text);
  		if (type != 'automatic' && type != 'manual')
  			return gr.end_text;
  		
  		var executedScript = this._executeScript(gr, type + "_script", current);
  		if (this._needsUpdate(gr, type, executedScript, gr.end_text.nil())) {
  			if ((!this._isNewRecord(current, type)) || (type == "manual")) {
  				current.update();
  			}
  		}
  	}
  },
  
  fireEvents: function(current, previous, table_name) {
  	var gr = new GlideRecord("sf_state_flow");
  	gr.addQuery("table", table_name);
  	gr.addQuery("event_rule", "!=", "");
  	gr.addQuery("end_text", current.state);
  	gr.addQuery("start_text", "").addOrCondition("start_text", previous.state);
  	gr.addQuery("active", "true");
  	gr.query();
  	while (gr.next())
  		gs.eventQueue(gr.event.event_name, current, current.state, previous.state);
  },
  
  addWorkNotes: function(current, previous, table_name) {
  	var gr = new GlideRecord("sf_state_flow");
  	gr.addQuery("table", table_name);
  	gr.addQuery("work_notes", "!=", "");
  	gr.addQuery("end_text", current.state);
  	gr.addQuery("active", "true");
  	gr.addQuery("start_text", "").addOrCondition("start_text", previous.state);
  	gr.orderByDesc("start_text");
  	gr.query();
  	if (gr.next()) {
  		var workNotes = gr.work_notes + "";
  		current.work_notes = workNotes;
  	}
  },
  
  _needsUpdate: function(current, type, executedScript, endingStateIsNil) {
  	if ((type == 'manual') && (executedScript || !endingStateIsNil))
  		return true;
  	if ((current.business_rule) && (!endingStateIsNil))
  		if (current.business_rule.when != 'before')
  		return true;
  	return false;
  },
  
  _isNewRecord: function(current) {
  	var c = new GlideRecord(current.getTableName());
  	return !c.get(current.getValue('sys_id') + '');
  },
  
  validFlow: function(current, flow_id, type) {
  	var gr = this._getFlow(flow_id);
  	var answer = false;
  	if (gr.active == true) {
  		answer = this._checkCondition(gr, type + "_string", current) && this._hasRoles(gr, type, 'roles') && this._hasRoles(gr, type, type + '_roles');
  		if (answer == true && gr.getValue(type + "_condition") != null)
  			answer = (new sn_state_flow.StateFlowFilter()).match(current, flow_id, type, true);
  	}
  	return answer;
  },
  
  _hasRoles: function(gr, type, field) {
  	var myUserObject = gs.getUser();
  	var roles = gr.getValue(field);
  	if (type != null && roles != null) {
  		var arrRoles = roles.split(",");
  		for (var x=0;x<arrRoles.length;x++) {
  			var sr = new GlideRecord('sys_user_role');
  			sr.get(arrRoles[x]);
  			if (myUserObject.hasRole(sr.getValue('name')))
  				return true;
  		}
  		return false;
  	}
  	return true;
  },
  
  createDefaultValue: function(current, basetable, type) {
  	var gr;
  	if (type == "override") {
  		gr = new GlideRecord("sys_dictionary_override");
  		gr.get(current.override);
  		gr.setValue("name", current.table);
  		gr.setValue("base_table", basetable);
  		gr.setValue("default_value_override", true);
  		gr.setValue("default_value", "javascript: new global.StateFlow().processFlow(current, '" + current.sys_id + "');");
  		gr.setValue("element", "state");
  		if (!gr.isValidRecord())
  			current.override = gr.insert();
  		else {
  			gr.update();
  			current.override = gr.getValue("sys_id");
  		}
  		current.update();
  	} else if (type == "default") {
  		gr = new GlideRecord("sys_dictionary");
  		gr.addQuery("name", current.table);
  		gr.addQuery("element", "state");
  		gr.query();
  		gr.next();
  		gr.setValue("default_value", "javascript: new global.StateFlow().processFlow(current, '" + current.sys_id + "');");
  		gr.update();
  	}
  	
  	return {
  		'table': gr.getTableName() + '', 
  		'sys_id': gr.sys_id + ''
  	};
  },
  
  createUIAction: function(current, update) {
  	var state = "";
  	if (!current.start_text.nil())
  		state = "current.state==" + current.start_text + " && ";
  	var gr = new GlideRecord("sys_ui_action");
  	gr.setValue("table", current.table);
  	gr.setValue("name", current.name);
  	gr.setValue("action_name", this._camelCase(current.name));
  	gr.setValue("form_button", true);
  	gr.setValue("active", true);
  	gr.setValue("show_insert", true);
  	gr.setValue("show_update", true);
  	gr.setValue("condition", state + "(new global.StateFlow().validFlow(current, '" + current.sys_id + "', 'manual'));");
  	gr.setValue("script", "new global.StateFlow().processFlow(current, '" + current.sys_id + "', 'manual');");
  	current.ui_action = gr.insert();
  	if(update)
  		current.update();
  },
  
  createBusinessRule: function(current, update) {
  	var state = "";
  	if (!current.start_text.nil())
  		state = "current.state==" + current.start_text + " && ";
  	var gr = new GlideRecord("sys_script");
  	gr.setValue("collection", current.table);
  	gr.setValue("name", current.name);
  	gr.setValue("when", "before");
  	gr.setValue("active", true);
  	gr.setValue("action_insert", true);
  	gr.setValue("action_update", true);
  	gr.setValue("execute_function" ,false);
  	gr.setValue("condition", state + "(new global.StateFlow().validFlow(current, '" + current.sys_id + "', 'automatic'));");
  	gr.setValue("script", "new global.StateFlow().processFlow(current, '" + current.sys_id + "', 'automatic');");
  	current.business_rule = gr.insert();
  	if(update)
  		current.update();
  },
  
  createClientScript: function(current) {
  	var clientScript = this._getClientScript(current);
  	if (clientScript == null)
  		clientScript = this._createClientScript(current);
  	this._linkClientScript(current, clientScript);
  },
  
  linkClientScript: function(current) {
  	var clientScript = this._getClientScript(current);
  	if (clientScript != null)
  		this._linkClientScript(current, clientScript);
  },
  
  _getClientScript: function(current) {
  	var gr = new GlideRecord(current.sys_class_name);
  	gr.addQuery("table", current.table);
  	gr.addQuery("client_script", "!=", "");
  	gr.query();
  	if (gr.next())
  		return gr.client_script;
  	return null;
  },
  
  _linkClientScript: function(current, clientScript) {
  	var gr = new GlideRecord(current.sys_class_name);
  	gr.addQuery("table", current.table);
  	gr.addQuery("client_script", "");
  	gr.query();
  	while (gr.next()) {
  		gr.client_script = clientScript;
  		gr.update();
  	}
  },
  
  createChangeClientScript: function(current) {
  	var clientScript = this._getChangeClientScript(current);
  	if (clientScript == null)
  		clientScript = this._createChangeClientScript(current);
  	this._linkChangeClientScript(current, clientScript);
  },
  
  linkChangeClientScript: function(current) {
  	var clientScript = this._getChangeClientScript(current);
  	if (clientScript != null)
  		this._linkChangeClientScript(current, clientScript);
  },
  
  _getChangeClientScript: function(current) {
  	var gr = new GlideRecord(current.sys_class_name);
  	gr.addQuery("table", current.table);
  	gr.addQuery("change_client_script", "!=", "");
  	gr.query();
  	if (gr.next())
  		return gr.change_client_script;
  	return null;
  },
  
  _linkChangeClientScript: function(current, clientScript) {
  	var gr = new GlideRecord(current.sys_class_name);
  	gr.get(current.sys_id);
  	gr.change_client_script = clientScript;
  	gr.update();
  },
  
  checkDeleteClientScripts: function(current) {
  	this.checkDeleteChangeClientScript(current);
  	this.checkDeleteClientScript(current);
  },
  
  checkDeleteChangeClientScript: function(current) {
  	var gr = new GlideRecord("sf_state_flow");
  	gr.addQuery("sys_id", "!=", current.sys_id);
  	gr.addQuery("change_client_script", "!=", "");
  	gr.query();
  	if (!gr.next()) {
  		var deleteScript = new GlideRecord("sys_script_client");
  		if (deleteScript.get(current.change_client_script))
  			deleteScript.deleteRecord();
  	}
  },
  
  checkDeleteClientScript: function(current) {
  	var gr = new GlideRecord("sf_state_flow");
  	gr.addQuery("sys_id", "!=", current.sys_id);
  	gr.addQuery("client_script", "!=", "");
  	gr.query();
  	if (!gr.next()) {
  		var deleteScript = new GlideRecord("sys_script_client");
  		if (deleteScript.get(current.client_script))
  			deleteScript.deleteRecord();
  	}
  },
  
  createEventRule: function(current) {
  	this.createSingletonRule(current, "event");
  },
  
  checkDeleteEventRule: function(current) {
  	this.checkDeleteSingletonRule(current, "event");
  },
  
  createWorkNotesRule: function(current) {
  	this.createSingletonRule(current, "work_notes");
  },
  
  checkDeleteWorkNotesRule: function(current) {
  	this.checkDeleteSingletonRule(current, "work_notes");
  },
  
  createSingletonRule: function(current, type) {
  	var foundRule = this._getRule(current, type);
  	if (foundRule == null)
  		foundRule = this._createRule(current, type);
  	current.setValue(type + "_rule", foundRule);
  },
  
  checkDeleteSingletonRule: function(current, type) {
  	var foundRule = this._getRule(current, type);
  	if (foundRule != null) {
  		// See if any other records need this rule
  		var gr = new GlideRecord(current.sys_class_name);
  		gr.addQuery("sys_id", "!=", current.sys_id);
  		gr.addQuery(type + "_rule", "!=", "");
  		gr.query();
  		if (gr.getRowCount() < 1) {
  			var deleteRule = new GlideRecord("sys_script");
  			deleteRule.get(foundRule);
  			deleteRule.deleteRecord();
  			
  			// Ensure no other records have this rule
  			var grCheck = new GlideRecord(current.sys_class_name);
  			grCheck.addQuery("sys_id", "!=", current.sys_id);
  			grCheck.addQuery(type + "_rule", "!=", "");
  			grCheck.query();
  			while (grCheck.next()) {
  				grCheck.setValue(type + "_rule", "");
  				grCheck.update();
  			}
  		}
  	}
  },
  
  linkRule: function(current, type) {
  	var foundRule = this._getRule(current, type);
  	if (foundRule != null)
  		this._linkRule(current, foundRule, type);
  },
  
  _getRule: function(current, type) {
  	var gr = new GlideRecord(current.sys_class_name);
  	gr.addQuery("table", current.table);
  	gr.addQuery(type + "_rule", "!=", "");
  	gr.query();
  	if (gr.next())
  		return gr.getValue(type + "_rule");
  	return null;
  },
  
  _linkRule: function(current, foundRule, type) {
  	var gr = new GlideRecord(current.sys_class_name);
  	gr.addQuery("table", current.table);
  	gr.addQuery(type + "_rule", "");
  	gr.addQuery(type, "!=", "");
  	gr.query();
  	while (gr.next()) {
  		gr.setValue(type + "_rule", foundRule);
  		gr.update();
  	}
  },
  
  _getFlow: function(flow_id) {
  	var gr = new GlideRecord("sf_state_flow");
  	gr.get(flow_id);
  	return gr;
  },
  
  _checkCondition: function(gr, type, current) {
  	var answer = true;
  	
  	if (gr.getValue(type) != null)
  		answer = this._execute(gr, type, current);
  	return answer == true;
  },
  
  _executeScript: function(gr, type, current) {
  	var answer = false;
  	if (gr.getValue(type) != null) {
  		answer = true;
  		this._execute(gr, type, current);
  	}
  	return answer == true;
  },
  
  _execute: function(gr, type, current) {
  	var evalString = gr.getValue(type) + '';
  	var answer = true;
  	
  	if (evalString != null) {
  		var evaluator = new GlideScopedEvaluator();
  		current.putCurrent();
  		answer = evaluator.evaluateScript(gr, type, {});
  		current.popCurrent();
  	}
  	return answer == true;
  },
  
  _createClientScript: function(current) {
  	var gr = new GlideRecord("sys_script_client");
  	gr.setValue("table", current.table);
  	gr.setValue("type", "onLoad");
  	gr.setValue("global", true);
  	gr.setValue("active", true);
  	gr.setValue("name", current.table + " state flow");
  	gr.setValue("script", this._buildClientScript(current));
  	return (clientScript = gr.insert());
  },
  
  _createChangeClientScript: function(current) {
  	var gr = new GlideRecord("sys_script_client");
  	gr.setValue("table", current.table);
  	gr.setValue("type", "onChange");
  	gr.setValue("field", "state");
  	gr.setValue("global", true);
  	gr.setValue("active", true);
  	gr.setValue("name", current.table + " change state flow");
  	gr.setValue("script", this._buildChangeClientScript(current));
  	return (clientScript = gr.insert());
  },
  
  _buildClientScript : function(current) {
  	var retString = "";
  	retString = retString + "function onLoad() {\n";
  	retString = retString + "	var ga = new GlideAjax('global.StateFlowAJAX');\n";
  	retString = retString + "	ga.addParam('sysparm_name', 'getValidStates');\n";
  	retString = retString + "	ga.addParam('sysparm_state', g_form.getValue('state'));\n";
  	retString = retString + "	ga.addParam('sysparm_table', '" + current.table + "');\n";
  	retString = retString + "	ga.addParam('sysparm_sys_class', '" + current.sys_class_name + "');\n";
  	retString = retString + "	ga.getXML(clientScriptAjaxResponse);\n";
  	retString = retString + "}\n\n";
  	
  	retString = retString + "function clientScriptAjaxResponse(serverResponse) {\n";
  	retString = retString + "	//Clear the list and add only valid options\n";
  	retString = retString + "	g_form.clearOptions('state');\n";
  	retString = retString + "	var result = serverResponse.responseXML.getElementsByTagName('result');\n";
  	retString = retString + "	if (result.length > 0) {\n";
  	retString = retString + "		var value = result[0].getAttribute('values').split(',');\n";
  	retString = retString + "		var label = result[0].getAttribute('labels').split(',');\n";
  	retString = retString + "		for (var i = 0; i < value.length; i++)\n";
  	retString = retString + "			g_form.addOption('state', value[i], label[i]);\n";
  	retString = retString + "		var mandatory = result[0].getAttribute('mandatory').split(',');\n";
  	retString = retString + "		var readonly = result[0].getAttribute('readonly').split(',');\n";
  	retString = retString + "		var visible = result[0].getAttribute('visible').split(',');\n";
  	retString = retString + "		var notmandatory = result[0].getAttribute('notmandatory').split(',');\n";
  	retString = retString + "		var notreadonly = result[0].getAttribute('notreadonly').split(',');\n";
  	retString = retString + "		var notvisible = result[0].getAttribute('notvisible').split(',');\n";
  	retString = retString + "		for (var i=0; i < mandatory.length; i++)\n";
  	retString = retString + "			if (mandatory[i])\n";
  	retString = retString + "				g_form.setMandatory(mandatory[i], true);\n";
  	retString = retString + "		for (var i=0; i < notmandatory.length; i++)\n";
  	retString = retString + "			if (notmandatory[i])\n";
  	retString = retString + "				g_form.setMandatory(notmandatory[i], false);\n";
  	retString = retString + "		for (var i=0; i < readonly.length; i++)\n";
  	retString = retString + "			if (readonly[i])\n";
  	retString = retString + "				g_form.setReadOnly(readonly[i], true);\n";
  	retString = retString + "		for (var i=0; i < notreadonly.length; i++)\n";
  	retString = retString + "			if (notreadonly[i])\n";
  	retString = retString + "				g_form.setReadOnly(notreadonly[i], false);\n";
  	retString = retString + "		for (var i=0; i < visible.length; i++)\n";
  	retString = retString + "			if (visible[i])\n";
  	retString = retString + "				g_form.setDisplay(visible[i], true);\n";
  	retString = retString + "		for (var i=0; i < notvisible.length; i++)\n";
  	retString = retString + "			if (notvisible[i])\n";
  	retString = retString + "				g_form.setDisplay(notvisible[i], false);\n";
  	retString = retString + "	}\n";
  	retString = retString + "}\n";
  	return retString;
  },
  
  _buildChangeClientScript : function(current) {
  	var retString = "";
  	retString = retString + "function onChange(control, oldValue, newValue, isLoading, isTemplate) {\n"
  	retString = retString + "   if (isLoading || newValue == '') {\n"
  	retString = retString + "      return;\n"
  	retString = retString + "   }\n"
  	retString = retString + "	var ga = new GlideAjax('global.StateFlowAJAX');\n";
  	retString = retString + "	ga.addParam('sysparm_name', 'getFieldRequirements');\n";
  	retString = retString + "	ga.addParam('sysparm_state', newValue);\n";
  	retString = retString + "	if (typeof g_scratchpad.newValue == 'undefined')\n";
  	retString = retString + "		ga.addParam('sysparm_old_state', oldValue);\n";
  	retString = retString + "	else\n";
  	retString = retString + "		ga.addParam('sysparm_old_state', g_scratchpad.newValue);\n";
  	retString = retString + "	g_scratchpad.newValue = newValue;\n";
  	retString = retString + "	ga.addParam('sysparm_table', '" + current.table + "');\n";
  	retString = retString + "	ga.addParam('sysparm_sys_class', '" + current.sys_class_name + "');\n";
  	retString = retString + "	ga.getXML(changeClientScriptAjaxResponse);\n";
  	retString = retString + "}\n\n";
  	
  	retString = retString + "function changeClientScriptAjaxResponse(serverResponse) {\n";
  	retString = retString + "	// Make all requested updates to the form\n";
  	retString = retString + "	var result = serverResponse.responseXML.getElementsByTagName('result');\n";
  	retString = retString + "	if (result.length > 0) {\n";
  	retString = retString + "		var mandatory = result[0].getAttribute('mandatory').split(',');\n";
  	retString = retString + "		var readonly = result[0].getAttribute('readonly').split(',');\n";
  	retString = retString + "		var visible = result[0].getAttribute('visible').split(',');\n";
  	retString = retString + "		var notmandatory = result[0].getAttribute('notmandatory').split(',');\n";
  	retString = retString + "		var notreadonly = result[0].getAttribute('notreadonly').split(',');\n";
  	retString = retString + "		var notvisible = result[0].getAttribute('notvisible').split(',');\n";
  	retString = retString + "		for (var i=0; i < mandatory.length; i++)\n";
  	retString = retString + "			if (mandatory[i])\n";
  	retString = retString + "				g_form.setMandatory(mandatory[i], true);\n";
  	retString = retString + "		for (var i=0; i < notmandatory.length; i++)\n";
  	retString = retString + "			if (notmandatory[i])\n";
  	retString = retString + "				g_form.setMandatory(notmandatory[i], false);\n";
  	retString = retString + "		for (var i=0; i < readonly.length; i++)\n";
  	retString = retString + "			if (readonly[i])\n";
  	retString = retString + "				g_form.setReadOnly(readonly[i], true);\n";
  	retString = retString + "		for (var i=0; i < notreadonly.length; i++)\n";
  	retString = retString + "			if (notreadonly[i])\n";
  	retString = retString + "				g_form.setReadOnly(notreadonly[i], false);\n";
  	retString = retString + "		for (var i=0; i < visible.length; i++)\n";
  	retString = retString + "			if (visible[i])\n";
  	retString = retString + "				g_form.setDisplay(visible[i], true);\n";
  	retString = retString + "		for (var i=0; i < notvisible.length; i++)\n";
  	retString = retString + "			if (notvisible[i])\n";
  	retString = retString + "				g_form.setDisplay(notvisible[i], false);\n";
  	retString = retString + "	}\n";
  	retString = retString + "}\n";
  	return retString;
  },
  
  _createRule: function(current, type) {
  	if (type == "event")
  		return this._createEventRule(current);
  	if (type == "work_notes")
  		return this._createWorkNotesRule(current);
  },
  
  _createWorkNotesRule: function(current) {
  	var gr = new GlideRecord("sys_script");
  	gr.setValue("collection", current.table);
  	gr.setValue("name", gs.getMessage("State Flow Notes for {0}", current.getDisplayValue("table")));
  	gr.setValue("when", "before");
  	gr.setValue("order", "10001"); // This should run last, to catch any state changes made by business rules
  	gr.setValue("active", true);
  	gr.setValue("action_insert", true);
  	gr.setValue("action_update", true);
  	gr.setValue("condition", "");
  	gr.setValue("execute_function", false);
  	gr.setValue("script", "if (!new global.StateFlow().validateMandatory(current, previous, '" + current.table + "')) \n " +
  	"    current.setAbortAction(true);\n" +
  	"if (current.state.changes())\n" +
  	"    new global.StateFlow().addWorkNotes(current, previous, '" + current.table + "');");
  	return gr.insert();
  },
  
  _createEventRule: function(current) {
  	var gr = new GlideRecord("sys_script");
  	gr.setValue("collection", current.table);
  	gr.setValue("name", gs.getMessage("State Flow Events for {0}", current.getDisplayValue("table")));
  	gr.setValue("when", "after");
  	gr.setValue("active", true);
  	gr.setValue("action_insert", true);
  	gr.setValue("action_update", true);
  	gr.setValue("condition", "current.state.changes()");
  	gr.setValue("execute_function", false);
  	gr.setValue("script", "new global.StateFlow().fireEvents(current, previous, '" + current.table + "');");
  	return gr.insert();
  },
  
  _camelCase: function(input) {
  	return input.toLowerCase().replace(/ (.)/g, function(match, group1) {
  		return group1.toUpperCase();
  	});
  },
  
  type: 'StateFlow'
}

Sys ID

9dba190cd7230100fceaa6859e61035f

Offical Documentation

Official Docs: