In our previous article, we explained how to configure and design email notifications for the Purchase requisition review workflow. Using Docentric improvements, you can design Email templates used for workflow notifications in the advanced email body editor with placeholders. But there is more – you can add any file you need to a workflow notification email as the email attachment.
In this article, we will demonstrate how to attach documents from the workflow entity, a purchase requisition header, to the workflow email notifications.
However, you can use the coding approach described in this article if you need to change the default logic of selecting attachments.
Setup
The setup is already described in the previous article; we need to configure the Purchase requisition review workflow to send email notifications based on WFEmail, a record from System email templates.
WFEmail in System email templates should be configured as described in the previous article but with one change though. We will use a different Class for placeholders, DocPurchReqWfEmailNotificationWithAttachmentsETH, to enable workflow email attachments.
The new class, DocPurchReqWfEmailNotificationWithAttachmentsETH, extends the previously used class, DocPurchReqWorkflowEmailNotificationETH, with an additional method:
1 2 3 4 5 6 7 8 9 10 |
public boolean handleAttachments(SysOutgoingEmailTable _outgoingEmailTable, container _parameters = conNull()) { Common commonTable = this.getAttachmentsContextRecord(); if (tableNum(PurchReqTable) == commonTable.TableId) { _outgoingEmailTable.insertAttachmentsFromCommon_DC(commonTable); } return false; } |
Note that the base class (DocEmailTemplateAdvancedHandlerWFAL) provides the access to the workflow entity, the PurchReqTable table record, so we can iterate through its Attachments (the related DocuRef records), and attach them to the outgoing email.
How to add attachments to outgoing emails
When a workflow email notification is created, it is stored in the Batch email sending status table (SysOutgoingEmailTable). On the other hand, its attachments are stored in the SysOutgoingEmailData table.
We extended the SysOutgoingEmailTable table with a few instance methods to enable adding the related attachments by inserting new records into the SysOutgoingEmailData table.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
/// <summary> /// For the provided table record _commonTable insert all Attachments (DocuRef records), which are files, /// as the attachments (new records in the SysOutgoingEmailData table) of this outgoing email (i.e. this record). /// </summary> /// <param name = "_commonTable">Table record for which the Attachments (DocuRef records) will be inserted</param> public void insertAttachmentsFromCommon_DC(Common _commonTable) { DocuRef docuRef; ttsbegin; while select docuRef where docuRef.RefTableId == _commonTable.TableId && docuRef.RefRecId == _commonTable.RecId && docuRef.RefCompanyId == _commonTable.DataAreaId { this.insertAttachmentFromDocuRef_DC(docuRef); } ttscommit; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
/// <summary> /// Insert the file of the provided DocuRef record, if such exists, as the attachment /// (a new record in the SysOutgoingEmailData table) of this outgoing email (i.e. this record). /// </summary> /// <param name = "_docuRef">Inserting DocuRef record</param> /// <returns>If the provided docuRef doesn't have the file attached, return false, otherwise return true.</returns> public boolean insertAttachmentFromDocuRef_DC(DocuRef _docuRef) { SysOutgoingEmailData outgoingEmailData; SysEmailDataId newDataId; void validateParameters() { if (!this.EmailItemId) { DocGlobalHelper::handleException(funcName(), 'Cannot insert an attachment of the SysOutgoingEmailTable record with EmailItemId = 0'); } if (!_docuRef) { DocGlobalHelper::handleException(funcName(), 'DocuRef record is not provided'); } } // Validate parameters. validateParameters(); // If the provided docuRef doesn't have Class which attaches files, it is Note or URL. // In this case return false. ClassId actionClassId = _docuRef.docuType().ActionClassId; if (!SysDictClass::isEqualOrSuperclass(actionClassId, classNum(DocuActionFile))) { return false; } // Insert the file attached to docuRef into the SysOutgoingEmailData table. ttsbegin; select forupdate maxof(DataId) from outgoingEmailData where outgoingEmailData.EmailItemId == this.EmailItemId && outgoingEmailData.EmailDataType == SysEmailDataType::Attachment; newDataId = outgoingEmailData.DataId + 1; outgoingEmailData.clear(); outgoingEmailData.EmailItemId = this.EmailItemId; outgoingEmailData.DataId = newDataId; outgoingEmailData.EmailDataType = SysEmailDataType::Attachment; outgoingEmailData.FileExtension = '.' + _docuRef.fileType(); outgoingEmailData.FileName = _docuRef.Name; outgoingEmailData.Data = DocumentManagement::getAttachmentAsContainer(_docuRef); outgoingEmailData.insert(); ttscommit; return true; } |
Let’s create workflow email notifications with attachments
In order to test workflow email notifications with attachments, we will first create a new purchase requisition with two attachments and submit it to the Purchase requisition review workflow.
When the purchase requisition is approved, the workflow email notification is created and saved into Batch email sending status. We can view the outgoing email message, before it is sent by Email distributor batch, by clicking the Show message button. Note that the email message has two email attachments, the files from the corresponding purchase requisition header.
We also added a new button to the into Batch email sending status form, Download message, which will generate from the selected record the EML file that you can open in Outlook and check the email message attachments.
Resources
Download Class for placeholders for this example >>
See also
Send nicely designed emails from workflows >>
Learn in more detail how to create dynamic tables in Email templates >>
Enabling link to the WF entity in Email templates >>