In this blog, let us see how to inherit and update an existing mail template in Odoo 15. We have to do this to add any changes or modifications to the content of a template that already exists. The mail templates are really important since most of the emails are sent to the customers/ vendors, which helps to establish a better relationship with them. So, the mail templates are added as data with no update set as True which makes them non-updatable. To add changes to the mail templates, first, we need to make those records updatable. Then make the necessary changes to the mail template, and then set the mail templates back to non-updatable. For example, let us try to modify the email_template_edi_invoice mail template in the account module. This mail template is used to send mail from the Send & Print button in the invoice.
As I have mentioned above, the first step is to update the noupdate of the template as False by using the function and value tags.
<function name="write" model="ir.model.data">
<function name="search" model="ir.model.data">
<value eval="[('name', '=', 'email_template_edi_invoice'), ('module', '=', 'account')]" />
</function>
<value eval="{'noupdate': False}" />
</function>
Here ”email_template_edi_invoice” is the record id of the mail template record that we need to modify and the data file of this template is in the “account” module. We are using two functions here; search and write. In the function tag, we have to provide the name of the function as the name parameter and the model in which the function has to be performed as the model parameter. Here we are searching the mail template by providing the domain [(‘name’, ‘=’, ’email_template_edi_invoice’), (‘module’, ‘=’, ‘account’)] in the eval parameter in the value tag within the function tag for search. Then the record found using the search is updated by using the write function by giving {‘noupdate’: False}. This allows us to make changes to the mail template record.
Now we can add the changes to the mail template. For example, I am adding the Invoice Date to the subject of the mail and in the name of the report that will be attached to the mail. For that, we have to update the subject and the report_name fields of the mail template record. Since we will be updating them from the custom module, provide the module name with the id of the record. In our case, the mail template is in the “account” module. So we have to provide the id as “account.email_template_edi_invoice”.
<record id="account.email_template_edi_invoice" model="mail.template">
<field name="subject">{{ object.company_id.name }} Invoice (Ref {{ object.name or 'n/a' }}) {{ object.invoice_date }}</field>
<field name="report_name">Invoice_{{ (object.name or '').replace('/', '_') }}{{ object.state == 'draft' and '_draft' or '' }}_{{ object.invoice_date.strftime('%Y_%m_%d') }}</field>
</record>
Updating the mail body is also similar. Even if we have a small change, we have to use the entire body for the update. For example, we can add the company logo at the end of the mail body with the code given below within the existing one:
<t t-if="object.company_id" class="row">
<t t-set="logo" t-value="'data:image/png;base64,%s' % object.company_id.logo.decode('utf-8')" />
<img src="logo" class="mx-auto" style="width: 150px;height: 80px;" />
</t>
Once we add the changes, we need to set the noupdate back to True for the record.
<function name="write" model="ir.model.data">
<function name="search" model="ir.model.data">
<value eval="[('name', '=', 'email_template_edi_invoice'), ('module', '=', 'account')]" />
</function>
<value eval="{'noupdate': True}" />
</function>
Here, we are doing the same that we have done at the beginning. But, we will search for the mail template record and then set the ‘noupdate’ as True using the search and write functions. It will help to prevent applying any updates to the mail template unnecessarily.
Here is the full code:
<?xml version="1.0" encoding="utf-8"?>
<odoo noupdate="1">
<function name="write" model="ir.model.data">
<function name="search" model="ir.model.data">
<value eval="[('name', '=', 'email_template_edi_invoice'), ('module', '=', 'account')]" />
</function>
<value eval="{'noupdate': False}" />
</function>
<record id="account.email_template_edi_invoice" model="mail.template">
<field name="subject">{{ object.company_id.name }} Invoice (Ref {{ object.name or 'n/a' }}) {{ object.invoice_date }}</field>
<field name="body_html" type="html">
<div style="margin: 0px; padding: 0px;">
<p style="margin: 0px; padding: 0px; font-size: 13px;">
Dear
<t t-if="object.partner_id.parent_id">
<t t-out="object.partner_id.name or ''">Brandon Freeman</t> (<t t-out="object.partner_id.parent_id.name or ''">Azure Interior</t>),
</t>
<t t-else="">
<t t-out="object.partner_id.name or ''">Brandon Freeman</t>,
</t>
<br /><br />
Here is your
<t t-if="object.name">
invoice <strong t-out="object.name or ''">INV/2021/05/0005</strong>
</t>
<t t-else="">
invoice
</t>
<t t-if="object.invoice_origin">
(with reference: <t t-out="object.invoice_origin or ''">SUB003</t>)
</t>
amounting in <strong t-out="format_amount(object.amount_total, object.currency_id) or ''">$ 143,750.00</strong>
from <t t-out="object.company_id.name or ''">YourCompany</t>.
<t t-if="object.payment_state in ('paid', 'in_payment')">
This invoice is already paid.
</t>
<t t-else="">
Please remit payment at your earliest convenience.
<t t-if="object.payment_reference">
<br /><br />
Please use the following communication for your payment: <strong t-out="object.payment_reference or ''">INV/2021/05/0005</strong>.
</t>
</t>
<br /><br />
Do not hesitate to contact us if you have any questions.
<t t-if="object.invoice_user_id.signature">
<br />
<t t-out="object.invoice_user_id.signature or ''">--<br />Mitchell Admin</t>
</t>
</p>
<t t-if="object.company_id" class="row">
<t t-set="logo" t-value="'data:image/png;base64,%s' % object.company_id.logo.decode('utf-8')" />
<img src="logo" class="mx-auto" style="width: 150px;height: 80px;" />
</t>
</div>
</field>
<field name="report_name">Invoice_{{ (object.name or '').replace('/', '_') }}{{ object.state == 'draft' and '_draft' or '' }}_{{ object.invoice_date.strftime('%Y_%m_%d') }}</field>
</record>
<function name="write" model="ir.model.data">
<function name="search" model="ir.model.data">
<value eval="[('name', '=', 'email_template_edi_invoice'), ('module', '=', 'account')]" />
</function>
<value eval="{'noupdate': True}" />
</function>
</odoo>
The entire code is added with noupdate=”1″. If you are supposed to add changes, replace the “1” with “0” during development. Unless only the first change will be applied.
Now, when we go to the invoice and click on Send & Print, we can see the Invoice Date in the subject and the name of the PDF attachment. The company logo will be there inside the mail body.
The email sent is shown in the chatter of the invoice, where you can see the changes clearly.
We have to add this code in an XML file in the data directory of the custom module. We have to specify the file in the data parameter and the module of the existing template(“account” in this example as we are updating the “email_template_edi_invoice template”) in the “depends” list of the manifest file.
With this method, we can inherit and update the existing email templates in Odoo and other custom modules.