Name

global.StdChangeTaskUtilsSNC

Description

This function contains utility functions related to creating/updating and the use of Standard Change Task templates. Public functions - getFieldsConfig

Script

var StdChangeTaskUtilsSNC = Class.create();
StdChangeTaskUtilsSNC.prototype = Object.extendsObject(StdChangeUtilsSNC, {

  PROP_MANDATORY_FIELDS: 'mandatory_task_fields',
  PROP_UNMODIFIABLE_FIELDS: 'restricted_task_fields',
  PROP_DEFAULT_VALUES: 'default_task_values',
  PROP_READONLY_FIELDS: 'readonly_task_fields',
  PROP_FIELDS_TO_COPY: 'task_fields_to_copy',

  initialize: function(request, responseXML, gc) {
  	AbstractAjaxProcessor.prototype.initialize.call(this, request,
  		responseXML,
  		gc);
  	this.log = new GSLog('com.snc.std_change_request.log', 'StdChangeTaskUtilsSNC');
  	this.arrayUtil = new ArrayUtil();
  	this.jsonUtil = new JSON();
  	this.TABLE_LABEL_CHANGE_TASK = new GlideRecord(this.TABLE_NAME_CHANGE_TASK).getLabel();
  },

  ajaxFunction_getPredefinedTemplate: function() {
  	var templateGr = new GlideRecordSecure(this.TABLE_NAME_TASK_TEMPLATE);
  	var sysId = this.getParameter('sysparm_templateId');

  	var resp = {name: "", shortDescription: "", template: ""};
  	if (!templateGr.get(sysId))
  		return this._toXmlAndSet(resp);

  	resp.name = templateGr.getValue("name");
  	resp.shortDescription = templateGr.getValue("short_description");
  	resp.template = templateGr.getValue("template");

  	return this.jsonUtil.encode(resp);
  },

  getDefaultValues: function() {
  	return this._getPropertyValue(this.PROP_DEFAULT_VALUES);
  },

  getMandatoryFields: function() {
  	return this._getCsvPropertyValue(this.PROP_MANDATORY_FIELDS);
  },

  getReadOnlyFields: function() {
  	return this._getCsvPropertyValue(this.PROP_READONLY_FIELDS);
  },

  getFieldsToCopy: function() {
  	return this._getCsvPropertyValue(this.PROP_FIELDS_TO_COPY);
  },

  getFieldsConfig: function() {
  	var resp = {};
  	this._addDefaultValuesConfig(resp, true);
  	this._addMandatoryFieldsConfig(resp);
  	this._addUnmodifiableFieldsConfig(resp);
  	return resp;
  },

  getNextOrderNumber: function(chgTaskTemplateGr) {
  	var orderNumber = 100;
  	if (!chgTaskTemplateGr)
  		return orderNumber;

  	var proposalId = chgTaskTemplateGr.getValue("std_change_proposal");
  	if (!proposalId)
  		return orderNumber;

  	var taskTemplateGr = new GlideAggregate("std_change_proposal_task");
  	taskTemplateGr.addAggregate("MAX", "order");
  	taskTemplateGr.addQuery("std_change_proposal", proposalId);
  	taskTemplateGr.groupBy("std_change_proposal");
  	taskTemplateGr.query();

  	if (taskTemplateGr.next()) {
  		var currentMax = taskTemplateGr.getAggregate("MAX", "order");
  		if (!isNaN(currentMax))
  			orderNumber = 100 + parseInt(currentMax, 10);
  	}

  	return orderNumber;
  },

  isTemplateReadOnly: function() {
  	return !gs.hasRole(this.ROLE_CHG_MANAGER);
  },

  getTemplateValidationResult: function(chgTaskTemplateGr, displayErrors) {
  	var result = {validationPassed: false, errorMsgs: []};

  	if (!chgTaskTemplateGr || !chgTaskTemplateGr.getUniqueValue()) {
  		this.log.logError("validateTemplateValueCompliance: no Standard Change Task template record supplied");
  		return result;
  	}

  	var q = this._parseEncodedQuery(chgTaskTemplateGr.getValue('template'));
  	var mandatoryResult = this._checkMandatoryFields(q, this.TABLE_LABEL_CHANGE_TASK, displayErrors);
  	var restrictedResult = this._checkRestrictedFields(q, this.TABLE_LABEL_CHANGE_TASK, displayErrors);

  	result.validationPassed = mandatoryResult.validationPassed && restrictedResult.validationPassed;
  	result.errorMsgs = mandatoryResult.errorMsgs.concat(restrictedResult.errorMsgs);

  	return result;
  },

  validateTemplateValueCompliance: function(chgTaskTemplateGr, displayErrors) {
  	if (!chgTaskTemplateGr || !chgTaskTemplateGr.getUniqueValue()) {
  		this.log.logError("validateTemplateValueCompliance: no Change Task Template record supplied");
  		return false;
  	}

  	// if displayErrors argument is not provided assume true
  	if (typeof displayErrors === "undefined")
  		displayErrors = true;

  	var q = this._parseEncodedQuery(chgTaskTemplateGr.getValue('template'));

  	var mandatoryResult = this._checkMandatoryFields(q, this.TABLE_LABEL_CHANGE_TASK, displayErrors);
  	var restrictedResult = this._checkRestrictedFields(q, this.TABLE_LABEL_CHANGE_TASK, displayErrors);

  	return mandatoryResult.validationPassed && restrictedResult.validationPassed;
  },

  checkFieldsToCopyWithMandatory: function(mandatoryFields, defaultValues, fieldsToCopy) {
  	var changeTaskGr = new GlideRecord(this.TABLE_NAME_CHANGE_TASK);
  	changeTaskGr.initialize();

  	/* First check that the combination of defaulted fields and fields to copy
  	   covers all the mandatory fields - if it doesn't we can't copy any Change
  	   tasks */
  	var missingFields = [];
  	var fieldName;
  	var defaultFields = this._parseEncodedQuery(defaultValues).names;
  	for (var i = 0; i < mandatoryFields.length; i++) {
  		fieldName = mandatoryFields[i];
  		if (!this.arrayUtil.contains(defaultFields, fieldName) &&
  		    !this.arrayUtil.contains(fieldsToCopy, fieldName))
  			missingFields.push(changeTaskGr[fieldName].getLabel());
  	}

  	return missingFields;
  },

  _getEmptyFields: function(mandatoryFields, defaultFieldsAndVals, changeTaskGr) {
  	var taskNumber = changeTaskGr.getValue("number");
  	var taskURL = changeTaskGr.getLink(true);
  	var emptyFields = null;
  	for (var k = 0; k < mandatoryFields.length; k++) {
  		var fieldName = mandatoryFields[k];
  		var defaultFieldIndex = defaultFieldsAndVals.names.indexOf(fieldName);
  		var defaultFieldValue = "";
  		if (defaultFieldIndex !== -1)
  			defaultFieldValue = defaultFieldsAndVals.vals[defaultFieldIndex];
  		if (changeTaskGr[fieldName].nil() && defaultFieldValue === "") {
  			emptyFields = emptyFields || {number: taskNumber, url: taskURL, fieldNames: []};
  			emptyFields.fieldNames.push(changeTaskGr[fieldName].getLabel());
  		}
  	}
  	return emptyFields;
  },

  _isValidData: function(proposalGr, changeId) {
  	var result = {
  		isValid: false,
  		changeGr: null,
  		changeTaskGr: null
  	};
  	if (!proposalGr || !proposalGr.getUniqueValue())
  		return result;

  	var changeGr = new GlideRecord(this.TABLE_NAME_CHANGE);
  	if (!changeGr.get(changeId))
  		return result;

  	var changeTaskGr = new GlideRecord(this.TABLE_NAME_CHANGE_TASK);
  	changeTaskGr.addQuery("change_request", changeGr.getUniqueValue());
  	changeTaskGr.orderBy("sys_created_on");
  	changeTaskGr.query();
  	if (!changeTaskGr.hasNext())
  		return result;

  	result.isValid = true;
  	result.changeGr = changeGr;
  	result.changeTaskGr = changeTaskGr;
  	return result;
  },

  createTaskTemplatesFromChange: function(proposalGr, changeId) {
  	var validatedData = this._isValidData(proposalGr, changeId);
  	if (!validatedData.isValid)
  		return;

  	var changeTaskGr = validatedData.changeTaskGr;
  	var mandatoryFields = this.getMandatoryFields();
  	var defaultValues = this.getDefaultValues();
  	var fieldsToCopy = this.getFieldsToCopy();
  	var defaultFieldsAndVals = this._parseEncodedQuery(defaultValues);
  	var count = 0;

  	/* First check that the combination of defaulted fields and fields to copy
  	   covers all the mandatory fields - if it doesn't we can't copy any Change
  	   tasks */
  	var missingFields = this.checkFieldsToCopyWithMandatory(mandatoryFields, defaultValues, fieldsToCopy);

  	if (missingFields.length > 0) {
  		var errorMsg = gs.getMessage("Change Task templates could not be created as the following mandatory fields are either not defaulted or not copied from the Change Task:<br/> {0}",
  						 			  missingFields.toString());
  		return [errorMsg];
  	}

  	var copyErrors = [];
  	while (changeTaskGr.next()) {
  		/* First check the Change Task has all the mandatory fields completed
  		   if it doesn't we can't add a template for it and will need to show an error */
  		var emptyFields = this._getEmptyFields(mandatoryFields, defaultFieldsAndVals, changeTaskGr);

  		if (emptyFields) {
  			copyErrors.push(gs.getMessage(
  				"A Change Task Template could not be created from Change Task <a href='{0}'><b>{1}</b></a> as the following mandatory template fields are empty: <b>{2}</b>",
  				[emptyFields.url, emptyFields.number, emptyFields.fieldNames.toString()]));
  			continue;
  		}

  		/* Now create an object of fieldnames and corresponding values copied from
  		   the Change Task as long as the field name is valid and is not empty

  		   For any copied field remove it from our set of default values if it also
  		   exists in there */
  		var copyFieldsAndVals = {names: [], vals: []};
  		for (var i = 0; i < fieldsToCopy.length; i++) {
  			var fieldName = fieldsToCopy[i];
  			if (!changeTaskGr.isValidField(fieldName) || changeTaskGr[fieldName].nil())
  				continue;

  			var defaultFieldIndex = defaultFieldsAndVals.names.indexOf(fieldName);
  			if (defaultFieldIndex !== -1) {
  				defaultFieldsAndVals.names.splice(defaultFieldIndex, 1);
  				defaultFieldsAndVals.vals.splice(defaultFieldIndex, 1);
  			}

  			copyFieldsAndVals.names.push(fieldName);
  			copyFieldsAndVals.vals.push(changeTaskGr.getValue(fieldName));
  		}

  		/* We can now add the default values into the fields to be copied */
  		var allFieldsAndVals = {names: [], vals: []};
  		allFieldsAndVals.names = copyFieldsAndVals.names.concat(defaultFieldsAndVals.names);
  		allFieldsAndVals.vals = copyFieldsAndVals.vals.concat(defaultFieldsAndVals.vals);

  		// Finally we can create the Change Task Template as part of the standard change
  		count++;
  		var changeTaskTemplateGr = new GlideRecord(this.TABLE_NAME_RELATED_TASK);
  		changeTaskTemplateGr.std_change_proposal = proposalGr.getUniqueValue();
  		changeTaskTemplateGr.name = changeTaskGr.short_description.nil() ? "Change Task " + count : changeTaskGr.getValue("short_description");
  		changeTaskTemplateGr.short_description = changeTaskGr.getValue("short_description");
  		changeTaskTemplateGr.template = this._formQuery(allFieldsAndVals);
  		changeTaskTemplateGr.order = count * 100;
  		changeTaskTemplateGr.insert();
  	}
  	return copyErrors;
  },

  canModifyTemplate: function(stdChgTaskGr) {
  	if (!stdChgTaskGr)
  		return false;

  	// if the Standard Change template is being retired we can't modify the task templates
  	if (stdChgTaskGr.std_change_proposal.proposal_type + "" === "3")
  		return false;

  	return this.reviewedFieldsAcl(stdChgTaskGr.std_change_proposal.getRefRecord());
  },

  _attrToLabel: function (attr) {
  	if (!this._sampleChangeTaskGr) {
  		this._sampleChangeTaskGr = new GlideRecord(this.TABLE_NAME_CHANGE_TASK);
  		this._sampleChangeTaskGr.initialize();
  	}

  	var label = this._sampleChangeTaskGr[attr].getLabel();
  	return {name: attr, label: label};
  },

  // prepare a name , value array from encodedQuery.
  // It creates two arrays of name and value each.
  _parseEncodedQuery: function(query, noEscape) {
  	return this._parseEncodedQueryByTable(this.TABLE_NAME_CHANGE_TASK, query, noEscape);
  },

  hasPropertyFieldChanged: function(propertyGr) {
  		return propertyGr.mandatory_task_fields.changes() || propertyGr.restricted_task_fields.changes() || propertyGr.default_task_values.changes() || propertyGr.task_fields_to_copy.changes();
  },

  type: 'StdChangeTaskUtilsSNC'
});

Sys ID

20b5fab9eb3032002a7a666cd206fe52

Offical Documentation

Official Docs: