This article is relevant if you want to automatically add an attachment to a NetSuite email message object.
Background
We are solving a number of client challenges with our Content Renderer Engine (CRE) which allows you to get much more data to a NetSuite Advanced PDF or HTML template. In many cases, because of the power of this tool, we are replacing the conventional Advanced PDF invoice and other standard transactional objects. Our CRE tool allows you to flexibly create file and email output. A client recently wanted to preserve the native NetSuite message object but they wanted all the goodness of CRE. In this case, they wanted a simple way to ensure that a file attachment was added to the native NetSuite message object so that users could have freedom to craft their own email yet ensure they have branded content as a file attachment.
SuiteScript 1.0 Pattern to Add Attachment to NetSuite Message
The following code pattern can be used as inspiration for any message object that needs a file attachment. At the same time, it illustrates how, with just a few lines of code , you can generate CRE profile based content. In addition, see the code pattern to turn off and hide NetSuite’s default message behavior which will add a transaction attachment.
//------------------------------------------------------------------------------ //Function: cre_EmailTemplate_BeforeLoad //Record: message //Type: BeforeLoad //Description: On the related transaction, generate the cre attachment and // add as attachments to current message //------------------------------------------------------------------------------ function cre_EmailTemplate_MsgBeforeLoad(type, form, request) { //check proper context if (type != 'create') return; var context = nlapiGetContext(); if (context.getExecutionContext() != 'userinterface') return; if (!request) return; // get the query string parameters; this message example only works with transactions // ne is a custom function to return back a value if an expression returns back empty var recid = ne(request.getParameter("transaction"),''); if (recid.length == 0) return; //here, we have a custom script parameter holding a JSON structure binding transactions //to specific types of CRE profile templates. var rectype = nlapiLookupField('transaction', recid, 'type', false); var cre_trx_binding = JSON.parse(ne(context.getSetting('SCRIPT', 'custscript_cre_transaction_binding'),'{}')); var cre_profileid = cre_trx_binding[rectype]; //only act on transactions that have a specific binding to CRE if (cre_profileid.length == 0) return; var error_list = []; //produce CRE output (effectively a PDF file) try { var creProfile = new CREProfile(cre_profileid); creProfile.Translate(recid); creProfile.Execute(); } catch(e) { var str = "There was trouble generating the CRE file: " + recid + '-->' + cre_profileid; + '; error: ' + e.getCode(); nlapiLogExecution("ERROR", 'could not create cre ouput', str); error_list.push("There was an error creating the CRE file. " + str); } if (error_list.length > 0){ return; } //we should have file output var file_obj = null; var attachment_list = []; var foldername = cre_getFolderName(TEMPLATE_FOLDER_ID); if (creProfile.fields.DocumentName.translatedValue) { try { file_obj = nlapiLoadFile(foldername +'/' + creProfile.fields.DocumentName.translatedValue); } catch(e) { var str = "There was trouble looking up CRE output file: " + creProfile.fields.DocumentName.Value + '-->' + creProfile.fields.DocumentName.translatedValue; + '; error: ' + e.getCode(); nlapiLogExecution("ERROR", 'could not create document', str); //syntax template does not exist. Return this one. error_list.push("There was an error creating the CRE attachment. " + str); } } //get the file object and add it to the attachment list array if (file_obj){ nlapiLogExecution('DEBUG', 'fetched file' + file_obj.getName() + '; id:' + file_obj.getId() + '; type:' + file_obj.getType() ); attachment_list.push(file_obj.getId()); } else { nlapiLogExecution('DEBUG', 'Missing fetchd file; return'); error_list.push("There was an error attaching the CRE file."); } //add the attachment to the oject if (attachment_list.length > 0){ for (var m=0; m<attachment_list.length; m++){ nlapiSelectNewLineItem('mediaitem'); nlapiSetCurrentLineItemValue('mediaitem', 'mediaitem', attachment_list[m]); nlapiCommitLineItem('mediaitem'); } } else { nlapiLogExecution('DEBUG', 'attachment_list is empty'); error_list.push("Expected an attachment and found none."); } // now enhance the default CRE message system to remove the default transaction checkbox so they don't send // netsuite's default message. var html = ""; html += '<SCRIPT language="JavaScript" type="text/javascript">\r\n'; html += "function bindEvent(element, type, handler) {if(element.addEventListener) {element.addEventListener(type, handler, false);} else {element.attachEvent('on'+type, handler);}} \r\n"; html += "</SCRIPT>\r\n"; html += '<SCRIPT language="JavaScript" type="text/javascript">\r\n'; html += "function wload() \r\n{\r\n"; html += "nlapiSetFieldValue('includetransaction', 'F');\r\n"; html += "var fld = nlapiGetField('includetransaction');\r\n"; html += "if (fld){fld.setDisplayType('hidden');};\r\n"; html += "var fld = nlapiGetField('emailpreference');\r\n"; html += "if (fld){fld.setDisplayType('hidden');};\r\n"; if (error_list.length > 0){ html += "alert('Warning: there appears to be an error fetching attachments. Please review the attachment list before sending.\\n\\n"+error_list.join('\\n')+"');\r\n"; nlapiLogExecution('ERROR', 'Error fetching attachments', JSON.stringify(error_list)); } html += "}\r\n"; html += "</SCRIPT>\r\n"; html += '<SCRIPT language="JavaScript" type="text/javascript">\r\n'; html += 'bindEvent(window, "load", wload);\r\n'; html += "</SCRIPT>\r\n"; var field0 = form.addField('custpage_client_html', 'inlinehtml', '',null, null); field0.setDefaultValue(html); }
Drive NetSuite To Fit Your Specific Requirements
NetSuite’s platform affords us many opportunities to streamline our day-to-day operational usage while increase our capacity to act quickly — this spells into lower cost and higher profits. If you have a unique requirement and wish to get more out the NetSuite platform, let’s have a conversation.
how can I attach a file in the file sublist of any transaction in 2.0. I have tried the below code but its giving error as :”SSS_INVALID_SUBLIST_OPERATION”,”message”:”You have attempted an invalid sublist or line item operation. You are either trying to access a field on a non-existent line or you are trying to add or remove lines from a static sublist.
Code:
var attachment_list = new Array();
attachment_list.push(fileObj.id);
var nsRecord = record.load({
type : record.Type.INVOICE,
id : i_INV_InternalID,
isDynamic: true
});
var lineCount = nsRecord.getLineCount({
sublistId: ‘mediaitem’
});
log.debug(‘lineCount:’,lineCount);
//return;
nsRecord.selectNewLine({
sublistId: ‘mediaitem’
});
nsRecord.setCurrentSublistValue({
sublistId: ‘mediaitem’,
fieldId: ‘mediaitem’,
value: attachment_list[0]
});
nsRecord.commitLine({
sublistId: ‘mediaitem’
});
var success = nsRecord.save({
enableSourcing: true,
ignoreMandatoryFields: true
});
Hello Onkar,
Sublist operations can be tricky. There are two approaches to use. You may want to try the record.Sublist operation instead of the method you are trying. Here is some SuiteScript 2.0 SuiteLet code where we are in a POST and a file was submitted. We attach it to a purchase order and then we display to the user the name of the file that was submitted.
if (request.files.file)
{
log.debug(request.files.file, request.files.length);
for (names in request.files.file)
{
log.debug(‘file.field:’ + names, request.files.file[names]);
}
request.files.file.folder = runtime.getCurrentScript().getParameter({
name: ‘custscript_pri_trx_app_file_cabinet_loc2’
});
request.files.file.name = Date.now() + ‘_’ + request.files.file.name;
log.debug(request.files.file.folder);
var internalID = request.files.file.save();
log.debug(‘file saved’, internalID)
log.debug(‘tran_id’, tran_id);
log.debug(‘mode’, mode);
if (internalID && tran_id) {
record.attach({
record: {
id: internalID,
type: ‘file’
},
to: {
id: tran_id,
type: record.Type.PURCHASE_ORDER
}
});
statusFld.defaultValue = ‘Success! ‘ +
‘File ‘ + request.files.file.name + ‘ successfully attached to the transaction.‘;
}
}
Hello Marty.
Thanks for this. Is there a way to automatically include several email addresses in the email window?
Thanks a lot.
I think you would have to manipulate the form via undocumented NetSuite client-side libraries. I have interrogated the email client-side forms (there are two of them) and it is feasible.
Marty