- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
05-25-2023 01:50 AM
Hello,
I have 2 locations:
- "Site1" (Location Type=Site) with parent location "Rio de Janeiro" (Location Type=City)
- "Site2" (Location Type=Site) with parent location "Rio de Janeiro" (Location Type=City)
I also have 2 users:
- user A with Location = "Site1"
- user B with Location = "Site2"
I have created a catalog article that is is linked to a service offering ("Available For Subscribers" relation)
If I make the service offering "Subscribed by Location Site1", it works:
- user A see the catalog article
- user B does not
But if I make the service offering "Subscribed by Location Rio de Janeiro":
- none of the users can see it
I would have expected child locations to be taken into account so that both users would see the catalog item.
Can anyone confirm that this is the expected behavior?
I could not fin any documentation reference to precisely tell whether it is expected or not.
Regards,
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
06-02-2023 05:18 PM
Hi All,
As @Barry Kant pointed out (thanks again!) I have confirmed that it is indeed the ServiceSubscriptionUtils script, not the SPMSubscriptionUtils script, that is being executed when evaluating which Catalog Items are visible to users based on the Offering Subscriptions. Furthermore, I have validated that you can indeed modify this script to that it will include all parent locations of the user's Location, which avoids the need to individually subscribe every child location at the Offering level.
Here is the code change needed to subscribe Locations recursively:
Here is the modified _addLocation function:
_addLocation: function(answer, location_id) {
var gr = new GlideRecord(this.constants.SERVICE_SUBSCRIBE_LOCATION);
var qry = gr.addQuery('cmn_location', location_id);
//FIX for recursive subscription: add parent locations
var grLoc = new GlideRecord('cmn_location');
while (!gs.nil(location_id)) {
if (grLoc.get(location_id)) {
location_id = grLoc.getValue('parent');
if (!gs.nil(location_id)) {
qry.addOrCondition('cmn_location', location_id);
}
}
}
this._query(gr, answer);
},
IMPORTANT: When testing this change, clear your server and browser cache before testing the results or else you may not see the change occur!
You can follow the same approach to recursively subscribe to Companies, Departments, and Groups as well.
@marcguegueniat (and others) please try this out and mark this as a Solution if this works for you. And if it doesn't, let me know because I'd love to see this through to resolution!
The opinions expressed here are the opinions of the author, and are not endorsed by ServiceNow or any other employer, company, or entity.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
05-30-2023 08:41 AM
What do you mean by "it is correct"? The comment you replied to is showing that the code appears to be including child locations, but the result we are describing that the location logic does not actually appear to be working correctly when viewing the catalog items. Are you saying our observation is correct, or that the code is correct, or that it is working correctly?
The opinions expressed here are the opinions of the author, and are not endorsed by ServiceNow or any other employer, company, or entity.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
05-30-2023 10:44 AM
It is correct that it doesn't look down from parent records. Meaning, this is how it works, but we ( I ) expect that it should take the structure into account. Departments and Locations can be in the 1000's which is not maintainable in the current state.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
05-30-2023 11:02 AM
Actually the code shows that it does include child Locations, but that it does not take child Companies, Departments, or Groups into account. Also, while agree that there are performance considerations, there would never be 1000 levels of depth in the hierarchy. I would expect this to be no more than 5-10 levels deep in most cases, which is certainly maintainable.
So the issues questions at hand for us to answer are:
1) Given that the code seems to be recursing through child locations, why aren't the results reflecting that?
2) Given that Locations are (theoretically) including child records, why aren't other subscriptions doing the same?
3) If there are different locations in which Subscriptions lists are being checked, then why is this duplicated? And what are those areas specifically so that we can keep them in sync? And what specific scenarios are the different business logic used?
The opinions expressed here are the opinions of the author, and are not endorsed by ServiceNow or any other employer, company, or entity.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
06-02-2023 05:32 AM
Hello,
I've actually found the related Script include : ServiceSubscriptionUtils
(thanks to this thread)
In this script we can see that, out of box, parent/child hierarchy is not taken into account.
I've been able to modify the script to include to make it include child locations of subscribed locations and it worked.
However, as pointed above, it is very unclear when the instance will recompute a user's offerings.
The instance clearly caches the result. This can make unit tests a real headache.
I've added a log to script to check when it is run, but it is still unclear.
If ever someone could explain us when the recompute happens, that would help.
The OOB script FYI:
var ServiceSubscriptionUtils = Class.create();
ServiceSubscriptionUtils.prototype = {
initialize : function() {
},
getMySubscriptions : function() {
var answer = new Object();
this._addUser(answer);
this._addGroup(answer);
var u = GlideUser.getUserByID(gs.getUserID());
this._addDept(answer, u.getDepartmentID());
this._addLocation(answer, u.getLocation());
this._addCompany(answer, u.getCompanyID());
// convert to an ArrayList
var a = new Array();
for (key in answer)
a.push(key);
return a;
},
_addUser : function(answer) {
var gr = new GlideRecord('service_subscribe_sys_user');
gr.addQuery('sys_user', gs.getUserID());
this._query(gr, answer);
},
_addGroup : function(answer) {
var groups = GlideUser.getMyGroups(gs.getUserID());
if (groups.isEmpty())
return;
var gr = new GlideRecord('service_subscribe_sys_user_grp');
gr.addQuery('sys_user_group', groups);
this._query(gr, answer);
},
_addDept : function(answer, dept_id) {
var gr = new GlideRecord('service_subscribe_department');
gr.addQuery('cmn_department', dept_id);
this._query(gr, answer);
},
_addLocation : function(answer, location_id) {
var gr = new GlideRecord('service_subscribe_location');
gr.addQuery('cmn_location', location_id);
this._query(gr, answer);
},
_addCompany : function(answer, company_id) {
var gr = new GlideRecord('service_subscribe_company');
gr.addQuery('core_company', company_id);
this._query(gr, answer);
},
_query : function(gr, answer) {
gr.query();
while (gr.next())
answer[gr.service_offering + ''] = true;
}
}
Regards,
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
06-02-2023 05:41 AM
Perhaps the SPMSubscriptionUtils is used if you have SPM installed, and otherwise the ServiceSubscriptionUtils script is used. Another strand in the tangled web...
The opinions expressed here are the opinions of the author, and are not endorsed by ServiceNow or any other employer, company, or entity.