‘Copy’ UI action for Change requests

///‘Copy’ UI action for Change requests

‘Copy’ UI action for Change requests

I

often see clients request the ability to copy task records.  There are a variety of ways to implement copying functionality and each method has its trade-offs.  Templates, a checkbox field combined with a business rule, or even activating the ‘Insert’ UI action buttons for the task table are all methods that I’ve seen.

In my experience, the best method is to create a brand new UI action button on the table in question.  Below is a script I created to add a ‘Copy’ button to the ‘Change request’ form. This script should be pretty complete for most implementations.  You may just have to customize a few lines to copy over the appropriate fields.  The main advantage that this script has over other methods is that it also copies all of the ‘Affected CI’ records, Change tasks, and attachments for both the Change request and all Change tasks.

To see some other examples of copy UI action methods click here.
Copy Change UI action
Name: Copy change
Form button: True
Table: Change Request
Condition: gs.hasRole(“itil”) && current.isValidRecord()
Script:

var chgID = current.sys_id.toString();
var newChange = new GlideRecord('change_request');
newChange.initialize();
newChange.short_description = current.short_description;
newChange.requested_by = current.requested_by;
newChange.category = current.category;
newChange.type = current.type;
newChange.assignment_group = current.assignment_group;
newChange.assigned_to = current.assigned_to;
newChange.description = current.description;
newChange.risk = current.risk;
newChange.urgency = current.urgency;
newChange.implementation_plan = current.implementation_plan;
newChange.test_plan = current.test_plan;
newChange.backout_plan = current.backout_plan;
newChange.insert();

//Copy attachments for this change
if (typeof GlideSysAttachment != 'undefined')
   GlideSysAttachment.copy('change_request', chgID, 'change_request', newChange.sys_id);
else
   Packages.com.glide.ui.SysAttachment.copy('change_request', chgID, 'change_request', newChange.sys_id);
copyTask();
copyCI();
gs.addInfoMessage('Change ticket ' + newChange.number + ' created.')
action.setRedirectURL(newChange);

function copyTask() {
//Find the current change tasks and copy them
var tasks = new GlideRecord('change_task');
tasks.addQuery('change_request', current.sys_id);
tasks.query();
while(tasks.next()){
var taskID = tasks.sys_id.toString();
//Copy the task record to a new task record
var newTask = new GlideRecord('change_task');
newTask.initialize();
newTask.change_request = newChange;
newTask.order = tasks.order;
newTask.short_description = tasks.short_description;
newTask.description = tasks.description;
newTask.assignment_group = tasks.assignment_group;
newTask.assigned_to = tasks.assigned_to;
newTask.insert();

//Copy attachments for this task
if (typeof GlideSysAttachment != 'undefined')
   GlideSysAttachment.copy('change_task', taskID, 'change_task', tasks.sys_id);
else
   Packages.com.glide.ui.SysAttachment.copy('change_task', taskID, 'change_task', tasks.sys_id);
}
}

function copyCI() {
//Copy over the affected CI list
var currentCI = new GlideRecord('task_ci');
currentCI.addQuery('task', current.sys_id);
currentCI.addNullQuery('u_ci_group'); //Added to ensure that copying does not duplicate Group CIs
currentCI.query();
while(currentCI.next()){
var newCI = new GlideRecord('task_ci');
newCI.initialize();
newCI.task = newChange.sys_id;
newCI.ci_item = currentCI.ci_item;
newCI.insert();
}
}
By | 2018-07-09T15:01:34-06:00 December 22nd, 2009|Categories: UI actions|Tags: , , |20 Comments

About the Author:

