[FIX] mail: fix tracking formatting when having several models
In odoo/odoo@9c9552fd20 a support of tracking value belonging to another model than the message has been added. In such cases the formatting method written at odoo/odoo#124182 fails as it expects a single model for all tracking values it receives. When field is removed 'model' is False, and we fallback on mail_message model. Part-of: odoo/odoo#156571
This commit is contained in:
committed by
Thibault Delavallée
parent
b1d403c4b4
commit
0db60bf1c2
@@ -2605,8 +2605,8 @@ msgstr ""
|
||||
#. module: mail
|
||||
#: model:ir.model.fields,help:mail.field_mail_alias_domain__default_from
|
||||
msgid ""
|
||||
"Default from when it does not match outgoing server filters. Can be either a "
|
||||
"local-part e.g. 'notifications' either a complete email address e.g. "
|
||||
"Default from when it does not match outgoing server filters. Can be either a"
|
||||
" local-part e.g. 'notifications' either a complete email address e.g. "
|
||||
"'notifications@example.com' to override all outgoing emails."
|
||||
msgstr ""
|
||||
|
||||
@@ -9402,6 +9402,13 @@ msgstr ""
|
||||
msgid "Unit of delay"
|
||||
msgstr ""
|
||||
|
||||
#. module: mail
|
||||
#. odoo-python
|
||||
#: code:addons/mail/models/mail_tracking_value.py:0
|
||||
#, python-format
|
||||
msgid "Unknown"
|
||||
msgstr ""
|
||||
|
||||
#. module: mail
|
||||
#. odoo-python
|
||||
#: code:addons/mail/models/mail_notification.py:0
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from odoo import api, fields, models
|
||||
from odoo import api, fields, models, _
|
||||
|
||||
|
||||
class MailTracking(models.Model):
|
||||
@@ -112,34 +112,59 @@ class MailTracking(models.Model):
|
||||
to display tracking values. Order it according to asked display, aka
|
||||
ascending sequence (and field name).
|
||||
|
||||
:return list: for each tracking value in self, their formatted display
|
||||
values given as a dict;
|
||||
"""
|
||||
model_map = {}
|
||||
for tracking in self:
|
||||
model = tracking.field_id.model or tracking.mail_message_id.model
|
||||
model_map.setdefault(model, self.browse())
|
||||
model_map[model] += tracking
|
||||
formatted = []
|
||||
for model, trackings in model_map.items():
|
||||
formatted += trackings._tracking_value_format_model(model)
|
||||
return formatted
|
||||
|
||||
def _tracking_value_format_model(self, model):
|
||||
""" Return structure and formatted data structure to be used by chatter
|
||||
to display tracking values. Order it according to asked display, aka
|
||||
ascending sequence (and field name).
|
||||
|
||||
:return list: for each tracking value in self, their formatted display
|
||||
values given as a dict;
|
||||
"""
|
||||
if not self:
|
||||
return []
|
||||
field_models = self.field_id.mapped('model')
|
||||
if len(set(field_models)) != 1:
|
||||
raise ValueError('All tracking value should belong to the same model.')
|
||||
TrackedModel = self.env[field_models[0]]
|
||||
tracked_fields = TrackedModel.fields_get(self.field_id.mapped('name'), attributes={'string', 'type'})
|
||||
|
||||
# fetch model-based information
|
||||
if model:
|
||||
TrackedModel = self.env[model]
|
||||
tracked_fields = TrackedModel.fields_get(self.field_id.mapped('name'), attributes={'string', 'type'})
|
||||
model_sequence_info = dict(TrackedModel._mail_track_order_fields(tracked_fields)) if model else {}
|
||||
else:
|
||||
tracked_fields, model_sequence_info = {}, {}
|
||||
|
||||
# generate sequence of trackings
|
||||
fields_sequence_map = dict(
|
||||
{
|
||||
tracking.field_info['name']: tracking.field_info.get('sequence', 100)
|
||||
for tracking in self.filtered('field_info')
|
||||
},
|
||||
**model_sequence_info,
|
||||
)
|
||||
# generate dict of field information, if available
|
||||
fields_col_info = (
|
||||
tracked_fields.get(tracking.field_id.name) or {
|
||||
'string': tracking.field_info['desc'],
|
||||
'type': tracking.field_info['type'],
|
||||
}
|
||||
for tracking in self
|
||||
)
|
||||
fields_sequence_map = dict(
|
||||
{tracking.field_info['name']: tracking.field_info.get('sequence', 100)
|
||||
for tracking in self.filtered('field_info')},
|
||||
**dict(TrackedModel._mail_track_order_fields(tracked_fields))
|
||||
'string': tracking.field_info['desc'] if tracking.field_info else _('Unknown'),
|
||||
'type': tracking.field_info['type'] if tracking.field_info else 'char',
|
||||
} for tracking in self
|
||||
)
|
||||
|
||||
formatted = [
|
||||
{
|
||||
'changedField': col_info['string'],
|
||||
'id': tracking.id,
|
||||
'fieldName': tracking.field_id.name or tracking.field_info['name'],
|
||||
'fieldName': tracking.field_id.name or (tracking.field_info['name'] if tracking.field_info else 'unknown'),
|
||||
'fieldType': col_info['type'],
|
||||
'newValue': {
|
||||
'currencyId': tracking.currency_id.id,
|
||||
@@ -153,7 +178,7 @@ class MailTracking(models.Model):
|
||||
for tracking, col_info in zip(self, fields_col_info)
|
||||
]
|
||||
formatted.sort(
|
||||
key=lambda info: (fields_sequence_map[info['fieldName']], info['fieldName']),
|
||||
key=lambda info: (fields_sequence_map.get(info['fieldName'], 100), info['fieldName']),
|
||||
reverse=False,
|
||||
)
|
||||
return formatted
|
||||
|
||||
@@ -152,6 +152,16 @@ class MailTestTrackCompute(models.Model):
|
||||
partner_phone = fields.Char(related='partner_id.phone', tracking=True)
|
||||
|
||||
|
||||
class MailTestTrackGroups(models.Model):
|
||||
_name = 'mail.test.track.groups'
|
||||
_description = "Test tracking with groups"
|
||||
_inherit = ['mail.thread']
|
||||
|
||||
name = fields.Char(tracking=1)
|
||||
partner_id = fields.Many2one('res.partner', tracking=2, groups="base.group_user")
|
||||
secret = fields.Char(tracking=3, groups="base.group_user")
|
||||
|
||||
|
||||
class MailTestTrackMonetary(models.Model):
|
||||
_name = 'mail.test.track.monetary'
|
||||
_description = 'Test tracking monetary field'
|
||||
|
||||
@@ -50,6 +50,7 @@ access_mail_test_track_all,mail.test.track.all,model_mail_test_track_all,base.gr
|
||||
access_mail_test_track_all_m2m,mail.test.track.all.m2m,model_mail_test_track_all_m2m,base.group_user,1,1,1,1
|
||||
access_mail_test_track_all_o2m,mail.test.track.all.o2m,model_mail_test_track_all_o2m,base.group_user,1,1,1,1
|
||||
access_mail_test_track_compute,mail.test.track.compute,model_mail_test_track_compute,base.group_user,1,1,1,1
|
||||
access_mail_test_track_groups,mail.test.track.groups,model_mail_test_track_groups,base.group_user,1,1,1,1
|
||||
access_mail_test_track_monetary,mail.test.track.monetary,model_mail_test_track_monetary,base.group_user,1,1,1,1
|
||||
access_mail_test_track_selection_portal,mail.test.track.selection.portal,model_mail_test_track_selection,base.group_portal,0,0,0,0
|
||||
access_mail_test_track_selection_user,mail.test.track.selection.user,model_mail_test_track_selection,base.group_user,1,1,1,1
|
||||
|
||||
|
@@ -746,6 +746,84 @@ class TestTrackingInternals(MailCommon):
|
||||
test_record,
|
||||
)
|
||||
|
||||
@users('employee')
|
||||
def test_track_multi_models(self):
|
||||
""" Some models track value coming from another model e.g. when having
|
||||
a sub model (lines) on which some value should be tracked on a parent
|
||||
model. Test there is no model mismatch. """
|
||||
main_track = self.env['mail.test.track.all'].create({
|
||||
'name': 'Multi Models Tracking',
|
||||
'char_field': 'char_value',
|
||||
})
|
||||
self.flush_tracking()
|
||||
self.assertEqual(len(main_track.message_ids), 1)
|
||||
self.assertFalse(main_track.message_ids.tracking_value_ids)
|
||||
|
||||
sub_track = self.env['mail.test.track.groups'].create({
|
||||
'name': 'Groups',
|
||||
'secret': 'secret',
|
||||
})
|
||||
# some custom code generates tracking values on main_track
|
||||
main_track.message_post(
|
||||
body='Custom Log with Tracking',
|
||||
tracking_value_ids=[
|
||||
(0, 0, {
|
||||
'field_id': self.env['ir.model.fields']._get(sub_track._name, 'secret').id,
|
||||
'new_value_char': 'secret',
|
||||
'old_value_char': False,
|
||||
}),
|
||||
(0, 0, {
|
||||
'field_id': False,
|
||||
'new_value_integer': self.env.uid,
|
||||
'old_value_integer': False,
|
||||
}),
|
||||
(0, 0, {
|
||||
'field_id': False,
|
||||
'field_info': {
|
||||
'desc': 'Old integer',
|
||||
'name': 'Removed',
|
||||
'sequence': 35,
|
||||
'type': 'integer',
|
||||
},
|
||||
'new_value_integer': 35,
|
||||
'old_value_integer': 30,
|
||||
}),
|
||||
],
|
||||
)
|
||||
trackings = main_track.message_ids.sudo().tracking_value_ids
|
||||
self.assertEqual(len(trackings), 3)
|
||||
|
||||
# check formatting, as it fetches info on model
|
||||
formatted = trackings._tracking_value_format()
|
||||
self.assertEqual(
|
||||
formatted,
|
||||
[
|
||||
{
|
||||
'changedField': 'Secret',
|
||||
'id': trackings[0].id,
|
||||
'fieldName': 'secret',
|
||||
'fieldType': 'char',
|
||||
'newValue': {'currencyId': False, 'value': 'secret'},
|
||||
'oldValue': {'currencyId': False, 'value': False}
|
||||
}, {
|
||||
'changedField': 'Old integer',
|
||||
'id': trackings[2].id,
|
||||
'fieldName': 'Removed',
|
||||
'fieldType': 'integer',
|
||||
'newValue': {'currencyId': False, 'value': 35},
|
||||
'oldValue': {'currencyId': False, 'value': 30}
|
||||
}, {
|
||||
'changedField': 'Unknown',
|
||||
'id': trackings[1].id,
|
||||
'fieldName': 'unknown',
|
||||
'fieldType': 'char',
|
||||
'newValue': {'currencyId': False, 'value': False},
|
||||
'oldValue': {'currencyId': False, 'value': False}
|
||||
}
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@users('employee')
|
||||
def test_track_sequence(self):
|
||||
""" Update some tracked fields and check that the mail.tracking.value
|
||||
|
||||
Reference in New Issue
Block a user