Name

sn_chg_soc.SoCDefinitionSNC

Description

SNC Class encapsulating SoC Definition code

Script

var SoCDefinitionSNC = Class.create();
SoCDefinitionSNC.prototype = Object.extendsObject(SoC, {

  initialize: function(_gr, _gs) {
  	SoC.prototype.initialize.call(this, _gr, _gs);
  	this._socUtil = new global.ChangeSoCUtil();
  },

  addInvitees: function(recipients, inviteMessage, sendEmail) {
  	var updateSysId = this._updatePermission(recipients);
  	if (sendEmail)
  		this.sendEmail(inviteMessage, recipients);

  	var result = {
  		chg_soc_definition: this._gr.getUniqueValue(),
  		recipients: recipients,
  		updated: false
  	};
  	if (updateSysId)
  		result.updated = true;
  	return result;
  },

  canDelete: function() {
  	return this.canWrite();
  },

  canRead: function() {
  	var currentUser = this._gs.getUser();
  	return this.canWrite() || this.isSharedWith(currentUser);
  },

  canWrite: function() {
  	return this._gr.isNewRecord() || this.isOwner(this._gs.getUser());
  },

  // If the given user is the owner
  isOwner: function(user) {
  	if (!(this._gr && this._gr.isValidRecord()))
  		return false;

  	// Are they the owner?
  	if (this._gr.owner + "" === user.getID() + "")
  		return true;

  	//Are they in the owning group
  	if (user.isMemberOf(this._gr.group_owner + ""))
  		return true;

  	return false;
  },

  _isSharedWithUsers: function(user) {
  	if (!this._gr.share_users.nil()) {
  		var users = this._gr.share_users.split(",");
  		for (var ui = 0; ui < users.length; ui++)
  			if (user.getID() + "" === users[ui])
  				return true;
  	}
  },

  _isSharedWithGroups: function(user) {
  	if (!this._gr.share_groups.nil()) {
  		var groups = this._gr.share_groups.split(",");
  		for (var gi = 0; gi < groups.length; gi++)
  			if (user.isMemberOf(groups[gi]))
  				return true;
  	}
  },

  _isSharedWithRoles: function(user) {
  	if (!this._gr.share_roles.nil() && user.hasRole(this._gr.getDisplayValue("share_roles")))
  			return true;
  	return false;
  },

  // If the definition is shared with the given user
  isSharedWith: function(user) {
  	if (!(this._gr && this._gr.isValidRecord()))
  		return false;

  	// NOT shared
  	if (this._gr.share_with.nil())
  		return false;

  	// Shared with Everyone
  	if (this._gr.share_with + "" === "1")
  		return true;

  	// Shared with Users, Groups, Roles
  	if (this._gr.share_with + "" === "2")
  		if (this._isSharedWithUsers(user) || this._isSharedWithGroups(user) || this._isSharedWithRoles(user))
  			return true;
  	return false;
  },

  _sort: function(field, reverse, primer) {
  	var key = primer ? function(x) { return primer(x[field]); } : function(x) { return x[field]; };
  	reverse = !reverse ? 1 : -1;
  	return function(a, b) {
  		a = key(a);
  		b = key(b);
  		return reverse * ((a > b) - (b > a));
  	};
  },

  getSuggestions: function(query) {
  	if (!query)
  		return [];

  	if (this._log.atLevel(global.GSLog.DEBUG))
  		this._log.debug("[getSuggestions] query: " + query);

  	var limit = parseInt(this._gs.getProperty(SoC.PROP_SUGGESTION_LIMIT, SoC.SUGGESTION_LIMIT));
  	var users = this._searchTable(SoC.SYS_USER, query, limit, this._gr.share_users + "");
  	var groups = this._searchTable(SoC.GROUP, query, limit, this._gr.share_groups + "");
  	var roles = this._searchTable(SoC.ROLE, query, limit, this._gr.share_roles + "");
  	var suggestions = [];
  	suggestions = suggestions.concat(users).concat(groups).concat(roles).sort(this._sort);

  	if (this._log.atLevel(global.GSLog.DEBUG))
  		this._log.debug("[getSuggestions] suggestions: " + JSON.stringify(suggestions));

  	return suggestions;
  },

  updateSchedule: function(changeSchedDef) {
  	this._gr.name = changeSchedDef.name;
  	this._gr.start_date_field = changeSchedDef.start_date_field;
  	this._gr.end_date_field = changeSchedDef.end_date_field;
  	this._gr.condition = changeSchedDef.condition;
  	var updateSysId = this._gr.update();

  	var result = {
  		chg_soc_definition: this._gr.getUniqueValue(),
  		name: { value: this._gr.name + "", display_value: this._gr.name.getDisplayValue() },
  		start_date_field: { value: this._gr.start_date_field + "", display_value: this._gr.start_date_field.getDisplayValue() },
  		end_date_field: { value: this._gr.end_date_field + "", display_value: this._gr.end_date_field.getDisplayValue() },
  		condition: {value: this._gr.condition + "", display_value: this._gr.condition.getDisplayValue()},
  		updated: false
  	};

  	if (updateSysId)
  		result.updated = true;
  	return result;
  },

  updatePermission: function(everyone) {
  	this._gr.share_with = everyone;
  	var updateSysId = this._gr.update();

  	var result = {
  		chg_soc_definition: this._gr.getUniqueValue(),
  		shareWith: everyone,
  		updated: false
  	};

  	if (updateSysId)
  		result.updated = true;
  	return result;
  },

  removePermission: function(tableName, sysId) {
  	if (this._log.atLevel(global.GSLog.DEBUG))
  		this._log.debug("[removePermission] tableName: " + tableName + " sysId: " + sysId);

  	switch (tableName) {
  		case SoC.ROLE:
  			this._gr.setValue("share_roles", this._removeElement((this._gr.share_roles + "").split(","), sysId));
  			break;
  		case SoC.GROUP:
  			this._gr.share_groups = this._removeElement((this._gr.share_groups + "").split(","), sysId);
  			break;
  		case SoC.SYS_USER:
  			this._gr.share_users = this._removeElement((this._gr.share_users + "").split(","), sysId);
  			break;
  		default:
  			this._log.debug("[removePermission] tableName not supported");
  	}

  	if (this._gr.share_with + "" === "2" && this._gr.share_roles.nil() && this._gr.share_groups.nil() && this._gr.share_users.nil())
  		this._gr.share_with = "";

  	var updateSysId = this._gr.update() + "";
  	var result = {
  		chg_soc_definition: this._gr.getUniqueValue(),
  		tableName: tableName,
  		sys_id: sysId,
  		removed: false
  	};
  	if (updateSysId)
  		result.removed = true;
  	return result;
  },

  deleteRecord: function() {
  	var result = {
  		chg_soc_definition: this._gr.getUniqueValue(),
  		removed: this._gr.deleteRecord()
  	};
  	return result;
  },

  _isValidData: function(name, userSysId) {
  	if (!name || !userSysId)
  		return false;
  	return true;
  },

  copy: function(name, userSysId) {
  	name = (name + "").trim();
  	var result = {
  		chg_soc_definition: this._gr.getUniqueValue(),
  		copied: false
  	};

  	if (!this._isValidData(name, userSysId)) {
  		this._log.error("[copy] name: " + name + " and userSysId: " + userSysId + " are both mandatory parameters");
  		result.error = this._gs.getMessage("Please provide a name for change schedule");
  		return result;
  	}

  	var origSysId = this._gr.getUniqueValue();
  	var definitionGr = SoCDefinition.findById(origSysId);
  	if (!definitionGr) {
  		this._log.error("[copy] Failed to find Change Schedule definition record by id: " + origSysId);
  		result.error = this._gs.getMessage("Failed to copy change schedule");
  		return result;
  	}

  	var elements = this._gr.getElements();
  	var numElements = elements.length;
  	for (var i = 0; i < numElements; i++) {
  		var element = elements[i];
  		var elementName = element.getName().toString();
  		var elementValue = this._gr.getValue(elementName);

  		if (this._log.atLevel(global.GSLog.DEBUG))
  			this._log.debug("[copy] elementName: " + elementName + " elementValue: " + elementValue);

  		definitionGr.setValue(elementName, elementValue);
  	}
  	definitionGr.sys_scope = this._gs.getCurrentApplicationId();
  	definitionGr.name = name;
  	definitionGr.owner = userSysId;

  	// Do not copy the sharing data
  	definitionGr.share_with = "";
  	definitionGr.share_users = "";
  	definitionGr.share_groups = "";
  	definitionGr.share_roles = "";
  	definitionGr.group_owner = "";

  	var copySysId = definitionGr.insert() + "";
  	if (copySysId && copySysId !== origSysId) {
  		result.chg_soc_definition = copySysId;
  		result.chg_soc_definition_child = this._copy(origSysId, copySysId, SoC.DEFINITION_CHILD);
  		result.chg_soc_definition_style_rule = this._copy(origSysId, copySysId, SoC.DEFINITION_STYLE_RULE);
  		result.copied = true;
  	} else {
  		this._log.error("[copy] Failed to copy Change Schedule definition: " + origSysId);
  		result.error = this._gs.getMessage("Failed to copy change schedule");
  	}
  	return result;
  },

  _copy: function (origSysId, copySysId, tableName) {
  	var newRecSysIds = [];
  	if (!origSysId || !copySysId || !tableName)
  		return newRecSysIds;
  	var gr = new GlideRecord(tableName);
  	gr.addQuery(SoC.DEFINITION, origSysId);
  	gr.query();
  	while (gr.next()) {
  		var newRecGr = new GlideRecord(tableName);
  		newRecGr.initialize();
  		var elements = gr.getElements();
  		var numElements = elements.length;
  		for (var i = 0; i < numElements; i++) {
  			var element = elements[i];
  			var elementName = element.getName().toString();
  			var elementValue = gr.getValue(elementName);

  			if (this._log.atLevel(global.GSLog.DEBUG))
  				this._log.debug("[_copy] elementName: " + elementName + " elementValue: " + elementValue);

  			newRecGr.setValue(elementName, elementValue);
  		}
  		newRecGr.sys_scope = this._gs.getCurrentApplicationId();
  		newRecGr.chg_soc_definition = copySysId;
  		newRecSysIds.push(newRecGr.insert() + "");
  	}

  	if (this._log.atLevel(global.GSLog.DEBUG))
  		this._log.debug("[_copy] origSysId: " + origSysId + " copySysId: " + copySysId + " tableName: " + tableName + " newRecSysIds: " + newRecSysIds);

  	return newRecSysIds;
  },

  _extractUserSysIds: function(recipients) {
  	var userSysIds = [];
  	recipients.forEach(function(recipient) {

  		if (this._log.atLevel(global.GSLog.DEBUG))
  			this._log.debug("[_extractUserSysIds] tableName: " + recipient.tableName + " sysId: " + recipient.sys_id);

  		switch (recipient.tableName) {
  			case SoC.ROLE:
  				var userSysIdsByRole = this._getUserByRole(recipient.sys_id);
  				if (userSysIdsByRole.length > 0)
  					userSysIds = userSysIds.slice().concat(userSysIdsByRole);
  				break;
  			case SoC.GROUP:
  				var userSysIdsByGroup = this._getGroupEmails(recipient.sys_id);
  				if (userSysIdsByGroup.length > 0)
  					userSysIds = userSysIds.slice().concat(userSysIdsByGroup);
  				break;
  			case SoC.SYS_USER:
  				if (recipient.sys_id)
  					userSysIds.push(recipient.sys_id);
  				break;
  			default:
  				this._log.debug("[_extractUserSysIds] Unsupported tableName");
  		}
  	}, this);
  	return this._uniq(userSysIds);
  },

  _getUserByRole: function(roleSysId) {
  	if (!roleSysId)
  		return [];
  	return this._getUserSysIds("sys_user_has_role", "role", roleSysId);
  },

  _getGroupEmails: function(groupSysId) {
  	if (!groupSysId)
  		return [];
  	return this._getUserSysIds("sys_user_grmember", "group", groupSysId);
  },

  _getUserSysIds: function(tableName, field, sysId) {
  	var userSysIds = [];
  	if (!tableName || !field || !sysId)
  		return userSysIds;
  	var gr = new GlideRecord(tableName);
  	gr.addQuery(field, sysId);
  	gr.query();
  	while (gr.next()) {
  		var userSysId = gr.user + "";
  		if (userSysId)
  			userSysIds.push(userSysId);
  	}
  	return userSysIds;
  },

  getPermissions: function() {
  	var sharing = {
  		shareWith: "",
  		shareGroups: "",
  		shareUsers: "",
  		shareRoles: ""
  	};

  	if (this._log.atLevel(global.GSLog.DEBUG))
  		this._log.debug("[getPermissions] this._gr.sys_id: " + this._gr.sys_id);

  	if (!this._gr || (this._gr.sys_id + "" === ""))
  		return sharing;

  	sharing.shareWith = this._gr.share_with + "";
  	sharing.shareGroups = this._getShareGroups();
  	sharing.shareUsers = this._getShareUsers();
  	sharing.shareRoles = this._getShareRoles();

  	return sharing;
  },

  _getShareUsers: function() {
  	var sharedUsers = this._gr.share_users + "";
  	if (!sharedUsers)
  		return [];
  	return this._socUtil.getProfiles(SoC.SYS_USER, sharedUsers.split(","));
  },

  _getShareRoles: function() {
  	var sharedRoles = this._gr.share_roles + "";
  	if (!sharedRoles)
  		return [];
  	return this._socUtil.getProfiles(SoC.ROLE, sharedRoles.split(","));
  },

  _getShareGroups: function() {
  	var sharedGroups = this._gr.share_groups + "";
  	if (!sharedGroups)
  		return [];
  	return this._socUtil.getProfiles(SoC.GROUP, sharedGroups.split(","));
  },

  getStyleRules: function() {
  	return new SoCDefinitionStyleRule(SoCDefinitionStyleRule.findByDefId(this._gr.getUniqueValue()), this._gs);
  },

  // Returns a gliderecord containing the changes for this definition
  getRecords: function(start, condition) {
  	var changeGr = new GlideRecordSecure(SoC.CHANGE_REQUEST);
  	changeGr.addNotNullQuery(this._gr.start_date_field + "");
  	changeGr.addNotNullQuery(this._gr.end_date_field + "");
  	if (!condition)
  		condition = this._gr.condition + "";
  	changeGr.addEncodedQuery(condition);
  	if (condition.indexOf(SoC.ORDERBY) === -1)
  		changeGr.orderBy(this._gr.start_date_field + "");
  	changeGr.query();

  	var pointer = 0;
  	while (pointer < start && changeGr.next())
  		pointer++;
  	return changeGr;
  },

  _removeElement: function(arr, elem) {
  	if (this._log.atLevel(global.GSLog.DEBUG))
  		this._log.debug("[_removeElement] arr: " + arr.join(",") + " elem: " + elem);

  	// remove all instances of elem
  	var index = arr.indexOf(elem);
  	while (index !== -1) {
  		arr.splice(index, 1);
  		index = arr.indexOf(elem);
  	}
  	var arrStr = arr.join(",");

  	if (this._log.atLevel(global.GSLog.DEBUG))
  		this._log.debug("[_removeElement] arrStr: " + arrStr);

  	return arrStr;
  },

  _searchTable: function(tableName, searchTerm, limit, ignoreList) {
  	var searchResults = [];

  	if (!tableName || !searchTerm)
  		return searchResults;

  	limit = limit || SoC.SUGGESTION_LIMIT;

  	if (this._log.atLevel(global.GSLog.DEBUG))
  		this._log.debug("[_searchTable] tableName: " + tableName + " searchTerm: " + searchTerm + " limit: " + limit + " ignoreList: " + ignoreList);

  	var gr = new GlideRecordSecure(tableName);
  	gr.setLimit(limit);
  	gr.addActiveQuery();
  	if (ignoreList)
  		(tableName === SoC.ROLE) ? gr.addQuery("name", "NOT IN", ignoreList) : gr.addQuery("sys_id", "NOT IN", ignoreList);
  	gr.addQuery("name", "CONTAINS", searchTerm);
  	gr.query();
  	while (gr.next())
  		searchResults.push(this._socUtil.getProfile(gr));
  	return searchResults;
  },

  _chunkArray: function(arrayToBeChunked, chunkSize) {
  	var arrayChunks = [];
  	if (!arrayToBeChunked || arrayToBeChunked.length === 0)
  		return arrayChunks;
  	if (!chunkSize)
  		chunkSize = 100;
  	for (var i = 0; i < arrayToBeChunked.length; i += chunkSize)
  		arrayChunks.push(arrayToBeChunked.slice(i, i + chunkSize));
  	return arrayChunks;
  },

  sendEmail: function(message, recipients) {
  	var userSysIds = this._extractUserSysIds(recipients);

  	if (this._log.atLevel(global.GSLog.DEBUG))
  		this._log.debug("[sendEmail] userSysIds: " + userSysIds.join(","));

  	if (!userSysIds)
  		return;

  	// We can't use servlet.uri; during AHA transfers node restarts, its value can change. We use the override.url unless it's empty, then we revert to the servlet.uri.
  	var instanceURL = this._gs.getProperty("glide.servlet.uri");
  	var overrideURL = this._gs.getProperty("glide.email.override.url");
  	var link = (overrideURL ? overrideURL : instanceURL + "nav_to.do") + "?uri=sn_chg_soc_change_soc.do%3Fsysparm_id%3D" + this._gr.sys_id;

  	var anchor = "<a href='" + link + "'>" + this._gs.getMessage("View Change Schedule") + "</a>";
  	var newLine = "<br>";
  	message = message + newLine + anchor;
  	var eventName = "sn_chg_soc.share.invitation";
  	var emailMessage = {
  		chgSocName: this._gr.name.getDisplayValue(),
  		message: message
  	};

  	var recipientChunks = this._chunkArray(userSysIds, 100);
  	for (var i = 0; i < recipientChunks.length; i++) {
  		var userSysIdStr = recipientChunks[i].join(",");
  		var emailMessageStr = JSON.stringify(emailMessage);
  		this._gs.eventQueue(eventName, null, userSysIdStr, emailMessageStr);

  		if (this._log.atLevel(global.GSLog.DEBUG))
  			this._log.debug("[sendEmail] chunk: " + i + " userSysIdStr: " + userSysIdStr + " emailMessageStr: " + emailMessageStr);
  	}
  },

  _uniq: function(arr) {
  		var hash = {};
  		return arr.filter(function(elem) {
  				return hash.hasOwnProperty(elem) ? false : (hash[elem] = true);
  		});
  },

  _updatePermission: function(recipients) {
  	var roleSysIds = [];
  	var groupSysIds = [];
  	var userSysIds = [];

  	recipients.forEach(function(recipient) {
  		switch (recipient.tableName) {
  			case SoC.ROLE:
  				roleSysIds.push(recipient.sys_id);
  				break;
  			case SoC.GROUP:
  				groupSysIds.push(recipient.sys_id);
  				break;
  			case SoC.SYS_USER:
  				userSysIds.push(recipient.sys_id);
  				break;
  			default:
  				this._log.debug("[_updatePermission] Unsupported tableName");
  		}
  	});

  	roleSysIds = this._uniq(roleSysIds.concat((this._gr.share_roles + "").split(",")));
  	groupSysIds = this._uniq(groupSysIds.concat((this._gr.share_groups + "").split(",")));
  	userSysIds = this._uniq(userSysIds.concat((this._gr.share_users + "").split(",")));

  	if (roleSysIds.length > 0 || groupSysIds.length > 0 || userSysIds.length > 0) {
  		if (this._gr.share_with.nil())
  			this._gr.share_with = 2;
  		this._gr.setValue("share_roles", roleSysIds.join(","));
  		this._gr.share_groups = groupSysIds.join(",");
  		this._gr.share_users = userSysIds.join(",");
  	}
  	else if (this._gr.share_with + "" === "2")
  		this._gr.share_with = "";
  	return this._gr.update() + "";
  },

  type: "SoCDefinitionSNC"
});

SoCDefinitionSNC.findById = function(socDefId) {
  if (!socDefId)
  	return null;
  var definitionGr = new GlideRecordSecure(SoC.DEFINITION);
  if (!definitionGr.get(socDefId))
  	return null;

  return definitionGr;
};

// Finds all the definitions the current user has access to
SoCDefinitionSNC.findAll = function(orderBy, textSearch) {
  if (!orderBy)
  	orderBy = SoC.NAME;

  var socDefGr = new GlideRecordSecure(SoC.DEFINITION);
  socDefGr.addActiveQuery();
  if (textSearch !== undefined && textSearch !== "undefined" && textSearch.trim() !== "")
  	socDefGr.addQuery(SoC.NAME, "CONTAINS", textSearch).addOrCondition(SoC.OWNER + "." + SoC.NAME, "CONTAINS", textSearch);
  socDefGr.orderBy(orderBy);
  socDefGr.query();
  return socDefGr;
};

SoCDefinitionSNC.findPinned = function(orderBy, textSearch) {
  var socDefGr = new GlideRecordSecure(SoC.DEFINITION);
  if (!orderBy)
  	orderBy = SoC.NAME;
  var pinnedDefPref = gs.getUser().getPreference("com.snc.soc.landing_page.pinned_schedules");
  var pinnedDefIds = pinnedDefPref ? pinnedDefPref.split(",") : [];

  socDefGr.addActiveQuery();
  if (textSearch !== undefined && textSearch !== "undefined" && textSearch.trim() !== "")
  	socDefGr.addQuery(SoC.NAME, "CONTAINS", textSearch).addOrCondition(SoC.OWNER + "." + SoC.NAME, "CONTAINS", textSearch);
  socDefGr.addQuery("sys_id", "IN", pinnedDefIds);
  socDefGr.orderBy(orderBy);
  socDefGr.query();
  return socDefGr;
};

