Name

global.CSQueryBRUtil

Description

Query business rule helper functions for Customer Service Management

Script

var CSQueryBRUtil = Class.create();
CSQueryBRUtil.prototype = Object.extendsObject(AbstractAjaxProcessor, {

  TABLE_CONTACT              : 'customer_contact',
  TABLE_ACCOUNT              : 'customer_account',
  TABLE_CONTACT_RELATIONSHIP : 'sn_customerservice_contact_relationship',
  TABLE_ACCOUNT_RELATIONSHIP : 'account_relationship',
  TABLE_SERVICE_ENTITLEMENT  : 'service_entitlement',
  TABLE_AST_CONTRACT         : 'ast_contract',
  TABLE_ALM_ASSET            : 'alm_asset',
  TABLE_CS_CASE              : 'sn_customerservice_case',
  TABLE_CSM_CONSUMER         : 'csm_consumer',
  TABLE_PRODUCT              : 'cmdb_model',
  TABLE_PRODUCT_CATEGORY     : 'cmdb_model_category',
  TABLE_ORDER                : 'csm_order',
  TABLE_ORDER_CASE           : 'csm_order_case', 
  TABLE_WORKORDER            : 'wm_order',
  MY_ACCOUNT                 : 'my_account',
  SUB_ACCOUNTS               : 'sub_accounts',
  TABLE_ACCOUNT_CONSUMER     : 'sn_acct_consumer_account_consumer',
  ACCTS_FROM_CONTACT_RELATIONSHIP      : 'accounts_from_contact_relationship',
  ACCTS_FROM_ACCTS_RELATIONSHIP        : 'accounts_from_account_relationship',
  ACCTS_FROM_ACCOUNT_CONSUMER          : 'accounts_from_account_counsumer',
  DEFAULT_DRIVER_FIELD                 : 'account',
  OOB_EXTENSION_POINT                  : 'CSQueryExtensionPoint',
  ACCESS_CONTEXT_EXTENSION_POINT       : 'CSMAccessContext',
  
  /*
  * Use Extension point feature to allow users to add their own Role constants.
  */
  getRoleContentPool: function(param){		
  	var result = {}; 
  	var ep = new GlideScriptedExtensionPoint().getExtensions(this.OOB_EXTENSION_POINT);
  	
  	//If there is any other new extension instance other than the OOB one, concat them together
  	//The extension instance with higher order number would overwrite the one with lower order number
  	for(var i = 0; i < ep.length; i ++){
  		var point = ep[i];				

  		if(param == 'permission')
              result = this.extendObj(result, point.getRolePermissionPool());	
  		else if(param == 'condition')
  			result = this.extendObj(result, point.getRoleConditionPool());
  	}
  	
  	return result;
  },
  
  /*
  * Concat the  JSON Object src to obj 
  */
  extendObj: function(obj, src) {
      Object.keys(src).forEach(function(key) { 
  		obj[key] = src[key]; 
  	});

      return obj;
  },
  
  /*
  * Cache the CSM roles user has
  */	
  getMyCSMRoles: function(){   
  	var key = 'my_csm_roles_' + gs.getUserID();
  	var results = gs.getSession().getClientData(key);

  	if (gs.nil(results) || results == 'NIL') {		
  		results = [];
  		var roles = gs.getUser().getRoles();

  		var CSMRoles = Object.keys(this.getRoleContentPool('permission'));
  		for(var i = 0; i < CSMRoles.length; i ++){
  			var role = CSMRoles[i];	
  			if(roles.indexOf(role) > -1)
  				results.push(role);
  		}

  		results  = (results.length > 0) ? results.join(',') : 'NIL';	
  		gs.getSession().putClientData(key, results);
  	}

  	results = (gs.nil(results) || results == 'NIL') ? null : results.split(',');				  
  	return results;  		   
  },
  
  
  /*
  * Cache the role details of login user has, field can be 'condition', 'access_context', or 'query';
  */	
  getRoleAccessDetails : function(field, table){		       
  	var results = [];
  	var myRoles = this.getMyCSMRoles();
  	
  	if(!gs.nil(myRoles) && myRoles.length > 0){					   			   
  		var fieldVals = [];
  		for(var i = 0; i < myRoles.length; i ++){
  			var pool = this.getRoleContentPool('permission');
  			var curRole = pool[myRoles[i]];
  			var obj = curRole[table];

  			if(obj.hasOwnProperty(field))
  				fieldVals = fieldVals.concat(obj[field]);
  		} 	
  		
  		var resultsCheck = {};
          fieldVals.forEach(function(item) {
              if (!gs.nil(item)) {
                  var itemKey = item.toString();
                  if (!(itemKey in resultsCheck)) {
                      resultsCheck[itemKey] = true;
                      results.push(item);
                  }
              }
          });

  	}

  	return results;	
  },
  
  /*
  * Cache the accessible accounts that login user has .
  */
  getMyAccessibleAccounts: function(tableName, skipMyAccount) {
  	/*
  	* As part of the refactoring done on this function. This function is changed to accept two Parameter instead of single Parameter.
  	* Handling Defaulting of these parameters as Follows
  	* If single Parameter passed and is a Boolean type assuming that the assigning the parameter passed to SkipMyAccount and setting the table to Account Table
  	* If single Parameter passed and is a String type then setting the table to the parameter passed and defaulting SkipMyAccount to false
  	* If two parameter passed and both are boolean, considering the second parameter to the SkipMyAccount and then setting the table to Account table as String is expected as 1st parameter.
          */
  	
  	var table = tableName;
  	if(gs.nil(tableName) || typeof tableName === "boolean"){
  		table = this.TABLE_ACCOUNT;
  	}
  	if(!gs.nil(tableName) && typeof tableName === "boolean" && gs.nil(skipMyAccount)){ 
  		skipMyAccount = tableName;
  	}
  	skipMyAccount = skipMyAccount || false;
  	var key = 'my_accessible_accounts_' + table + '_' + skipMyAccount + '_' + gs.getUserID();
  	var accounts = gs.getSession().getClientData(key);
  	var useSessionCache = true;

  	// Not in session cache and 'use_accounts_private_cache' property is enabled
  	var cacheUtil = new global.AccountsCacheUtil();
  	if (gs.nil(accounts) && cacheUtil.isPrivateCachingEnabledForAccounts()) {
  		var cacheName = 'MY_ACCESSIBLE_ACCOUNTS';
  		key = 'my_accessible_accounts_' + gs.getUser().getCompanyID();
  		cacheUtil.initPrivateCache(cacheName);
  		if (cacheUtil.isInPrivateCache(cacheName, key) || cacheUtil.useAccountsPrivateCache(table)) {
  			useSessionCache = false;
  			accounts = GlideCacheManager.get(cacheName, key);
  		}
  	}

  	if (gs.nil(accounts) || gs.hasRole('sn_acct_consumer.consumer')) {	
  		accounts = [];
  		var context_types = this.getRoleAccessDetails('access_context', table);	
  		var accts = [];
  		if(!gs.nil(context_types)){	
  			for(var i = 0; i < context_types.length; i ++){				
  				var context = context_types[i];
  				// The following methods handle the access context defined for each role in CSQueryBRUtilConstants.
  				if(!skipMyAccount && context == this.MY_ACCOUNT)
  					accts = accts.concat(gs.getUser().getCompanyID());

  				else if(context == this.SUB_ACCOUNTS)
  					accts = accts.concat(this.getSubAccounts());

  				else if(context == this.ACCTS_FROM_CONTACT_RELATIONSHIP)
  					accts = accts.concat(this.getAccountsFromContactRelationship());

  				else if(context == CSQueryBRUtilOOBConstants.ACCTS_WITHOUT_CONTACT_RESTRICT_ACCESS)
  					accts = accts.concat(new global.Account().getMyAccountsWithoutManagedAccess());

  				else if(context == this.ACCTS_FROM_ACCTS_RELATIONSHIP)
  					accts = accts.concat(this.getAccountsFromAccountRelationship());
  				else if(context == this.ACCTS_FROM_ACCOUNT_CONSUMER)
  					accts = accts.concat(this.getAccountsFromAccountConsumer());

  				else if(context == 'not_applicable')
  					accts = accts.concat('-1');

  				else if(context == 'all_accounts')
  					accts = accts.concat('all');	

  				else if(context == 'all_account_access')
  					accts = accts.concat('all_account_access');
  				else
  					accts = accts.concat(this.getAdditionalAccessibleAccounts(context)); 
  			}
  		} 
  		
          var accountsCheck = {};
          accts.forEach(function(item) {
              if (!gs.nil(item)) {
                  var itemKey = item.toString();
                  if (!(itemKey in accountsCheck)) {
                      accountsCheck[itemKey] = true;
                      accounts.push(item);
                  }
              }
          });
  		
  		accounts  = (accounts.length > 0) ? accounts.join(',') : 'NIL';
  		if (!useSessionCache)
                              GlideCacheManager.put("MY_ACCESSIBLE_ACCOUNTS", key, accounts);
                      else
                              gs.getSession().putClientData(key, accounts);
  	}	
  	accounts = (gs.nil(accounts) || accounts == 'NIL') ? null : accounts;
  	return accounts;
  },
  
  /*
  * If any additional Access Context is defined in Extension Point consider those.
  */
  getAdditionalAccessibleAccounts: function(context){
  	var accounts = []; 
  	var ep = new GlideScriptedExtensionPoint().getExtensions(this.ACCESS_CONTEXT_EXTENSION_POINT);
  	
  	for(var i = 0; i < ep.length; i ++){
  		var point = ep[i];
  		accounts = point.getAccessibleAccount(context,accounts);	
  	}
  	
  	return accounts;
  },
  
  getValue: function(value) {
  	if(value == 'my_userId')
  		return gs.getUserID();

  	if(value == 'my_consumerId') {
  		var consumerId = new global.CSManagementUtils().getConsumerId();
  		return consumerId == null ? '' : consumerId;
  	}

  	if(value == 'my_companyId')
  		return gs.getUser().getCompanyID();
  	
  	if (gs.tableExists(global.CSMBaseConstants.SOLD_PRODUCT)) {
  		var IBUtil =  new sn_install_base.InstallBaseUtil();
  		if (value == 'my_consumerOwnedProducts')
  			return IBUtil.getConsumerSoldProducts(global.CSMRelationshipConstants.ACCESS.FULL);
  		if (value == 'my_AdditionalIBs')
  			return IBUtil.getMyInstallBaseItems();
  		if (value == 'my_contactIBs')
  			return IBUtil.getMyInstallBaseItemsForSPContact();
  		if (value == 'my_contactSPs')
  			return IBUtil.getMySPsFromPrimaryContacts();
  		if(value == 'my_contactAdditionalSPs')
  			return IBUtil.getMySPsFromAdditionalContacts();
  		if(value == 'my_contactAdditionalSPsForCase')
  			return IBUtil.getMySPsFromAdditionalContacts(CSMRelationshipConstants.ACCESS.FULL);
  		if (value == 'my_consumerAdditionalSPs')
  			return IBUtil.getConsumerSoldProducts();
  		if (value == 'my_consumerSPs')
  			return IBUtil.getMyPrimaryConsumerSPs();
  		
  	}
  	if(value == 'my_related_party_cases'){
  		return new global.CSMRelationshipUtils().getRelatedPartyCases();
  	}
  	
  	return '';
  },
  
  /*
  * QBR queries can be used in each entity's QBR functions based on Conditions
  */
  getQBRConditionQueries: function(current,tableName,skipEncodedQuery){
  	var query = null;
  	var entity = gs.nil(tableName) ? current.getTableName() : tableName;
  	var conditions = this.getRoleAccessDetails('condition', entity);	
      if(!gs.nil(conditions)){
  		var queryStr = '';
  		for(var i = 0; i < conditions.length; i++){	
  			var pool = this.getRoleContentPool('condition');
  			var conditionPair = pool[conditions[i]];	  
  			// For conditions based on script or methods.		
  			if (gs.nil(conditionPair['query'])) {
  				if (!this._isValidField(entity, conditionPair['key']))
  					continue;
  				var op = conditionPair['operator'];
  				if (gs.nil(op)) {
  					if (gs.nil(query))
  						query = current.addQuery(conditionPair['key'], this.getValue(conditionPair['value']));
  					else
  						query.addOrCondition(conditionPair['key'], this.getValue(conditionPair['value']));
  				} else if (op == CSQueryBRUtilOOBConstants.OPERATOR_IN || op == global.CSQueryBRUtilOOBConstants.OPERATOR_CONTAINS) {
  					if (gs.nil(query))
  						query = current.addQuery(conditionPair['key'], op, this.getValue(conditionPair['value']));
  					else
  						query.addOrCondition(conditionPair['key'], op, this.getValue(conditionPair['value']));
  				}
  			}
  			// For encoded conditions				
  			else {
  				if(gs.nil(queryStr))
  					queryStr = conditionPair['query'];
  				else
  					queryStr = queryStr + '^OR' + conditionPair['query'];	
  			}  
  		}
  		
  		if(!gs.nil(queryStr)){
  			// Handle some corner cases
  			if(queryStr.indexOf('accountISEMPTY^contactISEMPTY') > -1 && queryStr.indexOf('consumerISEMPTY') > -1 && queryStr.indexOf('^OR') > -1)
  				return null;
  			if(!skipEncodedQuery)
  				query = current.addEncodedQuery(queryStr);
  		
  		}
  		
  	}	
  	
  	return query;
  },
  
  
  getQueries: function(current,tableName){
  	var queryStr = '';
  	var entity = gs.nil(tableName) ? current.getTableName() : tableName;
  	var conditions = this.getRoleAccessDetails('condition', entity);	
      if(!gs.nil(conditions)){
  		var pool = this.getRoleContentPool('condition');
  		for(var i = 0; i < conditions.length; i++){	
  			var conditionPair = pool[conditions[i]];	  	
  			if(!gs.nil(conditionPair['query'])){
                	if(gs.nil(queryStr))
  					queryStr = conditionPair['query'];
  				else
  				   queryStr = queryStr + '^OR' + conditionPair['query'];	
  			}
  			
  		}
  		
  	}	
  	
  	return queryStr;
  },
  
  
  /*
  * If a role has a condition in roles' POOL, then it should pass this condition validation.
  */
  checkRoleConditions : function(current,tableName) {	
  	var entity = gs.nil(tableName)? current.getTableName(): tableName;
  	var conditions = this.getRoleAccessDetails('condition', entity);
  	
  	if(!gs.nil(conditions)){
  		for(var i = 0; i < conditions.length; i++){
  			var pool = this.getRoleContentPool('condition');
  			var conditionPair = pool[conditions[i]];
  			if(!gs.nil(conditionPair['key'])){
  				//Logic to Handle Dot walking functionality in Condition Block.
  				var conditionList = conditionPair['key'].split(".");
  				var tempObj = current;
  				var currValue = '';
  				for( var j =0 ;j<conditionList.length; j++){
  					if(!gs.nil(tempObj)){
  						tempObj = tempObj[conditionList[j]];

  						if(tempObj == undefined){
  							//To Hanlde List Layout Issue of evaluating Script Properly based on the Key Value Pair even if the Key is not present in the List layout
  							var gr = new GlideRecord(tableName);
  							if(gr.isValidField(conditionList[j])){
  								gr.get(current.sys_id);
  								tempObj = gr[conditionList[j]];
  							}
  						}
  						currValue = tempObj;
  					}
  				}
  				var op = conditionPair['operator'];
  				var value = this.getValue(conditionPair['value']);
  				if (op == global.CSQueryBRUtilOOBConstants.OPERATOR_IN) {
  					if (value && value.indexOf(currValue + '') > -1)
  						return true;
  				} else if (op == global.CSQueryBRUtilOOBConstants.OPERATOR_CONTAINS) {
  					if (currValue && (currValue + "").indexOf(value) > -1 )
  						return true;
  				} else if (currValue == value)
  					return true;
  			}
  		}
  	}
  	return false;
  },
  
  /*
  * If a role has an access context related in roles' POOL, then it should pass this function
  * to get the access to a specific access context, such as an account.
  */
  checkRoleAccessCxt: function(current, driver_field, skipMyAccount,tableName) {
  	skipMyAccount = skipMyAccount || false;	
  	var entity = gs.nil(tableName)? current.getTableName(): tableName;
  	var access_contexts = this.getMyAccessibleAccounts(entity, skipMyAccount);
  	//For consumer 
  	if (access_contexts == '-1' )
  		return false; //For Consumers default access based on Account will be false as they are not dependent on Account Access

  	//For customer
  	if(!gs.nil(driver_field)){
  		var access_id = current.getValue(driver_field);
  		if (!gs.nil(access_id) && !gs.nil(access_contexts) && access_contexts.indexOf(access_id) != -1)
  			return true;
  	}

  	//For agents
  	if(gs.nil(driver_field) && !gs.nil(access_contexts) && access_contexts.includes('all'))
  		return true;

  	//For Requestor
  	if(!gs.nil(driver_field) && !gs.nil(access_contexts) && access_contexts.includes('all_account_access')){
  		return true;
  	}
  	
  	return false;
  },
  

  addProductCategoryQueryBR: function(current) {
  	var that = this;
  	var category_sys_ids = '';
  	if(gs.getProperty('csm_cmdb_model.customer_visible_flag')=='true') {
  		
  		var key ='cmdb_product_category_'+gs.getUserID();
  		var cmdb_category = gs.getSession().getClientData(key);
  		
  		if(gs.nil(cmdb_category)) {
  			var gr = new GlideAggregate(that.TABLE_PRODUCT);
  			gr.addAggregate('count');
  			gr.groupBy('cmdb_model_category');
  			gr.addQuery('customer_visible', true);
  			gr.query();
  			while(gr.next()){
  				if(category_sys_ids!=''){
  					category_sys_ids += ',';
  				}
  				category_sys_ids +=gr.cmdb_model_category;
  			}
  			gs.getSession().putClientData(key, category_sys_ids ? category_sys_ids:'NIL');
  			
  		} else {
  			category_sys_ids = cmdb_category !='NIL'? cmdb_category:'';
  		}
  		
  		if(category_sys_ids!='') {
  			var category = new GlideRecord(that.TABLE_PRODUCT_CATEGORY);
  			category.addQuery('sys_id', 'IN', category_sys_ids);
  			var q = category.getEncodedQuery();
  			
  			current.addEncodedQuery(q);
  		}
  	}
  	
  	return current;
  },
  
  addProductQueryBR: function(current) {
  	var that = this;
  	if(gs.getProperty('csm_cmdb_model.customer_visible_flag')=='true') {
  		var query = null;
  		var gr = new GlideRecord(that.TABLE_PRODUCT);
  		gr.addQuery('customer_visible', 'true');
  		var q = gr.getEncodedQuery();
  		if (!gs.nil(q))
  			current.addEncodedQuery(q);
  	}
  	return current;
  },
  
  addQueryBR: function(current,table) {
  	var tableName = gs.nil(table) ? current.getTableName():table;
  	var accounts = this.getMyAccessibleAccounts(tableName, false);
  	var query = this.getQBRConditionQueries(current,tableName);
  	/*
  	* In the getQBRConditionQueries function, The value of query return as undefined if the condition is not a key-value pair in the extension point. This is handled in the if..else block below
  	*/		
  	if(!gs.nil(query)){
  		query.addOrCondition('account', 'IN', accounts);	
  	}
  	else
  		current.addQuery('account', 'IN', accounts);
  	return current;
  },
  

  addOrderQueryBR: function(current) {
  	return this.addQueryBR(current,this.TABLE_ORDER);
  },

  addOrderQueryForConsumer: function(currrent) {
  	var query = new global.CSQueryBRUtil().getReferenceTableQueryForConsumer(current.getTableName());
  	if (!gs.nil(query))
  		current.addEncodedQuery(query);
  	return current;
  },

  
  addAccountQueryBR: function(current) {
  	var query = this.getReferenceTableQueryForCustomer(this.TABLE_ACCOUNT, 'sys_id');
  	if (!gs.nil(query))
  		current.addEncodedQuery(query);
  	
  	return current;
  },
  
  addEntitlementQueryBR: function(current) {
  	var query = this.getReferenceTableQueryForCustomer(this.TABLE_SERVICE_ENTITLEMENT);
  	if (!gs.nil(query))
  		current.addEncodedQuery(query);

  	return current;
  },
  
  addContractQueryBR: function(current) {
  	var query = this.getReferenceTableQueryForCustomer(this.TABLE_AST_CONTRACT);
  	if (!gs.nil(query))
  		current.addEncodedQuery(query);

  	return current;
  },
  
  addAssetQueryBR: function(current) {
  	var useM2MAssetContact = gs.getProperty('sn_customerservice.use_asset_contact_relationship', 'false');
  
  	if (useM2MAssetContact == 'false' || this.canOverrideM2MProperty()) {
  		var query = this.getReferenceTableQueryForCustomer(this.TABLE_ALM_ASSET);
  		if (!gs.nil(query))
  			current.addEncodedQuery(query);
  	} else {
  		var grSQ = current.addJoinQuery('sn_customerservice_m2m_asset_contact', 'sys_id', 'asset');
  		grSQ.addCondition('contact', gs.getUserID());
  	}
  	
  	return current;			
  },
  
  addSoldProductQueryBRForConsumer: function(current, tableName){
  	
  	var util = new sn_install_base.SoldProductAndInstallBaseFilter();
  	var userConsumerID = new global.CSManagementUtils().getConsumerId();
  	var list = util.getValidSoldProducts(userConsumerID, global.CSMRelationshipConstants.CONSUMER_SOLD_PRDOUCT_VIEWER);
  	
  	tableName = gs.nil(tableName) ? current.getTableName():tableName;
  	var query = this.getQBRConditionQueries(current,tableName);
  	/*
  	* In the getQBRConditionQueries function, The value of query return as undefined if the condition is not a key-value pair in the extension point. This is handled in the if..else block below
  	*/		
  	if(!gs.nil(query)){
  		query.addOrCondition('sys_id', 'IN', list);	
  	}
  	else
  		current.addQuery('sys_id', 'IN', list);
  	return current;
  	
  },
  
  addInstallBaseQueryBRForConsumer: function(current, tableName){
  	var tableName = gs.nil(tableName) ? current.getTableName():tableName;
  	this.addQueryBR(current, tableName);
  },
  
  /*
  	* The method support query in below format
  	* queryStr ^ (query ^OR accounts)
  	*	query: key-value condition
  	*	queryStr: query string from query paramater in condition
  	*	accounts: accessible accounts of user
  */
  addInstallBaseQueryBR: function(current, tableName){
  	var tableName = gs.nil(tableName) ? current.getTableName():tableName;
  	var accounts = this.getMyAccessibleAccounts(tableName, false);
  	var query = this.getQBRConditionQueries(current,tableName,true);
  	var queryStr = this.getQueries(current, tableName);
  	
  	if (!gs.nil(query) && !gs.nil(accounts)) {
  		query.addOrCondition('account', 'IN', accounts);
  	} else if (!gs.nil(accounts))
  		current.addQuery('account', 'IN', accounts);
  	
  	current.addEncodedQuery(queryStr);

  	return current;
  },

  
  addInstallBaseQueryBRForAgent: function(current, tableName){
  	var tableName = gs.nil(tableName) ? current.getTableName():tableName;
      this.addQueryforAgent(current, tableName);
  },
  
  addSoldProductCoveredQueryBRForAgent: function(current, tableName){
  	var tableName = gs.nil(tableName) ? current.getTableName():tableName;
      this.addQueryforAgent(current, tableName);
  },
  
  addInstallBaseQueryBRForM2M: function(current, tableName) {
      tableName = gs.nil(tableName) ? current.getTableName() : tableName;
      var accounts = this.getMyAccessibleAccounts(tableName, false);
      var queryStr = this.getQueries(current, tableName);
  	
      if (!gs.nil(queryStr) && !gs.nil(accounts)) 
          current.addEncodedQuery(queryStr + '^ORinstall_base_item.accountIN' + accounts);
      else if(!gs.nil(queryStr))
  		current.addEncodedQuery(queryStr);
  	else if(!gs.nil(accounts))
          current.addEncodedQuery('install_base_item.accountIN' + accounts);

  },
  
  addSoldProductCoveredQueryBRForM2M: function(current, tableName) {
      tableName = gs.nil(tableName) ? current.getTableName() : tableName;
      var accounts = this.getMyAccessibleAccounts(tableName, false);
      var queryStr = this.getQueries(current, tableName);
  	
      if (!gs.nil(queryStr) && !gs.nil(accounts)) 
          current.addEncodedQuery(queryStr + '^ORsold_product.accountIN' + accounts);
      else if(!gs.nil(queryStr))
  		current.addEncodedQuery(queryStr);
  	else if(!gs.nil(accounts))
          current.addEncodedQuery('sold_product.accountIN' + accounts);
  },

  addInstallBaseQueryBRForM2MForConsumer: function(current) {
      current.addEncodedQuery('install_base_item.consumer=' + this.getValue('my_consumerId'));
  },
  
  addSoldProductCoveredQueryBRForM2MForConsumer: function(current) {
      current.addEncodedQuery('sold_product.consumer=' + this.getValue('my_consumerId'));
  },
  
  // A special case for customer admin to override M2MAsset property. Not common for all entities.
  canOverrideM2MProperty: function(){
  	return gs.hasRole('sn_customerservice.customer_admin') && !gs.hasRole('sn_customerservice.partner_admin');
  },
  
  addContactQueryBR: function(current) {
  	var gr = new GlideRecord(this.TABLE_CONTACT);

  	//add login user
  	var query = gr.addQuery('sys_id', gs.getUserID());
  	var accounts = this.getMyAccessibleAccounts(this.TABLE_CONTACT, false);

  	if (!gs.nil(accounts))
  		query.addOrCondition('account', 'IN', accounts);
  		
  	var q = gr.getEncodedQuery();
  	if (!gs.nil(q))
  		current.addEncodedQuery(q);
  	
  	// 		gs.info("contact query :" + gr.getEncodedQuery());
  	return current;
  },

  	
  addCaseQueryBR: function(current) {		
  	return this.addQueryBR(current,this.TABLE_CS_CASE);
  },


  getReferenceTableQueryForCustomer: function(table, driver_field) {
  	driver_field = driver_field || 'account';
  	var query = null;
  	var accounts = this.getMyAccessibleAccounts(table, false);
  	
  	var gr = new GlideRecord(table);
  	if (!gs.nil(accounts))
  		query = gr.addQuery(driver_field, 'IN', accounts);
  	
  	return gr.getEncodedQuery();
  },
  
  
  getAccountPath: function(account) {
  	account = account || gs.getUser().getCompanyID();
  	var key = "accounts_path_" + account;
  	var path = gs.getSession().getClientData(key);
  	if (gs.nil(path)) {
  		var gr = new GlideRecord(this.TABLE_ACCOUNT);
  		gr.setWorkflow(false);
  		if (gr.get(account))
  			path = gr.getValue('account_path');
  		gs.getSession().putClientData(key, gs.nil(path) ? 'NIL' : path);
  	}
  	return path == 'NIL' ? null : path;
  },
  
  getAccountsFromContactRelationship: function() {
  	//account from contact relationship
  	var accounts = [];
  	var ac =  new GlideRecord(this.TABLE_CONTACT_RELATIONSHIP);
  	ac.addQuery('contact', gs.getUserID());
  	ac.setWorkflow(false);
  	ac.query();
  	while(ac.next())
  		accounts.push(ac.getValue('company'));
  	return accounts;
  },
  
  getAccountsFromAccountConsumer : function(){
  var consumerId  = new global.CSManagementUtils().getConsumerId();
  	var accounts = [];
  	if(consumerId){
  		var aco = new GlideRecord(this.TABLE_ACCOUNT_CONSUMER);
  		aco.addQuery('consumer',consumerId);
  		aco.addActiveQuery();
  		aco.setWorkflow(false);
  		aco.query();
  		while(aco.next())
  			accounts.push(aco.getValue('account'));
  	}

  	return accounts;
  },

  getAccountsFromAccountRelationship: function() {
  	//account from account relationship
  	var accounts = [];
  	var ar = new GlideRecord(this.TABLE_ACCOUNT_RELATIONSHIP);
  	ar.addQuery('reverse_relationship', false);
  	ar.addQuery('from_company', gs.getUser().getCompanyID());
  	ar.setWorkflow(false);
  	ar.query();
  	while(ar.next())
  		accounts.push(ar.getValue("to_company"));
  	return accounts;
  },
  
  generateCreateCaseHiddenValue: function(company) {
  	company = company || gs.getUser().getCompanyID();
  	var value = "company-" + company;
  	var gr = new GlideRecord('customer_account');
  	if (gr.get(company)) {
  		value += "#isCustomer-" + gr.customer;
  		value += "#isPartner-" + gr.partner;
  		
  		var count = new GlideAggregate('customer_account');
  		count.addQuery('account_path', 'STARTSWITH', gr.account_path + '/');
  		count.addAggregate('COUNT');
  		count.setWorkflow(false);
  		count.query();
  		if (count.next())
  			value += "#hasSubAccounts-" + (count.getAggregate('COUNT') > 0);
  		
  		var ar = new GlideAggregate('sn_customerservice_contact_relationship');
  		ar.addQuery('contact', gs.getUserID());
  		ar.addAggregate('COUNT');
  		ar.setWorkflow(false);
  		ar.query();
  		if (ar.next())
  			value += "#hasAccountContactRelation-"  + (ar.getAggregate('COUNT') > 0);
  	}
  	// 		gs.info("generateCreateCaseHiddenValue -->" + value);
  	return value;
  },
  
  // functions for consumers and consumer agents
  
  getConsumer: function(){
  	return new global.CSManagementUtils().getConsumerId();
  },
  
  getReferenceTableQueryForConsumer: function(table, field) {
  	var consumer = this.getConsumer();
  	if (gs.nil(consumer))
  		return null;

  	var gr = new GlideRecord(table);
  	
  	//check if base extension plugin is active
  	if (gs.tableExists('sn_customer_rel_consumer_to_consumer')) {
  		
          field = gs.nil(field)? "consumer":"sys_id";
  		
  		var encodedQuery = new sn_cs_base_ext.AuthorizedRepUtil().getConsumersforConsumerEQ(consumer, table, field);
  		//check if household plugin is active
  		if (gs.tableExists('csm_household_member') ) {
  			
  			var householdquery = new sn_csm_household.HouseHoldUtils().getConsumersforConsumerEQ(consumer, table, field );
  			if(!gs.nil(householdquery))
  				encodedQuery =  gs.nil(encodedQuery)? householdquery : encodedQuery + '^OR' + householdquery;
  		}
  		
  		gr.addEncodedQuery(encodedQuery);
  
  		
  	} else {
  		if (gs.nil(field))
  			field = 'consumer';
  		else if (field == 'user')
  			consumer = gs.getUserID();
  		
  		gr.addQuery(field, consumer);
  	}

  	return gr.getEncodedQuery();
  },
  
  addConsumerQueryforConsumer: function(current) {
  	var query = this.getReferenceTableQueryForConsumer(this.TABLE_CSM_CONSUMER, 'user');
  	if (!gs.nil(query))
  		current.addEncodedQuery(query);
  	
  	return current;
  },
  
  /*
   * Query eg: consumer IS loogedInConsumerId or sold_product IN consumers sold products
  */
  addCaseQueryforConsumer: function(current) {
  	var query = this.getReferenceTableQueryForConsumer(this.TABLE_CS_CASE);
  	var caseGR = new GlideRecord(this.TABLE_CS_CASE);
  	this.addQueryBR(caseGR);
  	var caseEncQueryWithQBR = caseGR.getEncodedQuery();
  	if (!gs.nil(caseEncQueryWithQBR))
  		query = (gs.nil(query)) ? caseEncQueryWithQBR : query + "^OR" + caseEncQueryWithQBR;
  	
  	if (!gs.nil(query))
  		current.addEncodedQuery(query);
  	
  	return current;
  },
  
  addQueryforAgent: function(current,table){	
  	var tableName = gs.nil(table)? current.getTableName(): table;
  	var query = this.getQBRConditionQueries(current,tableName);				
  	if(!gs.nil(query))
  		current.addEncodedQuery(query);

  	return current;			
  },

  addCaseQueryforAgent: function(current){
  	return this.addQueryforAgent(current,this.TABLE_CS_CASE);		
  },
  
  /*
  * Called from the BQBR to filter the cases a user with either the svc_location roles or relationship_agent or both 
  * roles can see.
  * 1. Location manager - Can see both consumer & account cases of all hierarchies of IBLs he/she is the manager of.
  * 2. Location consumer agent - Can only see cases assigned to orgs he/she belongs to and account and contact are not set.
  * 3. Location agent - Can only see cases assigned to orgs he/she belongs to and consumer and household are not set.
  * 4. Relationship agent - Can see cases for Account/Consumer/Household for which he is account or relationship manager of
  * Here's the combinations the below method generates the query for
  * 1, 2, 3, 4, 1&4, 2&3.
  * Location Manager role is a superset of both the location agent personas.
  *
  */
  addCaseQueryForLocationAndRelationshipPersonas: function(current){
  	var myRoles = gs.getUser().getRoles();
  	var encodedQuery = 'assigned_to=' + gs.getUserID();
  	var isRelationshipAgent = false;
  	
  	// Relationship personas.
  	if(myRoles.indexOf('sn_customerservice.relationship_agent') > -1){
  		var accountManagerQuery = new sn_cs_base_ext.AccountManagerRelationshipUtil().getAccessibleAccountsQuery(gs.getUserID());
  		var consumerManagerQuery = new sn_cs_base_ext.RelationshipManagerUtil().getAccessibleConsumersQuery(gs.getUserID());
  		var householdManagerQuery = gs.tableExists('csm_household_member') ? new sn_cs_base_ext.RelationshipManagerUtil().getAccessibleHouseholdsQuery(gs.getUserID()) : '';
  		isRelationshipAgent = !gs.nil(accountManagerQuery) || !gs.nil(consumerManagerQuery) || !gs.nil(householdManagerQuery);
  		
  		if(!gs.nil(accountManagerQuery))
  			encodedQuery += '^OR' + accountManagerQuery;
  		if(!gs.nil(consumerManagerQuery))
  			encodedQuery += '^OR' + consumerManagerQuery;
  		if(!gs.nil(householdManagerQuery))
  			encodedQuery += '^OR' + householdManagerQuery;
  	}
  	
  	// Location personas
  	if(gs.tableExists('sn_csm_business_location_internal')) {
  		var myOrgPaths = new global.ServiceOrganizationUtil().getUserServiceOrgPaths(gs.getUserID());
  		// Location Manager gets to see the cases from all his/her location hierarchies
  		if(myRoles.indexOf('sn_customerservice.svc_location_manager') > -1){
  			for(var i = 0; i < myOrgPaths.length;i++){
  				encodedQuery += '^ORservice_organization.service_organization_pathSTARTSWITH' + myOrgPaths[i];
  			    encodedQuery += '^ORrequesting_service_organization.service_organization_pathSTARTSWITH' + myOrgPaths[i];
  			}
  		} else {
  			// Location and location consumer agents can see cases assigned to their location(s) only.
  			if(myRoles.indexOf('sn_customerservice.svc_location_agent') > -1 || myRoles.indexOf('sn_customerservice.svc_location_consumer_agent') > -1){
  				for(var i = 0; i < myOrgPaths.length;i++){
  					encodedQuery += '^ORservice_organization.service_organization_path=' + myOrgPaths[i];
  					encodedQuery += '^ORrequesting_service_organization.service_organization_path=' + myOrgPaths[i];
  				}
  				
  				// Add the account vs consumer filter only if the logged in user is not a relationship agent and is either a location agent or a location consumer agent but not both.
  				// Cannot write a simple query that satisfies both the conditions.
  				if(!isRelationshipAgent && !(myRoles.indexOf('sn_customerservice.svc_location_agent') > -1 && myRoles.indexOf('sn_customerservice.svc_location_consumer_agent') > -1)){
  					if(myRoles.indexOf('sn_customerservice.svc_location_agent') > -1){
  						encodedQuery += "^consumerISEMPTY";
  						if(gs.tableExists('csm_household_member'))
  							encodedQuery += "^householdISEMPTY";
  					} else {
  						encodedQuery += "^accountISEMPTY^contactISEMPTY";
  					}
  				}
  			}
  		}
  	}
  	
  	if(!gs.nil(encodedQuery))
  		current.addEncodedQuery(encodedQuery);
  	return current;
  },
  
  addEntitlementQueryforConsumer: function(current) {
  	var query = this.getReferenceTableQueryForConsumer(this.TABLE_SERVICE_ENTITLEMENT);
  	if (!gs.nil(query))
  		current.addEncodedQuery(query);
  	
  	return current;
  },
  
  addEntitlementQueryforAgent: function(current){
  	return this.addQueryforAgent(current,this.TABLE_SERVICE_ENTITLEMENT);
  },
  
  addContractQueryforConsumer: function(current) {
  	var query = this.getReferenceTableQueryForConsumer(this.TABLE_AST_CONTRACT);
  	if (!gs.nil(query))
  		current.addEncodedQuery(query);
  	
  	return current;
  },
  
  addContractQueryforAgent: function(current) {
  	var query = this.getQBRConditionQueries(current,this.TABLE_AST_CONTRACT);		
  	return current;
  },
  
  addAssetQueryforConsumer: function(current) {
  	var query = this.getReferenceTableQueryForConsumer(this.TABLE_ALM_ASSET);
  	if (!gs.nil(query))
  		current.addEncodedQuery(query);
  	
  	return current;
  },
  
  addAssetQueryforAgent: function(current) {	
  	return this.addQueryforAgent(current,this.TABLE_ALM_ASSET);
  },
  
  canAgentReadCase: function (current,tableName) {
  	var entity = gs.nil(tableName) ? current.getTableName() : tableName;

  	if(this.checkRoleConditions(current,entity))
          return true;
  	
  	return false;
  },
  	
  /*
  * Get the sub accounts of an account
  */
  getSubAccounts : function() {  
  	var accounts = [];
  	var gr = new GlideRecord(this.TABLE_ACCOUNT);
  	var path = this.getAccountPath();
  	if (!gs.nil(path)) {  //PRB1329711: DO not Query Account for Sub Accounts if the Path is Nil.
  		gr.addQuery("account_path", 'STARTSWITH', path);
  		gr.query();

  		while(gr.next())
  			accounts = accounts.concat(gr.getValue('sys_id'));
  	}
  	return accounts;
  },		

  canESMUserReadCase: function (current, tableName) {	
  	var entity = gs.nil(tableName) ? current.getTableName() : tableName;

  	if( this.checkRoleConditions(current,entity) || this.checkRoleAccessCxt(current, this.DEFAULT_DRIVER_FIELD,false,entity))	
  		return true;
  	else
  		return current.contact == gs.getUser().getID();	
  },

  canESMUserReadEntitlement: function(current,tableName) {	
  	if (gs.nil(current))
  		return false;
  	
  	var account_id = current.getValue('account');
  	var companyId = gs.getUser().getCompanyID();
  	
  	if(gs.nil(account_id) && !gs.nil(current.product)) {
  		var asset = new GlideRecord("alm_asset");
  		asset.addQuery("account", companyId);
  		asset.addQuery("model", current.product);
  		asset.query();
  		if(asset.next())
  			return true;
  	}
  	
  	if(gs.nil(account_id) && !gs.nil(current.asset))
  		account_id = current.asset.account;
  	
  	if(gs.nil(account_id) && !gs.nil(current.contract))
  		account_id = current.contract.account;
  	
  	if(gs.nil(account_id))
  		return false;
  	
  	//if my account entitlement
  	if(companyId == account_id)
  		return true;	
  	
  	var entity = gs.nil(tableName) ? current.getTableName() : tableName;

  	return this.checkRoleAccessCxt(current, this.DEFAULT_DRIVER_FIELD, true, entity);
  	
  },
  
  canESMUserReadAccount: function(current,tableName){
  	if (gs.nil(current))
  		return false;
  	
  	if(current.sys_id == gs.getUser().getCompanyID())
  		return true;	
  	
  	var entity = gs.nil(tableName) ? current.getTableName() : tableName;

  	return this.checkRoleAccessCxt(current, 'sys_id', true,entity);
  },
  
  canESMUserReadContact: function(current,tableName){
  	if (gs.nil(current))
  		return false;
  	
  	if(current.sys_id == gs.getUser().getID())
  		return true;
  	
  	var entity = gs.nil(tableName) ? current.getTableName() : tableName;

  	return this.checkRoleAccessCxt(current, this.DEFAULT_DRIVER_FIELD, false, entity);
  },
  
  canESMUserReadAsset: function(current,tableName){
  	if (gs.nil(current))
  		return false;
  	
  	var useM2MAssetContact = gs.getProperty('sn_customerservice.use_asset_contact_relationship', 'false');
  	if (useM2MAssetContact == 'true') {
  		var gr = new GlideRecord('sn_customerservice_m2m_asset_contact');
  		gr.addQuery('asset', current.sys_id);
  		gr.addQuery('contact', gs.getUser().getID());
  		gr.query();
  		return gr.next();
  	}		

  	var entity = gs.nil(tableName) ? current.getTableName() : tableName;

  	return this.checkRoleConditions(current,entity) || this.checkRoleAccessCxt(current, this.DEFAULT_DRIVER_FIELD,false,entity);	

  },

  canESMUserReadContract: function(current, tableName){
  	if (gs.nil(current))
  		return false;	

  	var entity = gs.nil(tableName) ? current.getTableName() : tableName;

  	return this.checkRoleAccessCxt(current, this.DEFAULT_DRIVER_FIELD,false,entity);	
  },

  canConsumerReadAsset: function(current,tableName){
  	if (gs.nil(current))
  		return false;
  	var entity = gs.nil(tableName) ? current.getTableName() : tableName;
  	return this.checkRoleConditions(current,entity);	 //Check for Role Condition rather than Account Access Context for Consumers            
  },

  canConsumerReadContract: function(current,tableName){
  	if (gs.nil(current))
  		return false;
  	var entity = gs.nil(tableName) ? current.getTableName() : tableName;

  	return this.checkRoleConditions(current,entity);
  },
  
  canConsumerReadEntitlement: function(current,tableName){
  	if (gs.nil(current))
  		return false;
  	var entity = gs.nil(tableName) ? current.getTableName() : tableName;

  	return this.checkRoleConditions(current,entity);
  },
  
  canConsumerReadRecord: function(current,tableName){
  	if (gs.nil(current))
  		return false;
  	
  	var entity = gs.nil(tableName) ? current.getTableName() : tableName;

  	return this.checkRoleConditions(current,entity);
  	
  },
  	
  canUserReadRecord: function(current,tableName){
  	if (gs.nil(current))
  		return false;
  	
  	var entity = gs.nil(tableName) ? current.getTableName() : tableName;
  	return this.checkRoleConditions(current,entity) || this.checkRoleAccessCxt(current, this.DEFAULT_DRIVER_FIELD,false,entity);
  },
  
  canUserReadRecordFromQueries: function(current,tableName){
  	if (gs.nil(current))
  		return false;
  	var tableName = gs.nil(tableName) ? current.getTableName():tableName;
  	var queryStr = this.getQueries(current, tableName);
  	return GlideFilter.checkRecord(current, queryStr);
  },
  
  canAgentReadRecord: function(current,tableName){
  	if (gs.nil(current))
  		return false;
  	var tableName = gs.nil(tableName) ? current.getTableName():tableName;
  	var queryStr = this.getQueries(current, tableName);
  	return GlideFilter.checkRecord(current, queryStr);
  },
  
  addIPQueryBRForConsumer: function(current, tableName) {
  	if (gs.nil(current) || !current.isValid())
  		return;
  	var tableName = gs.nil(tableName) ? current.getTableName() : tableName;
  	var queryStr = this.getQueries(current, tableName);
  	if (!gs.nil(queryStr))
  		current.addEncodedQuery(queryStr);
  },
  
  _isValidField: function(entity, key) {
  	if (!entity || !key)
  		return;
  	var entityGR = new GlideRecord(entity);
  	var fields = key.split(".");
  	for (var i = 0, len = fields.length; i < len; i++) {
  		if (!entityGR.isValid() || !entityGR.isValidField(fields[i]))
  			return;
  		entityGR = entityGR.getElement(fields[i]).getRefRecord();
  	}
  	return true;
  },
  
  addAdditionalContactQueryBR: function(current, tableName) {
  	this._addEncodedQueryFromQueries(current, tableName);
  },
  
  addAdditionalConsumerQueryBR: function(current, tableName) {
  	this._addEncodedQueryFromQueries(current, tableName);
  },
  
  _addEncodedQueryFromQueries: function(current, tableName) {
  	if (gs.nil(current) || !current.isValid())
  		return;
  	tableName = gs.nil(tableName) ? current.getTableName() : tableName;
  	var queryStr = this.getQueries(current, tableName);
  	if (!gs.nil(queryStr))
  		current.addEncodedQuery(queryStr);
  },
  
  type: 'CSQueryBRUtil'
});

Sys ID

234859e1c3011200b12d9f2974d3ae32

Offical Documentation

Official Docs: