Name
global.AccountsCacheUtil
Description
Helper functions for caching accounts that login user has access in private cache
Script
var AccountsCacheUtil = Class.create();
AccountsCacheUtil.prototype = {
initialize: function() {},
/*
* Initialize cache
*/
initPrivateCache: function(name) {
if (!name)
return;
if (GlideCacheManager.get(name, "_created_") === null) {
GlideCacheManager.addPrivateCacheable(name);
GlideCacheManager.put(name, "_created_", new GlideDateTime().getNumericValue());
}
},
/*
* Partner accounts having relationship with more than max_partner_account_rel_limit of customer accounts
* max_partner_account_rel_limit is configurable as per customer requirement.
*/
getLargeAccountRelPartners: function() {
var max_account_rel_limit = parseInt(GlideProperties.get('max_partner_account_rel_limit', '500'));
var partners = [];
var ga = new GlideAggregate("account_relationship");
ga.addEncodedQuery("relationship_label=Is Partner Of^from_company!=NULL^to_company!=NULL");
ga.addAggregate("COUNT", "to_company");
ga.groupBy("from_company");
ga.addHaving('COUNT', '>', max_account_rel_limit);
ga.orderByAggregate('COUNT', 'to_company');
ga.query();
while (ga.next()) {
if (ga.getAggregate("COUNT", 'to_company') > max_account_rel_limit) {
partners.push(ga.getValue('from_company'));
}
}
return partners;
},
/*
* Check if the account that the user belongs to exists in LARGE_PARTNER_CACHE
*/
isMyAccountALargePartnerAccount: function() {
this.initPrivateCache('LARGE_PARTNER_ACCOUNTS');
var largeAccounts = [];
largeAccounts = GlideCacheManager.get('LARGE_PARTNER_ACCOUNTS', 'large_partner_accounts');
if (gs.nil(largeAccounts) || largeAccounts == 'NIL') {
largeAccounts = this.getLargeAccountRelPartners();
largeAccounts = (largeAccounts.length > 0) ? largeAccounts.join(',') : 'NIL';
GlideCacheManager.put("LARGE_PARTNER_ACCOUNTS", 'large_partner_accounts', largeAccounts);
}
var userAccount = gs.getUser().getCompanyID() + "";
return (largeAccounts.includes(userAccount));
},
/*
* Check if the account has more than max_sub_accounts_limit of children accounts in the hierarchy
* max_sub_accounts_limit is configurable as per customer requirement.
*/
isLargeParentAccount: function(userAccount) {
var max_sub_accounts_limit = parseInt(GlideProperties.get('max_sub_accounts_limit', '500'));
var account_path = new global.CSQueryBRUtil().getAccountPath(userAccount);
var ga = new GlideAggregate('customer_account');
ga.addEncodedQuery("account_pathSTARTSWITH" + account_path);
ga.addAggregate('COUNT');
ga.query();
if (ga.next() && ga.getAggregate('COUNT') > max_sub_accounts_limit) {
return true;
}
return false;
},
/*
* Cache LARGE_PARENT_ACCOUNTS to improve performance
*/
isMyAccountALargeParentAccount: function() {
this.initPrivateCache('LARGE_PARENT_ACCOUNTS');
var largeAccounts = j2js(GlideCacheManager.get('LARGE_PARENT_ACCOUNTS', 'large_parent_accounts'));
var userAccount = gs.getUser().getCompanyID() + "";
if (gs.nil(largeAccounts))
largeAccounts = [];
if (!gs.nil(largeAccounts) && largeAccounts.includes(userAccount)) {
return true;
}
if (this.isLargeParentAccount(userAccount)) {
if (!gs.nil(largeAccounts) && largeAccounts.length > 0) {
largeAccounts = largeAccounts.split(',');
}
largeAccounts.push(userAccount);
largeAccounts = (largeAccounts.length > 0) ? largeAccounts.join(',') : 'NIL';
GlideCacheManager.put("LARGE_PARENT_ACCOUNTS", 'large_parent_accounts', largeAccounts);
return true;
}
return false;
},
isPrivateCachingEnabledForAccounts: function() {
return (gs.getProperty("use_accounts_private_cache") == 'true');
},
/*
* Accounts that login user has access need to be cached in a private cache instead of session cache if,
* 1. Role - Partner and Partner account is having relationship with more than max_account_rel_limit of customer accounts
* 2. Role - customer_admin and the account has more than max_sub_accounts_limit in the account hierarchy
*/
useAccountsPrivateCache: function(table) {
if (gs.hasRole('sn_customerservice.partner') && (table != 'sn_customerservice_case' && table != 'csm_order_case' && table != 'wm_order') && this.isMyAccountALargePartnerAccount()) {
return true;
}
if (gs.hasRole('sn_customerservice.customer_admin') && this.isMyAccountALargeParentAccount()) {
return true;
}
return false;
},
isInPrivateCache: function(cacheName, key) {
var accounts = GlideCacheManager.get(cacheName, key);
return !gs.nil(accounts);
},
isInSessionCache: function(key) {
var data = gs.getSession().getClientData(key);
return !gs.nil(data);
},
/*
Flush MY_ACCESSIBLE_ACCOUNTS and LARGE_PARENT_ACCOUNTS private cache entries, so that they can be rebuilt.
Example hierarchy: A->B->C->D->500 children accounts. Covered usecases:
UseCase 1: Insert a child account with parent as D. Flush the MY_ACCESSIBLE_ACCOUNTS cache for immediate parent D
and C, B, A (parent accounts of D).
UseCase 2: Delete a child account of D. Flush the MY_ACCESSIBLE_ACCOUNTS cache for the deleted account,
immediate parent D and C, B, A (D's parent accounts in the hierarchy)
UseCase 3: Update an account where old parent is empty and new parent is D.
Flush the MY_ACCESSIBLE_ACCOUNTS cache for new parent D and C, B, A (parent accounts in the hierarchy of D)
UseCase 4: Update an account old parent is D and new parent is empty
Flush the MY_ACCESSIBLE_ACCOUNTS cache for old parent D and B, C, A (D's parent accounts in the hierarchy)
UseCase 5: Update an account old parent is D and new parent is E.
Flush the MY_ACCESSIBLE_ACCOUNTS cache for current account, old parent D and B, C, A (parent accounts of D)
Also Flush the MY_ACCESSIBLE_ACCOUNTS cache for new parent E and it's parent accounts in the hierarchy
Always Flush LARGE_PARENT_ACCOUNTS cache. Improvise the code to conditionally flush this cache entry.
*/
flushLargeParentAccountsCache: function(current, previous) {
if (!gs.nil(current.account_parent)) {
this.flushCacheEntry(current.account_parent, current.account_path);
this.flushCacheEntry(current.account_parent, current.account_path, "child_accounts_", global.CSMBaseConstants.CACHE_CATALOG_CHILD_ACCOUNTS);
}
if (current.operation() == "update" && !gs.nil(previous)) {
this.flushCacheEntry(previous.account_parent, previous.account_path);
this.flushCacheEntry(previous.account_parent, previous.account_path, "child_accounts_", global.CSMBaseConstants.CACHE_CATALOG_CHILD_ACCOUNTS);
}
},
flushCacheEntry: function(parent, path, keyPrefix, cacheName) {
if (gs.nil(keyPrefix)) {
keyPrefix = "my_accessible_accounts_";
}
var key = keyPrefix + parent;
if (gs.nil(cacheName)) {
cacheName = "MY_ACCESSIBLE_ACCOUNTS";
}
var accounts = GlideCacheManager.get(cacheName, key);
if (!gs.nil(accounts)) {
// Get all the parent accounts in the hierarchy
var parentAccounts = [];
var accountPaths = path.split("/");
var acctGr = new GlideRecord("customer_account");
acctGr.addQuery("account_code", "IN", accountPaths.toString());
acctGr.query();
while (acctGr.next()) {
parentAccounts.push(acctGr.getUniqueValue());
}
parentAccounts.forEach(function(account) {
gs.log("Flushing " + cacheName + " cache entry for account " + account);
key = keyPrefix + account;
GlideCacheManager.prefixFlush(cacheName, key);
});
// Improvise the code to conditionally flush this cache entry
if (cacheName == "MY_ACCESSIBLE_ACCOUNTS")
GlideCacheManager.flush('LARGE_PARENT_ACCOUNTS');
}
},
// The private cacheName is different when Query rules are disabled
flushLargePartnerAccountsCache: function(accountRel) {
var cacheName = "ACCOUNTS_FROM_ACCOUNT_REL";
var key = "accounts_from_account_rel_" + accountRel.from_company;
if (!new global.CSMQueryRulesUtil().useQueryRules()) {
cacheName = "MY_ACCESSIBLE_ACCOUNTS";
key = "my_accessible_accounts_" + accountRel.from_company;
}
var myAccessibleAccounts = GlideCacheManager.get(cacheName, key);
if (!gs.nil(myAccessibleAccounts)) {
gs.log("Flushing cache entry for account " + accountRel.from_company);
GlideCacheManager.prefixFlush(cacheName, key);
GlideCacheManager.flush('LARGE_PARTNER_ACCOUNTS');
}
},
type: 'AccountsCacheUtil'
};
Sys ID
f99f76c653ae0110d6a0ddeeff7b1239