mirror of https://github.com/OCA/social.git
[IMP] mail_layout_force
This commit improves the process of replacing the layout when sending an email without selecting an email template.pull/1620/head
parent
f5c4912a5c
commit
36cf86810b
|
@ -37,11 +37,14 @@ the company logo, and a small footer saying "Powered by Odoo".
|
||||||
There are notably two main layouts used in Odoo, and the user can't control when
|
There are notably two main layouts used in Odoo, and the user can't control when
|
||||||
they're used, as it's hardcoded into the different applications.
|
they're used, as it's hardcoded into the different applications.
|
||||||
|
|
||||||
|
* ``mail.message_notification_email``
|
||||||
* ``mail.mail_notification_light``
|
* ``mail.mail_notification_light``
|
||||||
* ``mail.mail_notification_paynow``
|
* ``mail.mail_notification_paynow``
|
||||||
|
|
||||||
This module allows to force a specific layout for a given ``email.template``,
|
This module allows to force a specific layout for a given ``email.template``,
|
||||||
effectively overwritting the one hardcoded by Odoo.
|
effectively overwritting the one hardcoded by Odoo. Additionally, it enables
|
||||||
|
forcing a custom layout for emails that do not use an existing ``email.template``
|
||||||
|
record (e.g., when sending an email from the chatter).
|
||||||
|
|
||||||
This allows you to fully customize the way Odoo emails are rendered and sent
|
This allows you to fully customize the way Odoo emails are rendered and sent
|
||||||
to your customers.
|
to your customers.
|
||||||
|
@ -54,9 +57,9 @@ to your customers.
|
||||||
Configuration
|
Configuration
|
||||||
=============
|
=============
|
||||||
|
|
||||||
# Go to Configuration > Technical > Emails > Templates
|
#. Go to Settings > Technical > Emails > Templates
|
||||||
# Open the desired ``email.template`` record.
|
#. Open the desired ``email.template`` record.
|
||||||
# In Advanced Parameters tab, find the Force Layout field.
|
#. In Advanced Parameters tab, find the Force Layout field.
|
||||||
|
|
||||||
You can leave it empty to use the default email layout (chosen by Odoo).
|
You can leave it empty to use the default email layout (chosen by Odoo).
|
||||||
You can force a custom email layout of your own.
|
You can force a custom email layout of your own.
|
||||||
|
@ -70,6 +73,16 @@ You can see how the existing layouts are defined for details or inspiration:
|
||||||
* ``mail.mail_notification_paynow``
|
* ``mail.mail_notification_paynow``
|
||||||
* ``mail.mail_notification_borders``
|
* ``mail.mail_notification_borders``
|
||||||
|
|
||||||
|
To force a new custom layout for emails that do not use an existing ``email.template``
|
||||||
|
record (e.g., emails sent from the chatter):
|
||||||
|
|
||||||
|
#. Go to Settings > Technical > User Interface > Views.
|
||||||
|
#. Copy the current layout (e.g., mail.message_notification_email) to create a new one, and remove any parts you don’t need.
|
||||||
|
#. Open the layout that you want to swap with a substitute. Then, under the Layout Mapping tab:
|
||||||
|
* Set ``Substitute Layout`` to the new custom layout you created.
|
||||||
|
* Set ``Models`` if you want to apply the replacement only to specific models. If left empty,
|
||||||
|
the email layout will be replaced for all models.
|
||||||
|
|
||||||
Bug Tracker
|
Bug Tracker
|
||||||
===========
|
===========
|
||||||
|
|
||||||
|
@ -95,6 +108,10 @@ Contributors
|
||||||
|
|
||||||
* Iván Todorovich <ivan.todorovich@camptocamp.com>
|
* Iván Todorovich <ivan.todorovich@camptocamp.com>
|
||||||
* Abraham Anes <abrahamanes@gmail.com>
|
* Abraham Anes <abrahamanes@gmail.com>
|
||||||
|
* `Quartile <https://www.quartile.co>`_
|
||||||
|
|
||||||
|
* Aung Ko Ko Lin
|
||||||
|
* Yoshi Tashiro
|
||||||
|
|
||||||
Maintainers
|
Maintainers
|
||||||
~~~~~~~~~~~
|
~~~~~~~~~~~
|
||||||
|
|
|
@ -13,5 +13,10 @@
|
||||||
"category": "Marketing",
|
"category": "Marketing",
|
||||||
"depends": ["mail"],
|
"depends": ["mail"],
|
||||||
"demo": ["demo/mail_layout.xml"],
|
"demo": ["demo/mail_layout.xml"],
|
||||||
"data": ["data/mail_layout.xml", "views/mail_template.xml"],
|
"data": [
|
||||||
|
"security/ir.model.access.csv",
|
||||||
|
"data/mail_layout.xml",
|
||||||
|
"views/ir_ui_views.xml",
|
||||||
|
"views/mail_template.xml",
|
||||||
|
],
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,2 +1,4 @@
|
||||||
|
from . import email_layout_mapping
|
||||||
|
from . import ir_ui_view
|
||||||
from . import mail_template
|
from . import mail_template
|
||||||
from . import mail_thread
|
from . import mail_thread
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
# Copyright 2025 Quartile (https://www.quartile.co)
|
||||||
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||||
|
|
||||||
|
from odoo import fields, models
|
||||||
|
|
||||||
|
|
||||||
|
class EmailLayoutMapping(models.Model):
|
||||||
|
_name = "email.layout.mapping"
|
||||||
|
_description = "Email Layout Mapping"
|
||||||
|
|
||||||
|
layout_id = fields.Many2one("ir.ui.view", ondelete="cascade")
|
||||||
|
substitute_layout_id = fields.Many2one(
|
||||||
|
"ir.ui.view",
|
||||||
|
domain=[("type", "=", "qweb")],
|
||||||
|
required=True,
|
||||||
|
help="Select a target layout.",
|
||||||
|
)
|
||||||
|
model_ids = fields.Many2many(
|
||||||
|
"ir.model", string="Models", help="Select models that the swapping applies to."
|
||||||
|
)
|
|
@ -0,0 +1,10 @@
|
||||||
|
# Copyright 2025 Quartile (https://www.quartile.co)
|
||||||
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||||
|
|
||||||
|
from odoo import fields, models
|
||||||
|
|
||||||
|
|
||||||
|
class IrUiView(models.Model):
|
||||||
|
_inherit = "ir.ui.view"
|
||||||
|
|
||||||
|
layout_mapping_line_ids = fields.One2many("email.layout.mapping", "layout_id")
|
|
@ -18,3 +18,58 @@ class MailThread(models.AbstractModel):
|
||||||
return super().message_post_with_template(
|
return super().message_post_with_template(
|
||||||
template_id, email_layout_xmlid=email_layout_xmlid, **kwargs
|
template_id, email_layout_xmlid=email_layout_xmlid, **kwargs
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _notify_thread_by_email(
|
||||||
|
self,
|
||||||
|
message,
|
||||||
|
recipients_data,
|
||||||
|
msg_vals=False,
|
||||||
|
mail_auto_delete=True,
|
||||||
|
model_description=False,
|
||||||
|
force_email_company=False,
|
||||||
|
force_email_lang=False,
|
||||||
|
resend_existing=False,
|
||||||
|
force_send=True,
|
||||||
|
send_after_commit=True,
|
||||||
|
subtitles=None,
|
||||||
|
**kwargs
|
||||||
|
):
|
||||||
|
msg_vals = msg_vals or {}
|
||||||
|
layout_xmlid = (
|
||||||
|
msg_vals.get("email_layout_xmlid")
|
||||||
|
or message.email_layout_xmlid
|
||||||
|
or "mail.mail_notification_layout"
|
||||||
|
)
|
||||||
|
layout = self.env.ref(layout_xmlid, raise_if_not_found=True)
|
||||||
|
res_model = (
|
||||||
|
self.env["ir.model"].sudo().search([("model", "=", self._name)], limit=1)
|
||||||
|
)
|
||||||
|
mapping = self.env["email.layout.mapping"].search(
|
||||||
|
[("layout_id", "=", layout.id), ("model_ids", "in", res_model.ids)],
|
||||||
|
limit=1,
|
||||||
|
)
|
||||||
|
if not mapping:
|
||||||
|
mapping = self.env["email.layout.mapping"].search(
|
||||||
|
[("layout_id", "=", layout.id), ("model_ids", "=", False)], limit=1
|
||||||
|
)
|
||||||
|
if mapping:
|
||||||
|
substitute_layout = mapping.substitute_layout_id
|
||||||
|
if not substitute_layout.xml_id:
|
||||||
|
substitute_layout._export_rows([["id"]])
|
||||||
|
# Refresh cache to get xml_id assigned by _export_rows
|
||||||
|
substitute_layout.invalidate_recordset()
|
||||||
|
msg_vals["email_layout_xmlid"] = mapping.substitute_layout_id.xml_id
|
||||||
|
return super()._notify_thread_by_email(
|
||||||
|
message,
|
||||||
|
recipients_data,
|
||||||
|
msg_vals=msg_vals,
|
||||||
|
mail_auto_delete=mail_auto_delete,
|
||||||
|
model_description=model_description,
|
||||||
|
force_email_company=force_email_company,
|
||||||
|
force_email_lang=force_email_lang,
|
||||||
|
resend_existing=resend_existing,
|
||||||
|
force_send=force_send,
|
||||||
|
send_after_commit=send_after_commit,
|
||||||
|
subtitles=subtitles,
|
||||||
|
**kwargs
|
||||||
|
)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Go to Configuration > Technical > Emails > Templates
|
#. Go to Settings > Technical > Emails > Templates
|
||||||
# Open the desired ``email.template`` record.
|
#. Open the desired ``email.template`` record.
|
||||||
# In Advanced Parameters tab, find the Force Layout field.
|
#. In Advanced Parameters tab, find the Force Layout field.
|
||||||
|
|
||||||
You can leave it empty to use the default email layout (chosen by Odoo).
|
You can leave it empty to use the default email layout (chosen by Odoo).
|
||||||
You can force a custom email layout of your own.
|
You can force a custom email layout of your own.
|
||||||
|
@ -13,3 +13,13 @@ You can see how the existing layouts are defined for details or inspiration:
|
||||||
* ``mail.mail_notification_light``
|
* ``mail.mail_notification_light``
|
||||||
* ``mail.mail_notification_paynow``
|
* ``mail.mail_notification_paynow``
|
||||||
* ``mail.mail_notification_borders``
|
* ``mail.mail_notification_borders``
|
||||||
|
|
||||||
|
To force a new custom layout for emails that do not use an existing ``email.template``
|
||||||
|
record (e.g., emails sent from the chatter):
|
||||||
|
|
||||||
|
#. Go to Settings > Technical > User Interface > Views.
|
||||||
|
#. Copy the current layout (e.g., mail.message_notification_email) to create a new one, and remove any parts you don’t need.
|
||||||
|
#. Open the layout that you want to swap with a substitute. Then, under the Layout Mapping tab:
|
||||||
|
* Set ``Substitute Layout`` to the new custom layout you created.
|
||||||
|
* Set ``Models`` if you want to apply the replacement only to specific models. If left empty,
|
||||||
|
the email layout will be replaced for all models.
|
||||||
|
|
|
@ -2,3 +2,7 @@
|
||||||
|
|
||||||
* Iván Todorovich <ivan.todorovich@camptocamp.com>
|
* Iván Todorovich <ivan.todorovich@camptocamp.com>
|
||||||
* Abraham Anes <abrahamanes@gmail.com>
|
* Abraham Anes <abrahamanes@gmail.com>
|
||||||
|
* `Quartile <https://www.quartile.co>`_
|
||||||
|
|
||||||
|
* Aung Ko Ko Lin
|
||||||
|
* Yoshi Tashiro
|
||||||
|
|
|
@ -7,11 +7,14 @@ the company logo, and a small footer saying "Powered by Odoo".
|
||||||
There are notably two main layouts used in Odoo, and the user can't control when
|
There are notably two main layouts used in Odoo, and the user can't control when
|
||||||
they're used, as it's hardcoded into the different applications.
|
they're used, as it's hardcoded into the different applications.
|
||||||
|
|
||||||
|
* ``mail.message_notification_email``
|
||||||
* ``mail.mail_notification_light``
|
* ``mail.mail_notification_light``
|
||||||
* ``mail.mail_notification_paynow``
|
* ``mail.mail_notification_paynow``
|
||||||
|
|
||||||
This module allows to force a specific layout for a given ``email.template``,
|
This module allows to force a specific layout for a given ``email.template``,
|
||||||
effectively overwritting the one hardcoded by Odoo.
|
effectively overwritting the one hardcoded by Odoo. Additionally, it enables
|
||||||
|
forcing a custom layout for emails that do not use an existing ``email.template``
|
||||||
|
record (e.g., when sending an email from the chatter).
|
||||||
|
|
||||||
This allows you to fully customize the way Odoo emails are rendered and sent
|
This allows you to fully customize the way Odoo emails are rendered and sent
|
||||||
to your customers.
|
to your customers.
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||||
|
access_email_layout_mapping_all,email.layout.mapping.all,model_email_layout_mapping,,1,0,0,0
|
||||||
|
access_email_layout_mapping_admin,email.layout.mapping.admin,model_email_layout_mapping,base.group_system,1,1,1,1
|
|
|
@ -376,11 +376,14 @@ the company logo, and a small footer saying “Powered by Odoo”.</p>
|
||||||
<p>There are notably two main layouts used in Odoo, and the user can’t control when
|
<p>There are notably two main layouts used in Odoo, and the user can’t control when
|
||||||
they’re used, as it’s hardcoded into the different applications.</p>
|
they’re used, as it’s hardcoded into the different applications.</p>
|
||||||
<ul class="simple">
|
<ul class="simple">
|
||||||
|
<li><tt class="docutils literal">mail.message_notification_email</tt></li>
|
||||||
<li><tt class="docutils literal">mail.mail_notification_light</tt></li>
|
<li><tt class="docutils literal">mail.mail_notification_light</tt></li>
|
||||||
<li><tt class="docutils literal">mail.mail_notification_paynow</tt></li>
|
<li><tt class="docutils literal">mail.mail_notification_paynow</tt></li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>This module allows to force a specific layout for a given <tt class="docutils literal">email.template</tt>,
|
<p>This module allows to force a specific layout for a given <tt class="docutils literal">email.template</tt>,
|
||||||
effectively overwritting the one hardcoded by Odoo.</p>
|
effectively overwritting the one hardcoded by Odoo. Additionally, it enables
|
||||||
|
forcing a custom layout for emails that do not use an existing <tt class="docutils literal">email.template</tt>
|
||||||
|
record (e.g., when sending an email from the chatter).</p>
|
||||||
<p>This allows you to fully customize the way Odoo emails are rendered and sent
|
<p>This allows you to fully customize the way Odoo emails are rendered and sent
|
||||||
to your customers.</p>
|
to your customers.</p>
|
||||||
<p><strong>Table of contents</strong></p>
|
<p><strong>Table of contents</strong></p>
|
||||||
|
@ -398,9 +401,11 @@ to your customers.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" id="configuration">
|
<div class="section" id="configuration">
|
||||||
<h1><a class="toc-backref" href="#toc-entry-1">Configuration</a></h1>
|
<h1><a class="toc-backref" href="#toc-entry-1">Configuration</a></h1>
|
||||||
<p># Go to Configuration > Technical > Emails > Templates
|
<ol class="arabic simple">
|
||||||
# Open the desired <tt class="docutils literal">email.template</tt> record.
|
<li>Go to Settings > Technical > Emails > Templates</li>
|
||||||
# In Advanced Parameters tab, find the Force Layout field.</p>
|
<li>Open the desired <tt class="docutils literal">email.template</tt> record.</li>
|
||||||
|
<li>In Advanced Parameters tab, find the Force Layout field.</li>
|
||||||
|
</ol>
|
||||||
<p>You can leave it empty to use the default email layout (chosen by Odoo).
|
<p>You can leave it empty to use the default email layout (chosen by Odoo).
|
||||||
You can force a custom email layout of your own.
|
You can force a custom email layout of your own.
|
||||||
You can use the <em>Mail: No-Layout notification template</em> to prevent Odoo
|
You can use the <em>Mail: No-Layout notification template</em> to prevent Odoo
|
||||||
|
@ -412,6 +417,22 @@ You can see how the existing layouts are defined for details or inspiration:</p>
|
||||||
<li><tt class="docutils literal">mail.mail_notification_paynow</tt></li>
|
<li><tt class="docutils literal">mail.mail_notification_paynow</tt></li>
|
||||||
<li><tt class="docutils literal">mail.mail_notification_borders</tt></li>
|
<li><tt class="docutils literal">mail.mail_notification_borders</tt></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<p>To force a new custom layout for emails that do not use an existing <tt class="docutils literal">email.template</tt>
|
||||||
|
record (e.g., emails sent from the chatter):</p>
|
||||||
|
<ol class="arabic simple">
|
||||||
|
<li>Go to Settings > Technical > User Interface > Views.</li>
|
||||||
|
<li>Copy the current layout (e.g., mail.message_notification_email) to create a new one, and remove any parts you don’t need.</li>
|
||||||
|
<li><dl class="first docutils">
|
||||||
|
<dt>Open the layout that you want to swap with a substitute. Then, under the Layout Mapping tab:</dt>
|
||||||
|
<dd><ul class="first last">
|
||||||
|
<li>Set <tt class="docutils literal">Substitute Layout</tt> to the new custom layout you created.</li>
|
||||||
|
<li>Set <tt class="docutils literal">Models</tt> if you want to apply the replacement only to specific models. If left empty,
|
||||||
|
the email layout will be replaced for all models.</li>
|
||||||
|
</ul>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" id="bug-tracker">
|
<div class="section" id="bug-tracker">
|
||||||
<h1><a class="toc-backref" href="#toc-entry-2">Bug Tracker</a></h1>
|
<h1><a class="toc-backref" href="#toc-entry-2">Bug Tracker</a></h1>
|
||||||
|
@ -441,6 +462,12 @@ If you spotted it first, help us to smash it by providing a detailed and welcome
|
||||||
</li>
|
</li>
|
||||||
<li><p class="first">Abraham Anes <<a class="reference external" href="mailto:abrahamanes@gmail.com">abrahamanes@gmail.com</a>></p>
|
<li><p class="first">Abraham Anes <<a class="reference external" href="mailto:abrahamanes@gmail.com">abrahamanes@gmail.com</a>></p>
|
||||||
</li>
|
</li>
|
||||||
|
<li><p class="first"><a class="reference external" href="https://www.quartile.co">Quartile</a></p>
|
||||||
|
<ul class="simple">
|
||||||
|
<li>Aung Ko Ko Lin</li>
|
||||||
|
<li>Yoshi Tashiro</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" id="maintainers">
|
<div class="section" id="maintainers">
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
# @author Iván Todorovich <ivan.todorovich@camptocamp.com>
|
# @author Iván Todorovich <ivan.todorovich@camptocamp.com>
|
||||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||||
|
|
||||||
|
from odoo import Command
|
||||||
from odoo.tests import TransactionCase
|
from odoo.tests import TransactionCase
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,6 +19,20 @@ class TestMailLayoutForce(TransactionCase):
|
||||||
"arch": "<t t-name='test'><h1></h1><t t-out='message.body'/></t>",
|
"arch": "<t t-name='test'><h1></h1><t t-out='message.body'/></t>",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
cls.mail_notification_layout = cls.env.ref("mail.mail_notification_layout")
|
||||||
|
cls.layout_substitute = cls.env["ir.ui.view"].create(
|
||||||
|
{
|
||||||
|
"name": "Substitute Layout",
|
||||||
|
"type": "qweb",
|
||||||
|
"mode": "primary",
|
||||||
|
"arch": """<?xml version="1.0"?>
|
||||||
|
<t t-name="custom_mail_notification_layout">
|
||||||
|
<div t-out="message.body"/>
|
||||||
|
<div t-if="signature" t-out="signature" style="font-size: 13px;"/>
|
||||||
|
<h1>Substituted</h1>
|
||||||
|
</t>""",
|
||||||
|
}
|
||||||
|
)
|
||||||
cls.template = cls.env["mail.template"].create(
|
cls.template = cls.env["mail.template"].create(
|
||||||
{
|
{
|
||||||
"name": "Test Template",
|
"name": "Test Template",
|
||||||
|
@ -71,3 +86,32 @@ class TestMailLayoutForce(TransactionCase):
|
||||||
composer._action_send_mail()
|
composer._action_send_mail()
|
||||||
message = self.partner.message_ids[-1]
|
message = self.partner.message_ids[-1]
|
||||||
self.assertEqual(message.mail_ids.body_html.strip(), "<h1></h1><p>Test</p>")
|
self.assertEqual(message.mail_ids.body_html.strip(), "<h1></h1><p>Test</p>")
|
||||||
|
|
||||||
|
def test_chatter_message_uses_default_layout(self):
|
||||||
|
self.partner.message_post(
|
||||||
|
body="Test Message",
|
||||||
|
email_layout_xmlid=self.mail_notification_layout.xml_id,
|
||||||
|
message_type="comment",
|
||||||
|
subtype_xmlid="mail.mt_comment",
|
||||||
|
mail_auto_delete=False,
|
||||||
|
force_send=True,
|
||||||
|
)
|
||||||
|
message = self.partner.message_ids[-1]
|
||||||
|
self.assertNotIn("<h1>Substituted</h1>", message.mail_ids.body_html)
|
||||||
|
self.assertIn("Test Message", message.mail_ids.body_html)
|
||||||
|
|
||||||
|
def test_chatter_message_uses_substituted_layout(self):
|
||||||
|
self.mail_notification_layout.layout_mapping_line_ids = [
|
||||||
|
Command.create({"substitute_layout_id": self.layout_substitute.id})
|
||||||
|
]
|
||||||
|
self.partner.message_post(
|
||||||
|
body="Test Message",
|
||||||
|
email_layout_xmlid=self.mail_notification_layout.xml_id,
|
||||||
|
message_type="comment",
|
||||||
|
subtype_xmlid="mail.mt_comment",
|
||||||
|
mail_auto_delete=False,
|
||||||
|
force_send=True,
|
||||||
|
)
|
||||||
|
message = self.partner.message_ids[-1]
|
||||||
|
self.assertIn("<h1>Substituted</h1>", message.mail_ids.body_html)
|
||||||
|
self.assertIn("Test Message", message.mail_ids.body_html)
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<odoo>
|
||||||
|
<record id="view_ir_ui_view_form_inherit" model="ir.ui.view">
|
||||||
|
<field name="name">ir.ui.view.form.inherit</field>
|
||||||
|
<field name="model">ir.ui.view</field>
|
||||||
|
<field name="inherit_id" ref="base.view_view_form" />
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//page[@name='inherit_children']" position="after">
|
||||||
|
<page
|
||||||
|
name="layout_mapping"
|
||||||
|
string="Layout Mapping"
|
||||||
|
attrs="{'invisible': [('type', '!=', 'qweb')]}"
|
||||||
|
>
|
||||||
|
<field name="layout_mapping_line_ids" nolabel="1">
|
||||||
|
<tree editable="bottom">
|
||||||
|
<field name="substitute_layout_id" />
|
||||||
|
<field name="model_ids" widget="many2many_tags" />
|
||||||
|
</tree>
|
||||||
|
</field>
|
||||||
|
</page>
|
||||||
|
</xpath>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
</odoo>
|
Loading…
Reference in New Issue