Record producers are a great piece of ServiceNow functionality that allows for the creation of records in any table via the standard Service Catalog interface. This capability has been around for quite a while and odds are that you’re already using it in your system to allow end-users to create new incidents…among other things.
Over the years I’ve worked with ServiceNow, I’ve seen several requests to be able to report on or identify the record producer used to create a particular record. This would allow for easier identification of the entry point for record producer transactions. Unfortunately, ServiceNow doesn’t give us a simple way of accomplishing this. Even though there is a record producer ‘Script’ field and a ‘producer’ script object to work with, nothing is built to be able to dynamically identify the record producer used. This means that you’re stuck hard-coding values in a script or adding unnecessary variables to your record producer forms for every single record producer in your system. Read on for a fairly simple solution to this problem!
This configuration can be accomplished in a few simple steps as shown below…
- Create a new field to store the value of the record producer used.
We’ll want to store the record producer value on each target record that is created. As such, you’ll need a field to store that value in. I think the best solution is simply to create a new reference field referencing the ‘Record producer’ [sc_cat_item_producer] table named ‘Record producer’ [u_record_producer] on the ‘task’ table. That way, you can have one shared field that will be available to almost everything that you’ll usually use with record producers. If you’ve got additional tables that don’t extend ‘task’, just repeat the same step there as well.
- Create a new business rule on the ‘Record Producer [sc_cat_item_producer]’ table.
The purpose of the business rule is to overcome the issue this article is about. We do this by leveraging the record producer ‘Script’ field to populate the ‘Record producer’ [u_record_producer] field created in the previous step. The business rule simply populates the record producer sys_id value into the record producer ‘Script’ field every time the record producer is inserted or updated and then the standard record producer script/creation process takes over and writes the producer Sys ID to the field per normal operations. If you need this to work for non-task tables, you can simply create a duplicate business rule there.
Name: Force population of record producer used
Table: Record producer [sc_cat_item_producer]
When: Before
Insert: True
Update: True
Advanced: True
Order: 1100
Condition: current.script.indexOf(‘Force population of record producer’) == -1
Script:
by modifying the script field entry on the record producer. Record producer will be
populated in a reference field on the target record named 'u_record_producer' (which
will need to be created).***/
current.script = current.script + '\n\n\n' + '/***DO NOT REMOVE OR MODIFY THIS SECTION!!! Automatically added by "Force population of record producer used" business rule. \nForces population of this record producer sys_id into the target record for reporting purposes.***/\n' + 'current.u_record_producer = ' + '"' + current.sys_id + '";';
Please note that you will need to manually update every record producer in the system that you want this to work with in order for the producer script to be updated as necessary!
If you’ve done all of the above steps correctly, you should end up with a nicely-populated ‘Record producer’ reference field on each generated record. This value can then be used for reporting or other purposes in your system!
Great addition but a bit more info could be needed.
What type of a field should the “Record producer” be? I created a string just to get it created but I assume it should be something else since only the sys_id will be displayed in that field otherwise (no reference).
There is also a ; missing in the end of the business rule (at least I had to add it to get it to work)
Thanks for the feedback! You can store the reference field value in any field type, but I think a reference field is best. I’ve added that to step 1 to clarify. I’ve also added a semicolon to the script.
Hey, that’s a good idea. I stumbled across another way recently.
If you put this as a business rule, it’ll pick up what you submit using the sysparm_action parameter in the glideuri map.
Worth putting error handling in there, but the basis is there.
if (map.get('sysparm_action') == 'execute_producer' && map.get('sysparm_id') ) {
current.u_producer = map.get('sysparm_id');
}
Nice, I wasn’t aware of this. I can see advantages to both approaches. Your method avoids having to populate anything in the record producer at all, but you’ve got to have a business rule on each target table. My method does everything within the record producer itself, but admins could break the code if they don’t pay attention to what they’re doing. Good to have a couple of choices!
Absolutely. More than one way to skin a cat 🙂
Is there a reason that code won’t work on a base task business rule? Why does the rule have to exist for every target table if its hte same code each time?
Great point. Add to that the fact that you probably don’t care about this for non-task tables and Ahmed’s solution ends up being very simple to implement. I like this better than what I have, I’ll update the article above.
Getting the following error:
ERROR at line 3: Expected ‘)’ to match ‘(‘ from line 3 and instead saw ‘;’.
My line 3 is the if statement ending with the opening curly brace. Seems to be barfing once it gets to the first &
Check out my updated script above. That should be just what you need.
Yeah I switched to raw ampersands as an experiment and it worked fine.
Fantastic, this is exactly what I needed to give the users visibility into which type of Service Creator task (in a category) they were seeing in a list.
The service creator-created record producer puts it at the beginning of the short description, but this solution gives us an actual field, very nice!
Thanks Sue! I’m glad it helped.
Hi Mark,
Again a great solution. Just curious, where did you find “gs.action.getGlideURI().getMap()” this method documented on Wiki. I search the glide system class documentation but could not spot it??
Thanks
I think it was just posted here. I don’t think it’s been documented anywhere and I haven’t seen any other use for it other than this.
For a beginner like me, it was not obvious that I should have checked the “insert” on the business rule. Couldn’t get it to work at first, but it does now.
Thanks!
Hi!
It seems like this code doesn’t work on the new Service Portal? Anyone found a workaround for that?
You’re right! Must be some limitation with the Service Portal API. Fortunately, I previously had a solution that worked just as well, and is compatible with service portal. I’ve updated the instructions above. You’ll need to remove the current business rule and add a new one to the Record producer table as described above. Then you’ll need to force an update to all of your record producer records that you want this to work with so that the customization will take effect.
Hey Mark,
I wanted to post an easy way to do it . We can use var rpID = RP.getParamaterValue(‘sysparm_id’); and use it in producer script to set it in target reference field created on incident/change or any target record.
It worked for me 🙂
Thanks,
Masoom Sharma
Thank you!
I have found that the record producer GlideRecord is available as a global object in the producer script.
The object reference is “cat_item”.
So you can get the sys_id of the record producer very easily using cat_item.sys_id
So for example…
current.u_record_producer = cat_item.sys_id;
Thank you!!
Thanks James! .. your suggestion worked perfectly!