20 Comments

  1. Sabrina Ethridge May 10, 2010 at 1:17 am - Reply

    This is great… Thanks. Is there something that I could add to this UI Action that would bypass any missing required fields during the copy process? This code appears to try to save the current change prior to making the copy.

  2. Ashutosh June 20, 2010 at 5:25 am - Reply

    Hi..this is awesome, Thanxx a ton..! but unfortunate this is not my current requirement!

    My requirement is to relate multiple problem tickets with one Change request record..however currently one PRBXXX is related with one CHGXXX record.

    I have found UI action, and business rule where changes need to make, but not able to get different logics..

    Any ideas to get this done !

    • Mark Stanger June 21, 2010 at 1:51 am - Reply

      Out of box, a problem can be related to a single change request, but a change request can be related to many problem tickets. Any time you have a reference field on a form, it represents a one-to-many relationship with the table it references. With problem-change, you have a reference field on the problem form, and a related list on the change form. You need to personalize the change request related lists and add the problems list.

  3. Scott Hetzel July 23, 2010 at 8:28 am - Reply

    Hi Mark,

    Is there a way to do this exact action but not automatically insert the record. Require the user to submit after filling out some Change Request specific fields on the new record which is displayed after pressing the UI Action?

    Thanks – Scott

    • Mark Stanger July 23, 2010 at 10:56 am - Reply

      There isn’t with this method. There is another way of doing the same thing that would allow you to select a change request to copy from (from a reference field). If you were to use this method, then you could put that field on a change request form with the few fields you needed to override, require those fields to be filled in, and then copy those values over the newly-created change.

      I’ve been meaning to post that method for a while. I’ll try to post it next week.

      • Scott Hetzel July 26, 2010 at 6:04 am - Reply

        Thanks for the info and Help!

        • Mark Stanger July 27, 2010 at 4:43 am - Reply

          No problem. Here’s a link to the article describing the other methods.
          https://www.servicenowguru.com/system-ui/ui-action

          • Scott Hetzel August 16, 2011 at 10:15 am - Reply

            Mark – do you know how I could change your code to NOT insert the record until the required fields are filled out by user? (similar to how the Global ‘New’ UI Action works)

            My problem is people will copy a Change with my UI Action, then close out their browser or navigate to another area of ServiceNow and not fill in my required fields..

            Thx..

  4. Mark Stanger August 16, 2011 at 10:20 am - Reply

    @scott – You can do a change copy without an insert, but you have to pass all of the information over the URL in a ‘sysparm_query’ parameter and then redirect the user to the URL in order to make it work. With a full record copy, that’s usually way too much information to handle that way. If you want to give it a try, you can construct your URL as shown here…

    https://www.servicenowguru.com/service-now-general-knowledge/populating-default-values-url-module/

    • Scott Hetzel August 16, 2011 at 1:04 pm - Reply

      I’m going to recommend we enforce policy/procedures (let the wrist slapping begin!) Thanks Mark for the info..

  5. Dave March 27, 2012 at 12:34 pm - Reply

    When such a UI action is executed my browser shows and error – “current not defined”, and nothing is written to the record I initialized.

    • Mark Stanger March 27, 2012 at 3:29 pm - Reply

      I’m not sure what might be the issue. These scripts have been tested and verified before. Please try copying and pasting from here and testing in a ServiceNow demo instance.

  6. Brian August 16, 2013 at 9:51 am - Reply

    Hello Mark. The script is absolutely perfect and I love it. One question or maybe just guidance…..In our organization, we have the user first specify what type of change they are creating. This is using an interceptor. We have separate work flows for each change type. It is common for a user to create an Emergency Change when they should have created an Urgent change. We also make the Change Type read only to keep the user from selecting one type and changing it to another and possibly bypassing parts of our process.

    My question is, how can I incorporate this script but allow the user to select the Change Type so that the appropriate work flow is associated.

    Thanks again.

    • Mark Stanger August 16, 2013 at 11:05 am - Reply

      There are ways to do that, but it’s actually fairly complicated. I’ve seen some discussions on the ServiceNow community about this, but haven’t really seen anything that covers all of the bases outside of what we do at Crossfuze in our turnkey change product.

      We allow the user to do 2 things. The first is that they can change the ‘Type’ field as long as the change is in a draft state. This allows for some flexibility in selecting the change type before you get into the full workflow. The second thing we’ve done is create a custom interceptor concept that routes the user to an intermediate record producer form that allows us to ask for details about the change…type, etc. before actually creating the change. Since it’s a part of our proprietary code base, I can’t share the details, but I would be willing to do a demo of the solution for you if you’d like to take a look.

  7. Masha August 29, 2013 at 5:15 pm - Reply

    Thank you Mark for the helpful script!

    Here are the corrections that I had to make for this script to work as intended:

    – When setting the change_request on the new task, a sys_id of the task should be used:
    ==> newTask.change_request = newChange.sys_id;

    – In the code for copying task attachments the second sys_id should be of the new task:
    if (typeof GlideSysAttachment != ‘undefined’)
    GlideSysAttachment.copy(‘change_task’, taskID, ‘change_task’, newTask.sys_id);//Calgary and up
    else
    Packages.com.glide.ui.SysAttachment.copy(‘change_task’, taskID, ‘change_task’, newTask.sys_id);//pre Calgary

    Thank you again!

  8. KabirS August 12, 2014 at 7:08 am - Reply

    Any way to copy the varaible information as well if it was generated via a Record Producer. Currently variable information not copied over.

    • Mark Stanger August 12, 2014 at 8:43 am - Reply

      This can certainly be done, you would need to perform a query against the ‘question_answer’ table using a similar routine to the one found in the sample script above and perform inserts of any records found.

      • KabirS August 12, 2014 at 8:57 am - Reply

        Thanks Mark for the quick reply. I thought that would be the case as well and wondered if there was any other quick way of doing this. Will give this a try 🙂

  9. Steve H December 2, 2014 at 9:29 am - Reply

    Mark,
    This works great on smaller changes, but we have run into an issue where we bump up against the UI transaction quota limits when we have many CI’s associated with the change. In our test example, we had 365 related CI’s and only were able to copy about 340 before it timed out.
    Any suggestions on how to avoid this?

    • Mark Stanger December 2, 2014 at 6:04 pm - Reply

      Hi Steve, I’m not sure how you could deal with that. You’ll probably need to contact ServiceNow support to investigate.

Leave A Comment