SoCDefinitionSNC.findOwned = function(orderBy, textSearch) {
  if (!orderBy)
  	orderBy = SoC.NAME;

  var grpMemGr = new GlideRecord("sys_user_grmember");
  grpMemGr.addQuery(SoC.USER, gs.getUser().getID());
  grpMemGr.query();

  var groups = [];
  while (grpMemGr.next())
  	groups.push(grpMemGr.group + "");

  var socDefGr = new GlideRecordSecure(SoC.DEFINITION);
  socDefGr.addActiveQuery();
  if (textSearch !== undefined && textSearch !== "undefined" && textSearch.trim() !== "")
  	socDefGr.addQuery(SoC.NAME, "CONTAINS", textSearch).addOrCondition(SoC.OWNER + "." + SoC.NAME, "CONTAINS", textSearch);
  socDefGr.addQuery(SoC.OWNER, gs.getUser().getID()).addOrCondition(SoC.GROUP_OWNER, "IN", groups);
  socDefGr.orderBy(orderBy);
  socDefGr.query();
  return socDefGr;
};

SoCDefinitionSNC.getRequiredFields = function(socDefGr) {
  if (!socDefGr)
  	return null;

  var requiredFields = {};

  for (var field in SoC.JS_INCLUDE)
  	if (SoC.JS_INCLUDE.hasOwnProperty(field))
  		requiredFields[field] = true;

  requiredFields[socDefGr.start_date_field + ""] = true;
  requiredFields[socDefGr.end_date_field + ""] = true;
  if ("chg_soc_definition_child" === socDefGr.sys_class_name + "")
  	requiredFields[socDefGr.reference_field + ""] = true;

  var popoverFields = (socDefGr.popover_left_col_fields + "");
  popoverFields += "," + (socDefGr.popover_right_col_fields + "");
  popoverFields = popoverFields.split(",");
  for (var i = 0; i < popoverFields.length; i++)
  	if (popoverFields[i])
  		requiredFields[popoverFields[i]] = true;

  return requiredFields;
};

Sys ID

27b33f2957230300b41069202d94f9d6

Offical Documentation

Official Docs: