Sending multiple customer invoices in a single email without billing period in D365FO

Does it happen in your type of business that some customers have multiple sales orders in short period of time, for example in one day? During the D365FO batch invoicing, if invoices are sent via email, such customers would get multiple emails in the same day. They will probably ask you to send them only one email with all invoices. This article describes a solution to this situation, emailing multiple invoices in one email from D365FO.

A while ago we published an article about the solution to the similar requirement: sending one email with all invoices generated for a customer during a certain billing period (let’s call it "billing-period" solution). Article and downloadable solution were welcomed by our users, whose feedback gave us an insight to their real-life requirements, such as the one covered in the article you are reading ("non-billing-period" solution).

You can download the solution that supports both the requirements from this and the previous article. Feel free to use it as is or adjust it to your needs.

The prerequisite is to install Docentric AX Free Edition first, and the solution provided in this article on top of that.

Business process description

We want to base the solution on the standard D365FO invoicing, let D365FO post and generate the invoices, which we will store on a known location and later execute a separate procedure that will collect and send them in the single email.

We can roughly divide the process into two steps:

Step 1: Post and print the selected sales orders to Azure Blob storage.

  • The step is performed as the standard D365FO batch or interactive invoicing.
  • Docentric File print destination is used for printing. It is configured to save each generated invoice as a separate file on Azure Blob storage. This is a standard feature of Docentric AX Free Edition, and no customization is required.
  • Location of the printed output file on Azure Blob storage is automatically stored on the Invoice journal. This feature has been implemented in the "billing-period" solution, as an extension of standard invoice posting. We will re-use it for the "non-billing-period" solution.

Step 2: Collect and email the printed invoices.

  • The step is performed as batch or interactive procedure, which is implemented as part of this, "non-billing-period" solution.
  • The procedure fetches all files to be sent for the selected customers. This is different from the "billing-period" solution, where we fetch the files based on the invoice date that matches the selected billing period.
  • Finally, procedure sends the fetched files in a single email to each customer.

Reused elements of the "billing-period" solution

As written above, the first step, posting and printing, is the same in both "billing-period" and "non-billing-period" solution. It is explained in detail in the previous article, but let’s repeat the most important points.

Invoice journal extension

We extended the CustInvoiceJour table and Invoice journal form with fields that allow us to save the information about the posted document location and to track if it was emailed.

DocReportRunDelegates_reportExecutionEnd event handler

We implemented an event handler that is invoked when the printing of a report to Docentric File print destination is completed. In this event handler, if the report being executed is invoice, we store the information about the Azure blob path of the printed invoice document. You can check the previous article for more details about the implementation.

Docentric File print destination setup

Print management for Sales Invoice report should be configured as Docentric File print destination. Besides the mandatory information for Output filename and format, we also enable the Save to Azure storage option and enter the values for Blob container and Blob path:

While posting, we will print invoices by using Print management. The above settings will be applied, and the printed file will be saved on Azure Blob storage based on the configured Azure blob path (Blob container + Blob path + File name). The exact path will be saved on the invoice journal and will be used in the emailing step.

Email body editor and placeholders

If you are already using Docentric AX Free or Full Edition, you are probably familiar with the feature-rich emailing capabilities it offers, such as Docentric Email print destination with the email body editor and placeholders, as well as email processing, unresolved email tokens handling, etc. You can seamlessly use them when printing a report to Docentric Email print destination, but for the solution described in this article we are developing a custom emailing procedure. Therefore, our improved emailing won’t work OOTB, so we need to additionally support the emailing features of our choice.

Email body editor and some placeholders are a must-have features, therefore we will support them by first implementing the DocEmailInvoicesHandler class with a few custom placeholders and then by using the Docentric improved Email templates where we will point to the previously implemented class.

That was an overview of the reused features from the "billing-period" solution. Let’s move on to what is new with the "non-billing-period" solution.

Emailing the multiple invoices for selected customers in a single mail

Main use-case for this solution is:

  • For the selected customers periodically send one email message with all invoices created since the previous email was sent.

Additional requirements are:

  • Ability to resend the already sent invoices.
  • Selection how the multiple invoices will be attached to the email: as separate files, as a .zip or as a merged PDF file.
  • Option to send through email processing, i.e. Batch email sending status.
  • Possibility to select the email template for the email message.
  • Ability to use the email tokens or specific email address for the email recipient.
  • Possibility to execute interactively or in batch.

This is the dialog where these options can be specified:

The above dialog offers a selectable query for specifying the customers. For each customer returned from the query a procedure will:

  • Fetch all invoice documents that are stored on Azure Blob storage and have not been sent (unless Send already sent invoices flag is set).
  • Create one email message based on the specified email template and email recipient address. Resolve the placeholders if they are used in the email template body.
  • Add the fetched invoice files as separate or merged/zipped file.
  • Send it immediately or store it in the Batch email sending status table, leaving to Email distributor batch to handle the outgoing emails.
  • Save the success or error information on the invoice journal.

The procedure can be started from the Invoice journal form > Invoice > Emailing invoices > Email without billing period (see image below) or from the Accounts receivable > Periodic tasks > Email multiple invoices without billing period menu item.

Implementation

The solution is implemented through SysOperation Framework. It is a well-documented D365FO framework, so we won’t bother you with all its implementation details. The important stuff happens in the service class DocEmailInvoicesService, in its processOperation() method, where for each customer returned from the query we call the sendCustomerEmail() method:

The sendCustomerEmail() method encapsulates the whole logic for one customer. The snippet below gives a high-level overview of that logic: it first resolves the recipient email addresses, then it prepares and sends the email message and finally updates the invoice journal with the success/error status:

Preparing and sending the email message happens in the DocEmailInvoicesManager::sendEmailAttachmentTypeNoBilling() method. Its first interesting part is combining all invoices for one customer, based on the option user selected for the attachments (separate files, .zip file or merged PDF file):

Next, if user selected sending through email processing, then a docEmailProcessingParams object should be populated (it will be given as a parameter to the actual email sending method DocEmailTemplateManager::sendMail()):

Finally, the email message is created based on the selected email template (_emailId parameter) and sent:

Resulting email

Below is the resulting email for one customer. It is stored in the Batch email sending status form, because the Use email processing option was selected:

With Docentric AX Free or Full version you can Download message directly from this form and inspect it:

Ideas for improvements

  • The DocEmailInvoicesHandler class could support more placeholders, for example a list of all invoice IDs, sum of all invoice amounts, first due date, etc.
  • Query could be modified to support the selection of invoices (for example, based on Due date, Amount, Invoice Id, etc.).
  • The Cc and Bcc fields can be introduced. Currently, only the To field is supported.

Resources

Download the solution project >>
Download the solution model >>

Leave a Reply

Your email address will not be published. Required fields are marked *

*

Docentric respects your privacy. Learn how your comment data is processed >>

Docentric respects your privacy. Learn how your comment data is processed >>