From ec35eca7c6b772139c8fa143b388ad1d936bc9ea Mon Sep 17 00:00:00 2001 From: lejeune quentin Date: Mon, 4 Jun 2018 14:09:14 +0200 Subject: [PATCH] [IMP] mail : Add possiblities to sequence tracking fields in the chatter Fields in the chatter can be organized with a business logic. Here fields for CRM and Website E-commerce have a tracking sequence. For other fields/module just add "track_sequence=x" on model --- addons/crm/models/crm_lead.py | 12 ++++++------ addons/mail/models/mail_thread.py | 3 ++- addons/mail/models/mail_tracking_value.py | 7 +++++-- addons/mail/views/mail_tracking_views.xml | 1 + addons/sale/models/sale.py | 10 +++++----- addons/test_mail/models/test_mail_models.py | 4 ++-- addons/test_mail/tests/test_message_track.py | 15 +++++++++++++++ 7 files changed, 36 insertions(+), 16 deletions(-) diff --git a/addons/crm/models/crm_lead.py b/addons/crm/models/crm_lead.py index 756a9f272a4..381e931ad86 100644 --- a/addons/crm/models/crm_lead.py +++ b/addons/crm/models/crm_lead.py @@ -63,23 +63,23 @@ class Lead(models.Model): return self._stage_find(team_id=team.id, domain=[('fold', '=', False)]).id name = fields.Char('Opportunity', required=True, index=True) - partner_id = fields.Many2one('res.partner', string='Customer', track_visibility='onchange', index=True, + partner_id = fields.Many2one('res.partner', string='Customer', track_visibility='onchange', track_sequence=1, index=True, help="Linked partner (optional). Usually created when converting the lead.") active = fields.Boolean('Active', default=True) date_action_last = fields.Datetime('Last Action', readonly=True) - email_from = fields.Char('Email', help="Email address of the contact", index=True) + email_from = fields.Char('Email', help="Email address of the contact", track_visibility='onchange', track_sequence=4, index=True) website = fields.Char('Website', index=True, help="Website of the contact") team_id = fields.Many2one('crm.team', string='Sales Channel', oldname='section_id', default=lambda self: self.env['crm.team'].sudo()._get_default_team_id(user_id=self.env.uid), index=True, track_visibility='onchange', help='When sending mails, the default email address is taken from the sales channel.') kanban_state = fields.Selection([('grey', 'No next activity planned'), ('red', 'Next activity late'), ('green', 'Next activity is planned')], string='Kanban State', compute='_compute_kanban_state') email_cc = fields.Text('Global CC', help="These email addresses will be added to the CC field of all inbound and outbound emails for this record before being sent. Separate multiple email addresses with a comma") - description = fields.Text('Notes') + description = fields.Text('Notes', track_visibility='onchange', track_sequence=6) create_date = fields.Datetime('Create Date', readonly=True) write_date = fields.Datetime('Update Date', readonly=True) tag_ids = fields.Many2many('crm.lead.tag', 'crm_lead_tag_rel', 'lead_id', 'tag_id', string='Tags', help="Classify and analyze your lead/opportunity categories like: Training, Service") - contact_name = fields.Char('Contact Name') - partner_name = fields.Char("Customer Name", index=True, help='The name of the future partner company that will be created while converting the lead into opportunity') + contact_name = fields.Char('Contact Name', track_visibility='onchange', track_sequence=3) + partner_name = fields.Char("Customer Name", track_visibility='onchange', track_sequence=2, index=True, help='The name of the future partner company that will be created while converting the lead into opportunity') opt_out = fields.Boolean(string='Opt-Out', oldname='optout', help="If opt-out is checked, this contact has refused to receive emails for mass mailing and marketing campaign. " "Filter 'Available for Mass Mailing' allows users to filter the leads when performing mass mailing.") @@ -124,7 +124,7 @@ class Lead(models.Model): city = fields.Char('City') state_id = fields.Many2one("res.country.state", string='State') country_id = fields.Many2one('res.country', string='Country') - phone = fields.Char('Phone') + phone = fields.Char('Phone', track_visibility='onchange', track_sequence=5) mobile = fields.Char('Mobile') function = fields.Char('Job Position') title = fields.Many2one('res.partner.title') diff --git a/addons/mail/models/mail_thread.py b/addons/mail/models/mail_thread.py index 13c4c65e9a5..fe08600259d 100644 --- a/addons/mail/models/mail_thread.py +++ b/addons/mail/models/mail_thread.py @@ -592,7 +592,8 @@ class MailThread(models.AbstractModel): new_value = getattr(self, col_name) if new_value != initial_value and (new_value or initial_value): # because browse null != False - tracking = self.env['mail.tracking.value'].create_tracking_values(initial_value, new_value, col_name, col_info) + track_sequence = getattr(self._fields[col_name], 'track_sequence', 100) + tracking = self.env['mail.tracking.value'].create_tracking_values(initial_value, new_value, col_name, col_info, track_sequence) if tracking: tracking_value_ids.append([0, 0, tracking]) diff --git a/addons/mail/models/mail_tracking_value.py b/addons/mail/models/mail_tracking_value.py index 5fbe63d6a14..5e758c45482 100644 --- a/addons/mail/models/mail_tracking_value.py +++ b/addons/mail/models/mail_tracking_value.py @@ -9,6 +9,7 @@ from odoo import api, fields, models, tools class MailTracking(models.Model): _name = 'mail.tracking.value' _description = 'Mail Tracking Value' + _order = 'track_sequence asc' # TDE CLEANME: why not a m2o to ir model field ? field = fields.Char('Changed Field', required=True, readonly=1) @@ -31,10 +32,12 @@ class MailTracking(models.Model): mail_message_id = fields.Many2one('mail.message', 'Message ID', required=True, index=True, ondelete='cascade') + track_sequence = fields.Integer('Tracking field sequence', readonly=1, default=100) + @api.model - def create_tracking_values(self, initial_value, new_value, col_name, col_info): + def create_tracking_values(self, initial_value, new_value, col_name, col_info, track_sequence): tracked = True - values = {'field': col_name, 'field_desc': col_info['string'], 'field_type': col_info['type']} + values = {'field': col_name, 'field_desc': col_info['string'], 'field_type': col_info['type'], 'track_sequence': track_sequence} if col_info['type'] in ['integer', 'float', 'char', 'text', 'datetime', 'monetary']: values.update({ diff --git a/addons/mail/views/mail_tracking_views.xml b/addons/mail/views/mail_tracking_views.xml index ea120a30ec4..cd98078848f 100644 --- a/addons/mail/views/mail_tracking_views.xml +++ b/addons/mail/views/mail_tracking_views.xml @@ -45,6 +45,7 @@ + diff --git a/addons/sale/models/sale.py b/addons/sale/models/sale.py index c4e39ab3768..18452106d23 100644 --- a/addons/sale/models/sale.py +++ b/addons/sale/models/sale.py @@ -122,15 +122,15 @@ class SaleOrder(models.Model): ('sale', 'Sales Order'), ('done', 'Locked'), ('cancel', 'Cancelled'), - ], string='Status', readonly=True, copy=False, index=True, track_visibility='onchange', default='draft') + ], string='Status', readonly=True, copy=False, index=True, track_visibility='onchange', track_sequence=3, default='draft') date_order = fields.Datetime(string='Order Date', required=True, readonly=True, index=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, copy=False, default=fields.Datetime.now) validity_date = fields.Date(string='Quote Validity', readonly=True, copy=False, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, help="Validity date of the quotation, after this date, the customer won't be able to validate the quotation online.") is_expired = fields.Boolean(compute='_compute_is_expired', string="Is expired") create_date = fields.Datetime(string='Creation Date', readonly=True, index=True, help="Date on which sales order is created.") confirmation_date = fields.Datetime(string='Confirmation Date', readonly=True, index=True, help="Date on which the sales order is confirmed.", oldname="date_confirm", copy=False) - user_id = fields.Many2one('res.users', string='Salesperson', index=True, track_visibility='onchange', default=lambda self: self.env.user) - partner_id = fields.Many2one('res.partner', string='Customer', readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, required=True, change_default=True, index=True, track_visibility='always') + user_id = fields.Many2one('res.users', string='Salesperson', index=True, track_visibility='onchange', track_sequence=2, default=lambda self: self.env.user) + partner_id = fields.Many2one('res.partner', string='Customer', readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, required=True, change_default=True, index=True, track_visibility='always', track_sequence=1) partner_invoice_id = fields.Many2one('res.partner', string='Invoice Address', readonly=True, required=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)], 'sale': [('readonly', False)]}, help="Invoice address for current sales order.") partner_shipping_id = fields.Many2one('res.partner', string='Delivery Address', readonly=True, required=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)], 'sale': [('readonly', False)]}, help="Delivery address for current sales order.") @@ -151,9 +151,9 @@ class SaleOrder(models.Model): note = fields.Text('Terms and conditions', default=_default_note) - amount_untaxed = fields.Monetary(string='Untaxed Amount', store=True, readonly=True, compute='_amount_all', track_visibility='onchange') + amount_untaxed = fields.Monetary(string='Untaxed Amount', store=True, readonly=True, compute='_amount_all', track_visibility='onchange', track_sequence=5) amount_tax = fields.Monetary(string='Taxes', store=True, readonly=True, compute='_amount_all') - amount_total = fields.Monetary(string='Total', store=True, readonly=True, compute='_amount_all', track_visibility='always') + amount_total = fields.Monetary(string='Total', store=True, readonly=True, compute='_amount_all', track_visibility='always', track_sequence=6) payment_term_id = fields.Many2one('account.payment.term', string='Payment Terms', oldname='payment_term') fiscal_position_id = fields.Many2one('account.fiscal.position', oldname='fiscal_position', string='Fiscal Position') diff --git a/addons/test_mail/models/test_mail_models.py b/addons/test_mail/models/test_mail_models.py index 06d84986fe8..04c1253e280 100644 --- a/addons/test_mail/models/test_mail_models.py +++ b/addons/test_mail/models/test_mail_models.py @@ -60,8 +60,8 @@ class MailTestFull(models.Model): count = fields.Integer(default=1) datetime = fields.Datetime(default=fields.Datetime.now) mail_template = fields.Many2one('mail.template', 'Template') - customer_id = fields.Many2one('res.partner', 'Customer', track_visibility='onchange') - user_id = fields.Many2one('res.users', 'Responsible', track_visibility='onchange') + customer_id = fields.Many2one('res.partner', 'Customer', track_visibility='onchange', track_sequence=2) + user_id = fields.Many2one('res.users', 'Responsible', track_visibility='onchange', track_sequence=1) umbrella_id = fields.Many2one('mail.test', track_visibility='onchange') def _track_template(self, tracking): diff --git a/addons/test_mail/tests/test_message_track.py b/addons/test_mail/tests/test_message_track.py index 8887698594e..faae6afcd57 100644 --- a/addons/test_mail/tests/test_message_track.py +++ b/addons/test_mail/tests/test_message_track.py @@ -116,3 +116,18 @@ class TestTracking(common.BaseFunctionalTest, common.MockEmails): self.record.message_ids[1], [('customer_id', 'many2one', False, self.user_admin.partner_id) # onchange tracked field ]) + + def test_message_track_sequence(self): + """ Update some tracked fields and check that the mail.tracking.value are ordered according to their track_sequence""" + self.record.write({ + 'name': 'Zboub', + 'customer_id': self.user_admin.partner_id.id, + 'user_id': self.user_admin.id, + 'umbrella_id': self.env['mail.test'].with_context(mail_create_nosubscribe=True).create({'name': 'Umbrella'}).id + }) + self.assertEqual(len(self.record.message_ids), 1, 'should have 1 tracking message') + + tracking_values = self.env['mail.tracking.value'].search([('mail_message_id', '=', self.record.message_ids.id)]) + self.assertEqual(tracking_values[0].track_sequence, 1) + self.assertEqual(tracking_values[1].track_sequence, 2) + self.assertEqual(tracking_values[2].track_sequence, 100)