[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:
Raphael Collet
2017-02-28 10:49:02 +01:00
committed by GitHub
parent 2a2b64f079
commit 1119fdd8a3
5 changed files with 123 additions and 2 deletions
+1
View File
@@ -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': [
+1
View File
@@ -18,4 +18,5 @@ import res_config
import update
import ir_actions
import ir_autovacuum
import ir_model
import html2text
+67
View File
@@ -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
+37
View File
@@ -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>
+17 -2
View File
@@ -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):