Name

global.sc_ic_Item

Description

This class should be subclasses and injected using sc_ic_Factory. Please refer to sc_ic_Factory for more information.

Script

var sc_ic_Item = Class.create();
sc_ic_Item.prototype = Object.extendsObject(sc_ic_Base, {
  initialize: function(_gr,_gs) {
  	sc_ic_Base.prototype.initialize.call(this,_gr,_gs);
  	
  	if (this._gr.getTableName()+"" != sc_ic.ITEM_STAGING)
  		throw new sc_ic_Exception("Incorrect GlideRecord type " + this._gr.getTableName() +" for " + this.type);
  	
  	// The set of fields that will make this record change to the draft state.
  	this._toDraft = {'name': true, 'short_description': true, 'description': true, 'sc_catalogs': true, 'sc_categories': true,
  					 'availability': true, 'cost': true, 'recurring_cost': true, 'recurring_frequency': true, 'desktop_image': true,
  					 'mobile_image': true, 'var_changed': true, 'item_type': true, 'var_defn_changed':true, 'var_meta_changed': true,
  					 'aprvl_defn_changed': true, 'task_defn_changed': true, 'layout_changed': true, 'entitlements': true};
  	
  	// The list of states that you're allowed to edit this item in.
  	this._editState = { 'draft': true, 'ready_to_publish': true, 'published':true, 'expired': true };
  },
  
  /**
   * Sets an Item to draft and increments version number if one of the trigger fields has been changed
   */
  setDraft: function() {
  	if (this._toDraftFieldsChanged() || this._serviceCreatorFieldsChanged()) {
  		this._gr.state = sc_ic.DRAFT;
  		this._gr.version = parseInt(this._gr.version+"") + 1;
  		this._gr[sc_ic.ACTIVE] = true;
  		
  		if (this._log.atLevel(GSLog.DEBUG))
  			this._log.debug("[setDraft] " + this._gr.name + " <" + this._gr.getUniqueValue() + ">");
  		
  		return this;
  	}
  	return this;
  },
  
  _toDraftFieldsChanged: function() {
  	for (var fld in this._toDraft) {
  		if (this._gr[fld].changes() && this._toDraft[fld]) 
  			return true;
  	}
  	return false;
  },
  
  _serviceCreatorFieldsChanged: function() {
  	if(this._gr.item_type+"" !== 'sc_cat_item_producer_service')
  		return false;
  	var serviceCreatorFields = {'workflow': true, 'submission_message': true, 'fulfillment_group': true, 'fulfillment_user': true};
  	for (var fld in serviceCreatorFields) {
  		if (this._gr[fld].changes() && serviceCreatorFields[fld])
  			return true;
  	}
  	return false;
  },
  
  setDraftForImage: function() {
  	var oldState = this._gr.state.toString();
  	this._gr.state = sc_ic.DRAFT;
  	this._gr.version = parseInt(this._gr.version+"") + 1;
  	this._gr[sc_ic.ACTIVE] = true;
  	this._gr.update();
  	this.displayDraftMessage(oldState);
  	return this;
  },
  
  /**
   * Sets the item as expired
   */
  setExpired: function() {
  	this._gr.state = sc_ic.EXPIRED;
  	this._gr.active = false;
  	return this;
  },
  
  /**
   * expires the item
   */
  expire: function() {
  	this.setExpired();
  	this._gr.update();
  	
  	if (!this._gr.isActionAborted() && !JSUtil.nil(this._gr[sc_.CATALOG_ITEM]))
  		sc_ic_Factory.wrap(this._gr[sc_.CATALOG_ITEM].getRefRecord()).expire();
  },
  
  /**
   * Makes the item draft
   */
  draft: function() {
  	var oldState = this._gr.state.toString();
  	
  	this.setDraft();
  	this._gr.update();
  	this.displayDraftMessage(oldState);
  	
  },
  
  isEditable: function() {
  	if (!this.accessibleInDomain())
  		return false;
  	return (this._editState[this._gr[sc_ic.STATE]+""] ? true : false);
  },
  
  /**
   * Sets the question definition changed flag if it's not already set.
   */
  questionDefinitionChanged: function() {
  	if (this._gr[sc_ic.VAR_DEFN_CHANGED]+"" == "true")
  		return;
  	if (this._log.atLevel(GSLog.DEBUG))
  		this._log.debug("[questionDefinitionChanged] Changed for " + this._gr.name + " <" + this._gr.getUniqueValue() + ">");
  	
  	this._gr[sc_ic.VAR_DEFN_CHANGED] = true;
  	this.draft();
  },
  
  /**
   * Sets the question meta changed flag if not already set
   */
  questionMetaChanged: function() {
  	if (this._gr[sc_ic.VAR_META_CHANGED]+"" == "true")
  		return;
  	
  	if (this._log.atLevel(GSLog.DEBUG))
  		this._log.debug("[questionMetaChanged] Changed for " + this._gr.name + " <" + this._gr.getUniqueValue() + ">");
  	
  	this._gr[sc_ic.VAR_META_CHANGED] = true;
  	this.draft();
  },
  
  /**
   * Sets the approval definition changed flag if not already set
   */
  approvalDefinitionChanged: function() {
  	if (this._gr[sc_ic.APRVL_DEFN_CHANGED]+"" == "true")
  		return;
  	
  	if (this._log.atLevel(GSLog.DEBUG))
  		this._log.debug("[approvalDefinitionChanged] Changed for " + this._gr.name + " <" + this._gr.getUniqueValue() + ">");
  	
  	this._gr[sc_ic.APRVL_DEFN_CHANGED] = true;
  	this.draft();
  },
  
  /**
   * Sets the task definition change flag if not already set
   */
  taskDefinitionChanged: function() {
  	if (this._gr[sc_ic.TASK_DEFN_CHANGED]+"" == "true")
  		return;
  	
  	if (this._log.atLevel(GSLog.DEBUG))
  		this._log.debug("[taskDefinitionChanged] Changed for " + this._gr.name + " <" + this._gr.getUniqueValue() + ">");
  	
  	this._gr[sc_ic.TASK_DEFN_CHANGED] = true;
  	this.draft();
  },
  
  /**
   * Sets the layout flag changed if not already set
   */
  layoutChanged: function() {
  	if (this._gr[sc_ic.LAYOUT_CHANGED]+"" == "true")
  		return;

  	if (this._log.atLevel(GSLog.DEBUG))
  		this._log.debug("[layoutChanged] Changed for " + this._gr.name + " <" + this._gr.getUniqueValue() + ">");
  	
  	this._gr[sc_ic.LAYOUT_CHANGED] = true;
  	this.draft();
  },
  
  okToPublish: function() {
  	var missingData = [];
  	if (JSUtil.nil(this._gr.sc_categories))
  		missingData.push("Categories: you need to add your Item to at least 1 Category");
  	
  	if (!this.createdFromServiceCreator()) {
  		var taskDefnGr = new GlideAggregate(sc_ic.TASK_DEFN_STAGING);
  		taskDefnGr.addQuery(sc_ic.ITEM_STAGING, this._gr.getUniqueValue());
  		taskDefnGr.addActiveQuery();
  		taskDefnGr.addAggregate("COUNT");
  		taskDefnGr.query();
  		
  		if (!taskDefnGr.next() || taskDefnGr.getAggregate("COUNT") == 0)
  			missingData.push("Tasks: your Item needs to have at least 1 Task");
  	}

  	if (missingData.length > 0) {
  		this._gr.setAbortAction(true);
  		var infoMessage = "Your Item isn't quite ready to be published - you need to resolve the following issues first:<ul>";
  		for (var i = 0; i < missingData.length; i++)
  			infoMessage += "<li>" + missingData[i] + "</li>";
  		infoMessage += "</ul>";
  		
  		gs.addInfoMessage(infoMessage);
  		this.redirect();

  		return false;
  	}

  	if (!this.accessibleInDomain()) {
  		gs.addErrorMessage(gs.getMessage("Item has already been published in another domain. Please change the domain and try again."));
  		return false;
  	}
  	return true;
  },
  
  /**
  * Publishes this simple item to a catalog item and returns the catalog item GlideRecord.
  * Checks the var_defn_changed and var_meta_changed values to check if the variables have been updated.
   * If the definition is changed it forces the expiration of the current and creation of a new item.  If
   * the meta has changed only the item and variables are updated.
   */
  publish: function() {
  	if (this._log.atLevel(GSLog.DEBUG))
  		this._log.debug("[publish] Publishing Item: " + this._gr.name + " <"+ this._gr.getUniqueValue() +"> to table " + this._gr.item_type);
  	
  	// Check the minimum data requirements are met before publishing
  	if (!this.okToPublish())
  		return;

  	//Which kind of target record are we dealing with
  	var targetTable = this._gr.item_type +"";
  	
  	var retVal;
  	
  	if (JSUtil.notNil(this._gr[sc_.CATALOG_ITEM])) {
  		var ci = new GlideRecord(targetTable);
  		ci.get(this._gr[sc_.CATALOG_ITEM]);
  		
  		var catItem = sc_ic_Factory.wrap(ci);
  		
  		//If the variables have been changed expire/create, otherwise update.
  		if (this._gr[sc_ic.VAR_DEFN_CHANGED]+"" == "true") {
  			catItem.expire();
  			retVal = sc_ic_Factory.getWrapperClass(targetTable).create(this._gr);
  		}
  		else {
  			catItem.refresh(this._gr);
  			if (this._gr[sc_ic.VAR_META_CHANGED]+"" == "true" || this._gr[sc_ic.LAYOUT_CHANGED]+"" == "true")
  				catItem.refreshQuestions(this._gr);
  			retVal = ci;
  		}
  	}
  	else {
  		// If there's not one published, create a Catalog Item.
  		retVal = sc_ic_Factory.getWrapperClass(targetTable).create(this._gr);
  	}
  	
  	var itemID = retVal.sys_id;
  	var itemStagingID = this._gr.sys_id;
  	
  	new SNC.NGSCCatalogRules(itemID + "", itemStagingID + "").publish();
  	
  	// Update the publishing information on this record.
  	this._gr[sc_.CATALOG_ITEM] = retVal.getUniqueValue();
  	this._gr[sc_ic.STATE] = sc_ic.PUBLISHED;
  	this._gr[sc_ic.VAR_DEFN_CHANGED] = false;
  	this._gr[sc_ic.VAR_META_CHANGED] = false;
  	this._gr[sc_ic.APRVL_DEFN_CHANGED] = false;
  	this._gr[sc_ic.TASK_DEFN_CHANGED] = false;
  	this._gr[sc_ic.LAYOUT_CHANGED] = false;
  	
  	this._enableQuietUpdate();
  	this._gr.update();
  	gs.updateSave(this._gr);
  	this._disableQuietUpdate();
  	
  	if (!this.createdFromServiceCreator()) {
  		var infoMsg = gs.getMessage("Your item has been published successfully - you can try your new item by clicking <a href='{0}'>here</a>", GlideappCatalogURLGenerator.getItemBaseURLFromGR(retVal));
  		if (this.isAdmin())
  			infoMsg = gs.getMessage("Your item has been published successfully - you can try your new item by clicking <a href='{0}'>here</a> and the new Catalog Item can be viewed by clicking <a href='{1}'>here</a>", [GlideappCatalogURLGenerator.getItemBaseURLFromGR(retVal), retVal.getLink()]);
  		if (new CatalogDomainUtil().isDomainIsolationEnabled()) {
  			var itemDomain = this._gr.sc_cat_item.sys_domain.name || 'global';
  			infoMsg = gs.getMessage("Your item has been published successfully in the domain {0} - you can try your new item by clicking <a href='{1}'>here</a>",[itemDomain, GlideappCatalogURLGenerator.getItemBaseURLFromGR(retVal)]);
  			if (this.isAdmin())
  				infoMsg = gs.getMessage("Your item has been published successfully in the domain {0} - you can try your new item by clicking <a href='{1}'>here</a> and the new Catalog Item can be viewed by clicking <a href='{2}'>here</a>",[itemDomain, GlideappCatalogURLGenerator.getItemBaseURLFromGR(retVal), retVal.getLink()]);
  		}
  		gs.addInfoMessage(infoMsg);
  	}
  	
  	return retVal;
  },
  
  unpublish: function () {
  	if (this._log.atLevel(GSLog.DEBUG))
  		this._log.debug("[publish] Unpublishing Item: " + this._gr.name + " <"+ this._gr.getUniqueValue() +"> to table " + this._gr.item_type);
  	
  	if (!this.accessibleInDomain()) {
  		gs.addErrorMessage(gs.getMessage("Cannot unpublish as the item has been published in another domain"));
  		return;
  	}
  	if (JSUtil.nil(this._gr[sc_.CATALOG_ITEM]))
  		return;
  	
  	this.draft();
  	if (!this._gr.isActionAborted())
  		sc_ic_Factory.wrap(this._gr[sc_.CATALOG_ITEM].getRefRecord()).expire();
  	
  	this._gs.addInfoMessage(this._gs.getMessage("Catalog Item  <span style='font-weight:bold'>{0}</span> is now inactive", this._gr[sc_.CATALOG_ITEM].getDisplayValue()));
  },
  
  /**
  * Validate categories exist in a catalog, and attempt give meaningful data if possible or show error.
  */
  validateCategories: function() {
  	var retVal = true;
  	if (JSUtil.nil(this._gr.sc_catalogs) && JSUtil.notNil(this._gr.sc_categories)) {
  		this._gr.sc_catalogs = GlideappCategory.getCatalogsByCategories(this._gr.sc_categories);
  		if (JSUtil.nil(this._gr.sc_catalogs)) {
  			this._gs.addErrorMessage(this._gs.getMessage('You cannot select categories that do not exist in selected catalog(s)'));
  			retVal = false;
  		}
  	}
  	else if (JSUtil.nil(this._gr.sc_catalogs) && JSUtil.nil(this._gr.sc_categories) && SNC.Catalog.getTotalCatalogCount() == 1)
  		this._gr.sc_catalogs = SNC.Catalog.getDefaultCatalog();
  	else if (JSUtil.notNil(this._gr.sc_catalogs) && JSUtil.notNil(this._gr.sc_categories)) {
  		if (!GlideappCategory.areCategoriesInCatalogs(this._gr.sc_catalogs, this._gr.sc_categories)) {
  			this._gs.addErrorMessage(this._gs.getMessage('You cannot select categories that do not exist in selected catalog(s)'));
  			retVal = false;
  		}
  	}
  	return retVal;
  },
  
  createDefaultSection: function() {
  	var sectionGr = new GlideRecord(sc_ic.SECTION);
  	sectionGr[sc_ic.ITEM_STAGING] = this._gr.getUniqueValue();
  	sectionGr[sc_ic.INDEX] = 0;
  	sectionGr.insert();
  },
  
  createdFromServiceCreator: function() {
  	return this._gr[sc_ic.ITEM_TYPE] == "sc_cat_item_producer" ||
  			this._gr[sc_ic.ITEM_TYPE] == "sc_cat_item_producer_service";
  },
  
  isAdmin: function() {
  	return gs.hasRole(sc_.CATALOG_ADMIN);
  },
  
  getUsersAvailableCatalogsRQ: function() {
  	if (this.isAdmin())
  		return "";

  	var availableCatalogIds = this.getUsersAvailableCatalogs().toString();
  	
  	return (availableCatalogIds == "" ? "sys_idIN0" : "sys_idIN" + availableCatalogIds);
  },
  
  getUsersAvailableCatalogs: function() {
  	var availableCatalogIds = [];
  
  	var availableCatalogsGr = new GlideAggregate(sc_ic.CATEGORY_REQUEST);
  	availableCatalogsGr.addEncodedQuery(sc_ic.MANAGER + "=" + gs.getUserID() + "^OR" + sc_ic.EDITORS + "LIKE" + gs.getUserID());
  	availableCatalogsGr.addNotNullQuery(sc_.CATEGORY);
  	availableCatalogsGr.groupBy(sc_.CATALOG);
  	availableCatalogsGr.query();
  
  	while (availableCatalogsGr.next())
  		availableCatalogIds.push(availableCatalogsGr[sc_.CATALOG]+"");
  
  	return availableCatalogIds;
  },

  getUsersAvailableCategoriesRQ: function() {
  	if (this.isAdmin()) {
  		return "sc_catalogIN" + this._gr[sc_ic.CATALOGS];
  	}
  			
  	var availableCategoryIds = this.getUsersAvailableCategories().toString();

  	return (availableCategoryIds == "" ? "sys_idIN0" : "sys_idIN" + availableCategoryIds);
  },
  
  getUsersAvailableCategories: function() {
  	var availableCategoryIds = [];
  	var selectedCatalogs = this._gr[sc_ic.CATALOGS] + "";
  
  	var availableCategoriesGr = new GlideRecord(sc_ic.CATEGORY_REQUEST);
  	availableCategoriesGr.addEncodedQuery(sc_ic.MANAGER + "=" + gs.getUserID() + "^OR" + sc_ic.EDITORS + "LIKE" + gs.getUserID());
  	availableCategoriesGr.addNotNullQuery(sc_.CATEGORY);
  	if (!JSUtil.nil(selectedCatalogs)) {
  		var selectedCatalogsArr = selectedCatalogs.split(",");
  		for (var i = 0; i < selectedCatalogsArr.length; i++) {
  			var catQuery;
  			if (i == 0) 
  				catQuery = availableCategoriesGr.addQuery("sc_catalog", selectedCatalogsArr[i]);
  			else
  				catQuery.addOrCondition("sc_catalog", selectedCatalogsArr[i]);
  		}
  	}
  	availableCategoriesGr.query();

  	while (availableCategoriesGr.next())
  		availableCategoryIds.push(availableCategoriesGr[sc_.CATEGORY]+"");
  	
  	return availableCategoryIds;
  },
  
  getUsersDefaultCatalog: function() {
  	var availableCatalogIds = this.getUsersAvailableCatalogsRQ();
  	
  	var catalogGr = new GlideRecord(sc_.CATALOG);
  	catalogGr.addEncodedQuery(availableCatalogIds);
  	catalogGr.query();
  	if (catalogGr.getRowCount() == 1) {
  		catalogGr.next();
  		return catalogGr.getDisplayValue();
  	}
  	
  	return "";
  },
  
  getUsersDefaultCategory: function() {
  	var availableCategoryIds = this.getUsersAvailableCategoriesRQ();
  	
  	var categoryGr = new GlideRecord(sc_.CATEGORY);
  	categoryGr.addEncodedQuery(availableCategoryIds);
  	categoryGr.query();
  	if (categoryGr.getRowCount() == 1) {
  		categoryGr.next();
  		return categoryGr.getDisplayValue();
  	}
  	
  	return "";
  },
  	
  /**
   * Warn user if the previous state was Published
   */

  displayDraftMessage: function(oldState){
  	var wasPublished = false;
  	if (oldState == sc_ic.PUBLISHED)
  		wasPublished = true;
  	if (wasPublished)
  		this._gs.addInfoMessage(this._gs.getMessage("Your item has been set back to Draft from Published state"));
  },
  
  accessibleInDomain: function() {
  	if (!this.createdFromServiceCreator() && new CatalogDomainUtil().isDomainIsolationEnabled() && this._gr.sc_cat_item) {
  		var currentDomain = gs.getUser().getDomainID();
  		if (JSUtil.nil(currentDomain))
  			currentDomain = 'global';
  		var itemDomain = this._gr.sc_cat_item.sys_domain;
  		if (currentDomain != itemDomain)
  			return false;
  	}
  	return true;
  },

  type: 'sc_ic_Item'
});

Sys ID

684ea920c32111003d2ae219cdba8f38

Offical Documentation

Official Docs: