Select specific attachments to copy

Rob Sestito
Mega Sage

Hey SN Comm,

I have a couple of things that I want to see if they can be enhanced. For my first one, we have a UI Action that grabs the attachments from the HR Case, and posts them to the HR Task: (this is in production)

find_real_file.png

GlideSysAttachment.copy(current.parent.sys_class_name, current.parent, current.getTableName(), current.sys_id);

current.update();
action.setRedirectURL(current);

gs.addInfoMessage("Attachments have been added!");

gsftSubmit(null, g_form.getFormElement(), 'sysverb_update_and_stay');

Then, I have a Business Rule to do the following (which is NOT in production yet): This BR automatically allows the case worker, to have the attachments added to the email (from email client) from the Case/Task (depending on which table I give as the target).

find_real_file.png

(function executeRule(current, previous /*null when async*/) {
	//gs.log('M in loop');
	
	// Add your code here
	var lookatt=new GlideRecord('sys_attachment');
	lookatt.addQuery('table_sys_id',current.instance);
	lookatt.query();
	while(lookatt.next())
		{
		//	gs.log('M in loop again');
		GlideSysAttachment.copy('sn_hr_core_case_operations', current.instance, 'sys_email', current.sys_id);
	}
})(current, previous);

I really want to see if there is a way, at least for the UI Action,'Grab Attachments', to make my options selectable. I think it would be really beneficial to be able to do that with these features.

Anyone able to see/or know if this is possible at all?

Thanks in advance!

-Rob

1 ACCEPTED SOLUTION

Hi Rob,

 

Yeah I was able to replicate the issue in my Personal Development instance as well. Took me a while and have updated the Business Rule. Just update your Business Rule as per the script mentioned below. 

(function executeRule(current, previous /*null when async*/) {
	
	// Add your code here
	var tic_num = '';
	var sub =  current.subject;
	var number = sub.replace(/[^\d.]/g,'');//current.subject.toString().substr(0,10);
	var num = number.substr(0,7);
	var num2 =sub.indexOf(num);
	if(num2 > 3)
	   tic_num = sub.substr(num2-3,num.length + 3);
	else
	  tic_num = sub.substr(0,num.length + num2);
	var ticket_number = tic_num.replace(/\s/g,'');
      // The first 14 characters of the subject are the ticket number. 
      // We need to subtract this number to get the sys_id of the task record.

     var gr = new GlideRecord('incident');  //Replace with your Table Name from which you want to copy to Email Client
     gr.addQuery('number',ticket_number);
     gr.query();
     gr.next();
     
     var arrayAttachment = GlideSysAttachment.copy(gr.sys_class_name, gr.sys_id ,'sys_email', current.sys_id);

     for (var i = 0; i< arrayAttachment.size(); i++) { 
             var attachmentSidsPiece = String(arrayAttachment.get(i)).split(',');
             var sourceAttachmentSysid = attachmentSidsPiece[0];
             var targetAttachmentSysid = attachmentSidsPiece[1]; 
             var sourceRec = new GlideRecord('sys_attachment');
             var targetRec = new GlideRecord('sys_attachment');

     if (sourceRec.get('sys_id',sourceAttachmentSysid) &&       
                               targetRec.get('sys_id',targetAttachmentSysid)) {

       if (sourceRec.u_send_to_email_client==false) {
            //delete all other attachments that are not marked to send via the email client        
            targetRec.deleteRecord();

     } else { //reset the flag
           sourceRec.u_send_to_email_client= false;
           //as soon as the email record is created, reset the flag to false again
           sourceRec.update();
    }
 }
}
	
})(current, previous);

Rest of the code remains the same. Hopefully this time it should work:) 

 

Please let me know if still there is an issue and we can check further.

 

Hope this help. Please mark the answer as helpful/correct based on impact.

 

Regards,

Shloke

Hope this helps. Please mark the answer as correct/helpful based on impact.

Regards,
Shloke

View solution in original post

32 REPLIES 32

Brandon Barret1
Mega Sage

Hi Rob, This sounds like an interesting use case and I want to be sure I understand: you want your users to be able to select specific attachments to add to the emails they send out?

This post, although dated, seems like it could be relevant:

https://www.google.com/amp/s/blogs.dxc.technology/2016/12/23/select-attachments-from-the-underlying-task-record-in-servicenow-and-send-them-via-the-email-client/amp

This post also discusses copying specific attachments, although I’m not sure whether the information is of any help. It still may be worth a look.

https://community.servicenow.com/community?id=community_question&sys_id=a73f4be1dbdcdbc01dcaf3231f961986

Have you had any luck or made any progress on this? Wish I could be of more help.

Hey Brandon,

Thank you for the information and links - I will check these out along with shloke's post below!

Cheers,

-Rob

shloke04
Kilo Patron

Hi Rob,

 

First link posted by Brandon still works. But the solution I think is not complete with couple of  challenges I faced was like  the Script Include portion missing where you are expected to do a Synchronous Ajax call is missing for which I struggled a bit and also the Business rule logic looked complicated to me so tweaked it accordingly as per my convenience and then finally made it to work:

 

I have listed all the steps needed in short with code and results as well which might be helpful, you can also refer to the original post as well which ever looks simple to you:):

 

1) Create a New Field of type "True/False" called "Send to Email Client(u_send_to_email_client)" on the Attachment table and have the default value as False.

2) Create a UI Page and name it as "Email_Client_Attachments" and have the script as listed below:

 

HTML:

<?xml version="1.0" encoding="utf-8" ?>
<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
<j:set var="jvar_sysid" value="${sysparm_sys_id}"/>
<g:evaluate var="jvar_att" jelly="true" object="true">
    var arr =  [];
                var records = [];
                var att = new GlideRecord("sys_attachment");
                att.addEncodedQuery("table_sys_id=" + jelly.jvar_sysid);
	             att.orderBy("file_name");
                att.query();
                while(att.next())
                {
                  arr.push(att.file_name.toString());
                  records.push(att.sys_id.toString());
                }
	            
                var arr1 = '';
                var records1 =  '';
                for(var i=0;i&lt;arr.length;i++)
                  {
                     if(i == 0)
                          records1 = records[i];
                      else if(arr[i] != arr[i-1])
                        {
	
                      }
      }
	           
                var att1 = new GlideRecord("sys_attachment");
                att1.addEncodedQuery("sys_idIN" + records1);
                att1.query();
                att1;
</g:evaluate>
<j2:if test="${jvar_att.hasNext()}">
<j:while test="${jvar_att.next()}">
<g:ui_checkbox name='related_attachment:${jvar_att.getValue("sys_id")}' value='${jvar_att.getValue("file_name")}' class='attachment_checkbox'>${jvar_att.getValue("file_name")}</g:ui_checkbox><br/>
                </j:while>
                </j2:if>
                <br/>
                <button onclick="myFunctionSubmit()">Ok</button>
                <button onclick="myFunctionCancel()">Cancel</button>
</j:jelly>

 

Client Script:

 

function myFunctionSubmit(){
	var x = $$('.attachment_checkbox[value=true]'); //array of the checkbox elements
	if(x.length == 0)
		{
		alert("Please select an attachment");
		return false;
	}
	else if (x.length > 0)
		{
		var list_of_attchs_ids = '';
		var attch_name  = '';
		for (var j=0; j< x.length; j++) {
			//get the sys_id of the attachment from the checkbox element name
			attch_name  = x[j].name.split(':');
			if (list_of_attchs_ids=='')
				list_of_attchs_ids = attch_name[1];
			else
				list_of_attchs_ids = list_of_attchs_ids + ','+ attch_name[1];
		}
		var ajax = new GlideAjax("getAttachmentLists");
		ajax.addParam("sysparm_name","updateAttachmentList");
		ajax.addParam("sysparm_attachmentsysid",list_of_attchs_ids);
		ajax.getXMLWait();
	}
	var ticket_id = g_form.getUniqueValue();
	var table_name = g_form.getTableName();
	var newURL = 'email_client.do?sysparm_table=' + table_name + '&sysparm_sys_id='+ ticket_id +'&sysparm_target=' + table_name + '&sys_target=' + table_name + '&sys_uniqueValue=' + ticket_id +
	'&sys_row=0&sysparm_encoded_record='; //build the URL of the email client window
	//alert(newURL);
	popupOpenEmailClient(newURL); //opens the email client
	
	GlideDialogWindow.get().destroy(); //to automatically close the window
}


function myFunctionCancel()
{
	GlideDialogWindow.get().destroy();
}

 

3) Now Create a Script Include name "getAttachmentLists" and make it a Client Callable one available from All Application Scopes as shown below:

 

var getAttachmentLists = Class.create();
getAttachmentLists.prototype = Object.extendsObject(AbstractAjaxProcessor, {

updateAttachmentList: function()
{
	var attach_sys_id = this.getParameter("sysparm_attachmentsysid");
	var att = new GlideRecord("sys_attachment");
	att.addEncodedQuery("sys_idIN" + attach_sys_id);
	att.query();
	while(att.next())
		{
			att.u_send_to_email_client = true;
			att.update();
		}
	return "Success";
},

    type: 'getAttachmentLists'
});

 

4) Now create a UI Action named "Copy Attachments(Change it if you don't like the name:)" and select the Table on which you want this functionality on. I have done this for Task Table as shown below:

function copyAttachments(){
	var gdw = new GlideDialogWindow('Email_Client_Attachments');
	gdw.setTitle('Please select the Attachments to Copy to Email Client');
	gdw.setSize(450,300);
	gdw.setPreference('sysparm_sys_id', g_form.getUniqueValue()); // Our task record ID
	gdw.render();
}

 

find_real_file.png

 

5) Finally create a Before Insert Business Rule named "Copy Attachment to Email Client" written on the Email(sys_email) table with condition as "Type is send-ignored" and use the below script:

 

(function executeRule(current, previous /*null when async*/) {
	
	// Add your code here
	var ticket_number = current.instance.number.toString();
	var gr = new GlideRecord('task');  //Change the Table Name accordingly and query as well based on table selected
	gr.addQuery('number',ticket_number);
	gr.query();
	gr.next();
	var arrayAttachment = GlideSysAttachment.copy(gr.sys_class_name, gr.sys_id ,'sys_email', current.sys_id);
	
	for (var i = 0; i< arrayAttachment.size(); i++) {
		var attachmentSidsPiece = String(arrayAttachment.get(i)).split(',');
		var sourceAttachmentSysid = attachmentSidsPiece[0];
		var targetAttachmentSysid = attachmentSidsPiece[1];
		var sourceRec = new GlideRecord('sys_attachment');
		var targetRec = new GlideRecord('sys_attachment');
		
		if (sourceRec.get('sys_id',sourceAttachmentSysid) &&
			targetRec.get('sys_id',targetAttachmentSysid)) {
			
			if (sourceRec.u_send_via_email_client==false) {
				//delete all other attachments that are not marked to send via the email client
				targetRec.deleteRecord();
				
			} else { //reset the flag
				sourceRec.u_send_to_email_client= false;
				//as soon as the email record is created, reset the flag to false again
				sourceRec.update();
			}
		}
	}
	
})(current, previous);

 

Screenshot for reference:

find_real_file.png

 

 

find_real_file.png

 

 

And Finally the Result looks like below:

 

find_real_file.png

 

Click on the Button and it gives you an option to select the Attachments you want to copy to Email Client

 

find_real_file.png

 

Click on OK Button and it takes you to Email Client with the Attachment selected being copied:

 

find_real_file.png

 

 

Hope this help. Please mark the answer as helpful/correct based on impact.

 

Regards,

Shloke

Hope this helps. Please mark the answer as correct/helpful based on impact.

Regards,
Shloke

This is GREAT information!

Thanks for sharing - I will get to working on this today and let you know of any issues/results I get!

Cheers,

-Rob