UPDATE: As of the Helsinki ServiceNow release, this is tracked for you automatically in a new ‘Order Guide’ field on the ‘Requested Item’ table! This solution should be discontinued in Helsinki releases and beyond.
O
rder guides are a service catalog concept that allow you to set up an initial form to ask the user certain questions in order to determine a collection of catalog items they need to order. The classic use case for an order guide is the ‘New Employee Hire’ item that ServiceNow provides in the out-of-box demo data. While order guides are really a front-end routing concept, it can sometimes be useful to report on requests that were generated for a particular order guide. This functionality doesn’t exist out-of-box in ServiceNow, but it is very easy to add. Here’s a good tip that I recently learned from Sean Grison and Valor Poland about how to populate the order guide used to generate a particular request.
Only three steps are necessary to record the order guide used to generate a request…
- Create a new reference field called ‘Order guide’ on the ‘Request (sc_request)’ table. The field needs to reference the ‘Order guide (sc_cat_item_guide)’ table. You may also choose to secure write access to this field using an ACL since it really shouldn’t need to be changed by any user.
- Create a new business rule on the ‘Request (sc_request)’ table with the following settings…
‘Populate Order Guide’ Business Rule
Name: Populate Order Guide
When: Before
Insert: True
Script:var c = new GlideRecord('sc_cart');
c.get('user', gs.getUserID());
if(c.current_guide){
var isOrderGuide = true;
var foundItemCount = 0;
//Query the order guide rule base
var og = new GlideRecord('sc_cat_item_guide_items');
og.addQuery('guide', c.current_guide);
og.query();
while(og.next()){
var mustHave = false;
var foundItem = false;
//If the condition is empty then item must be ordered
if(og.condition.nil()){
mustHave = true;
}
//Check to see if the rule matches at least one item in the cart
var itm = new GlideRecord('sc_cart_item');
itm.addQuery('cart', c.sys_id);
itm.addQuery('cat_item', og.item.sys_id.toString());
itm.query();
if(itm.hasNext()){
foundItem = true;
foundItemCount++;
}
if(mustHave && !foundItem){
//Do not update order guide
isOrderGuide = false;
break;
}
}
if(isOrderGuide && foundItemCount > 0){
//If actual order guide items are included populate the order guide field
current.u_order_guide = c.current_guide;
}
} - Set up a ‘Write’ ACL on your new ‘Order guide’ field to restrict access to the field. This field should only be modified by the system as part of the ordering process so you should set up an ACL to limit those permissions. The simplest way to do this is to set up a write ACL for ‘sc_request.u_order_guide’ with the ‘nobody’ role and un-check the ‘Admin override’ checkbox.
Now when users order an item using a record producer, the record producer will be referenced in the ‘Order guide’ field you created on the request table!
Hi Mark,
I can vouch for this approach – used it with a couple of clients – I think it first appeared in a KB article (KB11261) – and well worth publishing more widely.
Brian
There’s actually a much better & safer way to do this.
The cart doesn’t get destroyed until after the request is created, so you can simply run a Business Rule on the sc_request table before the insert:
c.get('user', gs.getUserID());
current.u_order_guide = c.current_guide;
This works consistently because a user can have only one cart at a time.
This also solves a problem you’ll encounter (like I just did) when you try to run a workflow on sc_request using a condition based on the u_order_guide field you just populated.
Love it! Thanks for sharing. It’s nice to get away from modifying out-of-box code for this. I’ve updated the article above to reflect this change.
Please use the updated script I’ve provided above instead of this one (or the one in the /hi KB article). See the article above for a full explanation of why the other solutions won’t work.
Mark,
You actually helped me with this on a community forum topic – http://community.service-now.com/forum/7340
It has been working fine, but I’ve recently run into an issue with the order guide field getting populated by stand alone catalog items. It doesn’t happen every time.
I set up the ACL suggested above, but that doesn’t solve the issue. Have you seen this before? Do you know what could cause it?
I haven’t seen that, and I’m not even sure how that’s possible based on the instructions above. The field on the cart table that the guide is pulled from (current_guide) is a direct reference to the order guide table so there’s no way that a regular item could even be stored in that field. If you’ve followed the instructions above, the new ‘Order guide’ field you created is also a direct reference to the order guide table. I would check to make sure that your order guide field is really a reference to the order guide table.
I just verified that it’s set up exactly as you describe.
I don’t see it happening with non-admin users, so will keep an eye out.
Thanks.
Hi,
I am facing the same issue. Have you found a solution to tackle this problem ?
Thanks
Indu
Mark,
I was looking at my original post above and didn’t word it properly:
“It has been working fine, but I’ve recently run into an issue with the order guide field getting populated by stand alone catalog items. It doesn’t happen every time. ”
The order guide field is getting populated with the order guide. However, the service is a standalone service. (not ordered from the order guide) I have a forum topic out on the community about this, but wanted to clarify my original question.
I see what you’re saying. Any time people click on an order guide item in the catalog (even if they don’t end up completing the order guide), the order guide will be populated on the next request. The other issue is that people can work through an order guide and then delete certain contents of the request on the confirmation screen. Unfortunately, there’s not any way to guarantee that the order guide will be populated correctly 100% of the time because of these factors.
What we can do is mitigate that error by using a smarter script. I’ve created a new business rule script that you can try out (see above). The new script checks to make sure that at least one of the items from the order guide rule base is included in the order if we are populating the ‘Order guide’ field on the request. It also does a second check to verify that any order guide rule base entry with NO condition MUST be included in the order.
Even with these additional checks in place, the system behavior might still result in requests where somebody clicked on an order guide, then ordered one of the items in the guide as a standalone item instead. The best way to guard against this is to make sure you have at least one item with no conditions in the rule base, ensuring that it will always have to be part of the order if we’re going to populate an order guide.
Hi Mark,
Just thinking out loud, could this technique be used to populate the same request with user defined variables from the order guide? Although in principle that’s not what order guides should be used for but there are situations where defining variables and having that information available on the request could be very handy.
So, expanding on your last line of business rule code above:
[code]
current.u_order_guide = c.current_guide;
current.short_description = “New Employee Hire Request”;
var notes = “User details”;
notes += “\n Name ” + c.current_guide.variables.name;
notes += “\n Title ” + c.current_guide.variables.title;
notes += “\n Department ” + c.current_guide.variables.department.getDisplayValue();
current.description = notes;
[/code]
Would the above work? I’m assuming the same method can be used in referencing variables as with catalog items.
Thank you in advance 🙂
I don’t think that this would work, but it’s worth a shot. The reason I don’t think it will work is that the system doesn’t keep track of the order guide variables after it passes them to the individual items (I think). So even though you could identify the order guide you wouldn’t be able to get the variable info. As far as I know, the only way to do that is to cascade the variable info on to one or more items included by the order guide.
Sure enough it does not work. I can now verify this 🙁
As you said we don’t seem to have access to the variables in the order guide.
If you cascade the variables from the Order Guide onto the request item, you can run a workflow on the sc_req_item table against one of the Order Guide’s items with a Run Script activity that transfers the values stored in the item’s variables into the request’s Description field. The script would look something like this:
* Set values on the request from the RITM *
***************************************************/
var req = new GlideRecord(‘sc_request’);
req.get(current.request);
req.short_description = “New Employee Hire Requestâ€;
var notes = “User detailsâ€;
notes += “\n Name †+ current.variables.name;
notes += “\n Title †+ current.variables.title;
notes += “\n Department †+ current.variables.department.getDisplayValue();
req.description = notes;
req.update();
Of course, only one of the items in the Order Guide should run this workflow (otherwise it’ll end up rewriting the Description field for every item on the Request), and that item should include all of the cascaded variables from the OG that you want to include in the Request’s description field.
Thanks for sharing this Jim! I combined your comments into one with your most recent script. Nice work!
Thanks Jim. We ended up doing something very similar except instead of workflow we used a business rule.
Appreciate the response though 🙂
Hi Mark,
I have been looking at this script and wanting you use it for wizards instead of order guides. The problem I am currently facing is trying to figure out how ServiceNow is populating the field ‘current_guide’ on the shopping cart, and then possibly duplicating this functionality to cater for a Wizard.
Any tips or advice on how to go about this is appreciated.
Thanks
Reuben
I don’t know of a method to do this same thing using wizards. You might have to ask on the ServiceNow community and see if anyone has an answer there. For what it’s worth, I absolutely hate wizards because of inconsistencies and limitations like this one. I try to avoid them unless there’s no other way to meet the given requirement.
Hi Mark,
This solution is indeed very helpful. It works great with one order guide but when I tried it with multiple order guides, I got only first selected Order Guide. Is it possible to make order guide field a simple string field (and not a reference field) and add multiple order guides to this field with a delimiter?
Thanks,
Tapish
Thanks. Unfortunately, that’s not possible because of the way that ServiceNow stores the order guide reference on the cart. It only stores one at a time.
Mark, this works great initially but unfortunately there is an issue I discovered. If the user only go to the “Choose option” portion of the order guide and not submit it all the way, it will add the sc_cart_item table and leave it there. Later on if the user go to a stand alone catalog item and submit that one, this business rule still thinks coming from that order guide and ties that new stand alone request to the Order guide mistakenly. I’m debating whether we should a condition on this business rule to detect to update only if its coming from an order guide? Or should we nuke the order guide cart at the start of every standalone item?
The problem is that ServiceNow doesn’t really give you a good way to prevent this type of situation with the cart setup. The logic I’ve created makes this a rare occurrence because it checks to make sure at least one of the order guide items is included in the cart at the time of the order. I’m not sure of a better way to handle this right now.
Hello Mark,
This is a nice way but still I feel that order guides are missing functions, especially when it comes to bundles. I created two useful scripts relating to order guides and their behavior in the Service Catalog. If you could have a look into it and tell me what you think that would be great. I created two discussions in the servicenow community:
https://community.servicenow.com/thread/164434
https://community.servicenow.com/thread/164465
Michael,
Although I really haven’t come across either of these situations personally, I think they could both be very useful in the right situation. It will be good to get them out and have a few people test them to see if any changes need to be made. Thanks for sharing!
I’m wondering if something may have changed with Eureka here. I no longer have an earlier release to fiddle with. As it stands now, if a user goes into an order guide, up to the point where they can see the tabs for each item without checking out, and then returns to the regular service catalog to order an item, the items from the guide remain in sc_cart_item but are not visible in the user’s cart. They are removed by the system sometime after the sc_request item is created, as they can still be accessed by business rules that run on sc_request. Unfortunately this breaks the script above.
I was attempting to use this as a way to implement an approval process for items ordered separately but not through order guides. Since there is a loophole happening by having ghost sc_cart_item entries just by visiting the order guide, the entire approval process can be bypassed.
Any advice would be very much appreciated!
Nate, there is an ‘active’ field in sc_cart_item. You’ll find that the order guide itemsto the cart added at the point of clicking “Choose Options” but are false until you click checkout. Just add the line ‘itm.addActiveQuery();’ to the populate order guide business rule before ‘itm.query();’
Hi Mark,
I see your note about this being discontinued with Helsinki…..do you have any suggestions for a new solution? Also, just curious, what changed with Helsinki that breaks this.
Thanks, Bryan
Nothing gets broken with Helsinki, and this solution will still work. It’s just not necessary in Helsinki because ServiceNow tracks it for you.
O ok, awesome thanks. We’re currently using this on Helsinki and I think we’re seeing some of those exceptions where it’s not captured 100% of the time. How is SN tracking it now in Helsinki?
I don’t know the specifics of how they’re recording it, but I know that they’ve added an ‘Order Guide’ field as indicated at the top of this article to store that value in.
Ah, I found it (https://docs.servicenow.com/bundle/helsinki-it-service-management/page/product/service-catalog-management/task/t_OrderProcess.html) Now I just need to figure out how to write that back up to the Request before insert. Should be do-able. Thanks as always.
I think you might still be confused. You shouldn’t have to do anything at all to get it to work. ServiceNow should already have the code in place and the field to record the value in. If it’s not working in a Helsinki system then you should contact ServiceNow support to fix it for you.
Hey Mark,
SN currently has a problem logged where the OOB order guide field on sc_req_item is not being set when the order guide is accessed through the Service Portal; their intended fix isn’t scheduled until Jakarta at this point…
As a result, I tried to use the solution here and it does not do the trick when ordering in the Service Portal. Any idea why? Could it be related to current_guide? In the classic UI, the business rule fires and populates the field.
Kindly,
Alex
I’d check your error logs to see if there are any errors or warnings associated to having that script run. I’d guess that the issue is that the business rules aren’t being processed at all. You could verify that by changing it so that it did nothing more than log out to the system log.
I was logging in the business rule and I know it was running. By logging at several parts, I know it was not getting into the GlideRecord query. I think this is because the Service Portal (at least on Helsinki) does not use a cart concept and so the GlideRecord of sc_cart is not applicable.
For now, I went a different route. I am using it for an Application Access order guide and every item has the same variable set. As such, I’m using a shared variable to store the value and then firing a business rule to populate it on the sc_req_item table.
Thanks for taking a look,
-Alex