Subscribed by Location in case of a parent location

marcguegueniat
Kilo Sage

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,

1 ACCEPTED SOLUTION

CMDB Whisperer
Mega Sage
Mega Sage

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:

CMDBWhisperer_0-1685751084618.png

 

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.

View solution in original post

13 REPLIES 13

hi Marc, CMDB Whisperer, 

from the top of my head the SPMSubscriptionUtils is used to calculate the Total Number of Subscribers that is shown it the legacy Service Owner Workspace records. It is in the Service Offering table. 
This logic runs by schedule on a daily base. 

This Calculates per Service Offering

The ServiceSubscriptionUtils takes the logged on user as input, so it is a session output.

var u = GlideUser.getUserByID(gs.getUserID());

The can be used to show My Subscribed Services to show that effectively in:
Show Outage based on My Subscriptions.
Show Catalog Items based on My Subscriptions.

Both scripts consume the same Subscription tables but serve a different purpose. 

We see sometimes request to add Service Subscriptions based on Business Unit, but then you need to be aware that both these script Utilities (as well as UI in DPM) are affected. 

BR,

Barry

Thank you for that clarification.  That makes much more sense.


The opinions expressed here are the opinions of the author, and are not endorsed by ServiceNow or any other employer, company, or entity.

CMDB Whisperer
Mega Sage
Mega Sage

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:

CMDBWhisperer_0-1685751084618.png

 

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.

Just a side note:

The script may fall into an infinite loop, for instance if location_id is not nil but still does not exist in the table.

An update like this one avoids the infinite loop:

		while (!gs.nil(location_id) && grLoc.get(location_id)) {
			location_id = grLoc.getValue('parent');
			if (!gs.nil(location_id)) {
				qry.addOrCondition('cmn_location', location_id);
			}
		}

 Regards,