Interested in a ServiceNow event built for developers? Registration for now[dev]26 is officially open!

How to copy attachment from sctask to ritm

Praveen94
Kilo Contributor

How to copy attachment from sctask to ritm

1 ACCEPTED SOLUTION

Ankur Bawiskar
Tera Patron

Hi Praveen,

I assume you want attachment to be copied over from SC Task to RITM when attachment is added

sample BR on sys_attachment; It would be copying all attachments to RITM from SC TASK

BR: after insert on sys_attachment

Condition: current.table_name == 'sc_task'

Script:

var taskRec = new GlideRecord('sc_task');

taskRec.addQuery('sys_id', current.table_sys_id);

taskRec.query();

if(taskRec.next()){

var ritmRec = new GlideRecord('sc_req_item');

ritmRec.addQuery('sys_id',taskRec.request_item);

ritmRec.query();

if(ritmRec.next()){

GlideSysAttachment.copy('sc_task', current.table_sys_id, 'sc_req_item', ritmRec.sys_id);

}

}

Regards
Ankur

Regards,
Ankur
✨ Certified Technical Architect  ||  ✨ 10x ServiceNow MVP  ||  ✨ ServiceNow Community Leader

View solution in original post

20 REPLIES 20

Hi Ankur,

 

Every time BR runs duplicate attachment is attaching to RITM as per provided script.

Step 1: attaching to sctask update to Ritm

Step2: Again attaching different attachment to same sctask again it's copying all attchments to RITM.

 

Thanks

Praveen

 

 

Here is the code I use for the same purpose, use it in the script section and set the condition as current.request_item.cat_item == 'sys ID of your item'

 

moveRitmAttachments();

function moveRitmAttachments() {
    var attachmentGr = new GlideRecord('sys_attachment');
    attachmentGr.addQuery('table_name','sc_task');
    attachmentGr.addQuery('table_sys_id',current.sys_id);
    attachmentGr.query();
    while (attachmentGr.next()) {
	attachmentGr.table_name = 'request_item';
	attachmentGr.table_sys_id = current.sys_id;
	attachmentGr.update();
    }    
}

 

If my reply has helped in any way, kindly mark it correct/helpful. Thanks!

Hi Praveen,

please delete older attachments and then fresh copy all

updated script for both the questions


var taskRec = new GlideRecord('sc_task');

taskRec.addQuery('sys_id', current.table_sys_id);

taskRec.query();

if(taskRec.next()){

var ritmRec = new GlideRecord('sc_req_item');

ritmRec.addQuery('cat_item.name', 'YOUR CATALOG ITEM NAME HERE');

ritmRec.addQuery('sys_id',taskRec.request_item);

ritmRec.query();

if(ritmRec.next()){

// delete all RITM Attachments before copy

var att = new GlideRecord('sys_attachment');
att.addQuery('table_sys_id', ritmRec.sys_id);
att.query();
att.deleteMultiple();

GlideSysAttachment.copy('sc_task', current.table_sys_id, 'sc_req_item', ritmRec.sys_id);

}

}

Regards
Ankur

Regards,
Ankur
✨ Certified Technical Architect  ||  ✨ 10x ServiceNow MVP  ||  ✨ ServiceNow Community Leader

Hi Ankur,

Is there a way to retain the attachments in the RITM? Currently the code is replacing all the attachments in the RITM from the sctask. Thank you

Regards,

Raph

Why Duplication Happens

The GlideSysAttachment.copy('source_table', 'source_sys_id', 'target_table', 'target_sys_id') method is designed to copy all attachments associated with the source record to the target record. Because the Business Rule triggers after insert on the sys_attachment table, it runs every single time a single new attachment is uploaded. When it triggers, GlideSysAttachment.copy() runs and copies the entire batch of attachments currently on the SCTASK over to the RITM.

  • First Upload (A.1): A.1 is uploaded. The BR copies all attachments on SCTASK (which is just A.1) to RITM. RITM has: [A.1].
  • Second Upload (A.2): A.2 is uploaded. The BR triggers again and copies all attachments currently on SCTASK (which is now A.1 and A.2) to RITM. RITM has: [A.1] + [A.1, A.2] = [A.1, A.1, A.2].

 

Solution 1: Use writeContentStream() (Recommended Best Practice)

Instead of copying the entire record's attachment payload, you can copy only the specific attachment currently triggering the rule (current).

Since the Business Rule is on sys_attachment and triggers after insert, "current" represents the single, newly-added attachment. By utilizing GlideSysAttachment's stream-writing methods, you can copy just that individual file to the parent RITM.

 

Updated Script:

(function executeRule(current, previous /*null when async*/) {

    // 1. Get the parent SCTASK record using the attachment's table_sys_id
    var taskRec = new GlideRecord('sc_task');
    if (taskRec.get(current.table_sys_id)) {

        // 2. Query the parent RITM record
        var ritmRec = new GlideRecord('sc_req_item');

        if (ritmRec.get(taskRec.request_item)) {

            // 3. Copy ONLY the current newly inserted attachment
            var gsa = new GlideSysAttachment();
            gsa.writeContentStream(

                ritmRec,
                current.file_name,
                current.content_type,
                gsa.getContentStream(current.sys_id)

            );
        }
    }

})(current, previous);

 

Hope this helps!

 

References:
https://www.servicenow.com/community/itsm-articles/copying-attachment-from-one-record-to-another-rec...

https://www.servicenow.com/community/servicenow-impact-forum/copy-attachment-from-sc-task-to-ritm/m-...

https://www.servicenow.com/community/itsm-forum/copy-attachment-from-scatsk-to-ritm/td-p/3357029