[IMP] mail: reflect inheritance of mail.thread on ir.model (#15107)
The boolean field `is_mail_thread` on `ir.model` allows to create custom models that inherit from model `mail.thread`. The selection field `track_visibility` on `ir.model.fields` allows to add tracking on custom fields. Also change the order on model `ir.model` to make mail thread models appear first.
This commit is contained in:
@@ -50,6 +50,7 @@ Main Features
|
||||
'wizard/email_template_preview_view.xml',
|
||||
'views/mail_template_views.xml',
|
||||
'views/ir_actions_views.xml',
|
||||
'views/ir_model_views.xml',
|
||||
'views/res_partner_views.xml',
|
||||
],
|
||||
'demo': [
|
||||
|
||||
@@ -18,4 +18,5 @@ import res_config
|
||||
import update
|
||||
import ir_actions
|
||||
import ir_autovacuum
|
||||
import ir_model
|
||||
import html2text
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
|
||||
class IrModel(models.Model):
|
||||
_inherit = 'ir.model'
|
||||
_order = 'is_mail_thread DESC, name ASC'
|
||||
|
||||
is_mail_thread = fields.Boolean(
|
||||
string="Mail Thread", oldname='mail_thread', default=False,
|
||||
help="Whether this model supports messages and notifications.",
|
||||
)
|
||||
|
||||
@api.multi
|
||||
def write(self, vals):
|
||||
if self and 'is_mail_thread' in vals:
|
||||
if not all(rec.state == 'manual' for rec in self):
|
||||
raise UserError(_('Only custom models can be modified.'))
|
||||
if not all(rec.is_mail_thread <= vals['is_mail_thread'] for rec in self):
|
||||
raise UserError(_('Field "Mail Thread" cannot be changed to "False".'))
|
||||
res = super(IrModel, self).write(vals)
|
||||
# setup models; this reloads custom models in registry
|
||||
self.pool.setup_models(self._cr, partial=(not self.pool.ready))
|
||||
# update database schema of models
|
||||
models = self.pool.descendants(self.mapped('model'), '_inherits')
|
||||
self.pool.init_models(self._cr, models, dict(self._context, update_custom_fields=True))
|
||||
self.pool.signal_registry_change()
|
||||
else:
|
||||
res = super(IrModel, self).write(vals)
|
||||
return res
|
||||
|
||||
def _reflect_model_params(self, model):
|
||||
vals = super(IrModel, self)._reflect_model_params(model)
|
||||
vals['is_mail_thread'] = issubclass(type(model), self.pool['mail.thread'])
|
||||
return vals
|
||||
|
||||
@api.model
|
||||
def _instanciate(self, model_data):
|
||||
model_class = super(IrModel, self)._instanciate(model_data)
|
||||
if model_data.get('is_mail_thread') and model_class._name != 'mail.thread':
|
||||
parents = model_class._inherit or []
|
||||
parents = [parents] if isinstance(parents, basestring) else parents
|
||||
model_class._inherit = parents + ['mail.thread']
|
||||
return model_class
|
||||
|
||||
|
||||
class IrModelField(models.Model):
|
||||
_inherit = 'ir.model.fields'
|
||||
|
||||
track_visibility = fields.Selection(
|
||||
[('onchange', "On Change"), ('always', "Always")], string="Tracking",
|
||||
help="When set, every modification to this field will be tracked in the chatter.",
|
||||
)
|
||||
|
||||
def _reflect_field_params(self, field):
|
||||
vals = super(IrModelField, self)._reflect_field_params(field)
|
||||
vals['track_visibility'] = getattr(field, 'track_visibility', None)
|
||||
return vals
|
||||
|
||||
def _instanciate_attrs(self, field_data, partial):
|
||||
attrs = super(IrModelField, self)._instanciate_attrs(field_data, partial)
|
||||
if field_data.get('track_visibility'):
|
||||
attrs['track_visibility'] = field_data['track_visibility']
|
||||
return attrs
|
||||
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="model_form_view" model="ir.ui.view">
|
||||
<field name="model">ir.model</field>
|
||||
<field name="inherit_id" ref="base.view_model_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="transient" position="after">
|
||||
<field name="is_mail_thread" attrs="{'readonly': [('state','!=', 'manual')]}" groups="base.group_no_one"/>
|
||||
</field>
|
||||
<xpath expr="//field[@name='field_id']//field[@name='copy']" position="after">
|
||||
<field name="track_visibility" attrs="{'readonly': [('state','!=', 'manual')]}"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="model_search_view" model="ir.ui.view">
|
||||
<field name="model">ir.model</field>
|
||||
<field name="inherit_id" ref="base.view_model_search"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="model" position="after">
|
||||
<filter string="Mail Thread" name="is_mail_thread" domain="[('is_mail_thread', '=', True)]"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="field_form_view" model="ir.ui.view">
|
||||
<field name="model">ir.model.fields</field>
|
||||
<field name="inherit_id" ref="base.view_model_fields_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="copy" position="after">
|
||||
<field name="track_visibility" attrs="{'readonly': [('state','!=', 'manual')]}"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -129,7 +129,14 @@ class IrModel(models.Model):
|
||||
""" Return the (sudoed) `ir.model` record with the given name.
|
||||
The result may be an empty recordset if the model is not found.
|
||||
"""
|
||||
return self.sudo().search([('model', '=', name)])
|
||||
model_id = self._get_id(name) if name else False
|
||||
return self.sudo().browse(model_id)
|
||||
|
||||
@tools.ormcache('name')
|
||||
def _get_id(self, name):
|
||||
self.env.cr.execute("SELECT id FROM ir_model WHERE model=%s", (name,))
|
||||
result = self.env.cr.fetchone()
|
||||
return result and result[0]
|
||||
|
||||
# overridden to allow searching both on model name (field 'model') and model
|
||||
# description (field 'name')
|
||||
@@ -455,7 +462,15 @@ class IrModelFields(models.Model):
|
||||
""" Return the (sudoed) `ir.model.fields` record with the given model and name.
|
||||
The result may be an empty recordset if the model is not found.
|
||||
"""
|
||||
return self.sudo().search([('model', '=', model_name), ('name', '=', name)])
|
||||
field_id = self._get_id(model_name, name) if model_name and name else False
|
||||
return self.sudo().browse(field_id)
|
||||
|
||||
@tools.ormcache('model_name', 'name')
|
||||
def _get_id(self, model_name, name):
|
||||
self.env.cr.execute("SELECT id FROM ir_model_fields WHERE model=%s AND name=%s",
|
||||
(model_name, name))
|
||||
result = self.env.cr.fetchone()
|
||||
return result and result[0]
|
||||
|
||||
@api.multi
|
||||
def _drop_column(self):
|
||||
|
||||
Reference in New Issue
Block a user