How to Extend and Modify an Existing Mail Template in Odoo 17

In Odoo 17, a crucial aspect of system customization involves inheriting and modifying existing mail templates. By tweaking or revising the content of these templates, you can customize them to suit your particular business requirements.

In this extensive guide, we'll delve into the step-by-step process of inheriting and modifying an existing mail template in Odoo 17.

Understanding the Structure of Mail Templates in Odoo 17

Before proceeding with the process, it's important to grasp the structure of a mail template in Odoo 17. Mail templates in Odoo are constructed using XML code and encompass different fields that outline the email's content, such as the subject, body, recipient, and attachments. These templates form the basis for dispatching automated emails from the system.


To exemplify this concept, let's contemplate an instance of modifying the mail template within the accounting module. Upon clicking the "SEND & PRINT" button from the "account.move" model, a wizard will emerge. Our objective is to amend the current mail template employed in this wizard.

The current code for the "Invoice: Sending" mail template appears as follows:

<?xml version="1.0" ?>
<odoo>
    <data noupdate="1">
        <!--Email template -->
        <record id="email_template_edi_invoice" model="mail.template">
            <field name="name">Invoice: Sending</field>
            <field name="model_id" ref="account.model_account_move"/>
            <field name="email_from">{{ (object.invoice_user_id.email_formatted or object.company_id.email_formatted or user.email_formatted) }}</field>
            <field name="partner_to">{{ object.partner_id.id }}</field>
            <field name="subject">{{ object.company_id.name }} Invoice (Ref {{ object.name or 'n/a' }})</field>
            <field name="description">Sent to customers with their invoices in attachment</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 <span style="font-weight:bold;" t-out="object.name or ''">INV/2021/05/0005</span>
        </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 <span style="font-weight:bold;" t-out="format_amount(object.amount_total, object.currency_id) or ''">$ 143,750.00</span>
        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: <span style="font-weight:bold;" t-out="object.payment_reference or ''">INV/2021/05/0005</span>.
            </t>
        </t>
        <t t-if="hasattr(object, 'timesheet_count') and object.timesheet_count">
            <br /><br />
            PS: you can review your timesheets <a t-att-href="'my/timesheets?search_in=invoice&amp;search=%s' % object.name">from the portal.</a>
        </t>
        <br /><br />
        Do not hesitate to contact us if you have any questions.
        <t t-if="not is_html_empty(object.invoice_user_id.signature)">
            <br /><br />
            <t t-out="object.invoice_user_id.signature or ''">--<br/>Mitchell Admin</t>
        </t>
    </p>
</div>
            </field>
            <field name="report_template_ids" eval="[(4, ref('account.account_invoices'))]"/>
            <field name="lang">{{ object.partner_id.lang }}</field>
            <field name="auto_delete" eval="True"/>
        </record>
        </odoo>

The provided code snippet reveals the declaration of the mail template named "Invoice: Sending," linked with the model "account.model_account_move." It encompasses several fields, including the sender's email, recipient's email, subject, description, HTML body, report template, report name, language specification, and auto-delete configuration.

Enabling Editable Mail Templates

To edit the mail template, adjustments must be made to the existing code. Currently, the attribute noupdate="1" restricts modifications to the template. Altering this attribute will allow the template to become editable.

Below is an example demonstrating how to enable editability of the template using the search and write functions:

<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>

In the provided code snippet, we begin by searching for the mail template identified as "email_template_edi_invoice" within the "account" module. Subsequently, we modify the noupdate attribute to False, thereby permitting modifications to the template.

Adjusting the Mail Template

With the mail template now editable, we can move forward with the required modifications. For instance, we may opt to incorporate the invoice date into the email's subject line and specify the name of the report to be attached.

To adjust the mail template, we must update the subject and report_name fields of the mail.template record. Below is the code snippet illustrating this process:

<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>

This code snippet demonstrates updating the subject field to incorporate the invoice date through the object.invoice_date variable. Additionally, it adjusts the report_name field to include the invoice date in the specified format.

Setting the noupdate attribute to True

After making the required modifications, it's crucial to revert the mail template to its non-updatable state to prevent unintended alterations in the future. Here's how you can accomplish this:

<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>

By setting the value of noupdate to True, we ensure that the mail template remains non-updatable.

Conclusion

Incorporating and revising an existing mail template in Odoo 17 is a simple task. By enabling the template for updates, adjusting relevant fields, and then reverting it to a non-updatable status, you can tailor the template content to your requirements. It's essential to apply these modifications within a custom module for systematic management and compatibility with forthcoming updates.

By adhering to the instructions provided in this blog post, you can effectively inherit and modify mail templates within Odoo 17. This empowers you to craft customized and tailored email communications to suit the specific requirements of your business.

Managing bill payments through the European SEPA system in Odoo 17 Accounting