From 035057a5224e5d57feb176bebf199a45541b5149 Mon Sep 17 00:00:00 2001 From: Renaud Thiry Date: Wed, 8 Mar 2023 12:09:41 +0000 Subject: [PATCH] [IMP] mail: track contact address MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently there is no way of knowing who changed the address of a partner. This field is of high importance and should be tracked to be able to follow who is editing it. As addresses are represented with a bunch of fields, tracking them individually would result in weird-looking tracking messages with each value stacked on top of the other. To avoid this, we take advantage of the fact that tracking can be used on non-stored compute fields to log any change as a change over the full address. The full address is derived from the contact_address field to take advantage of the existing regional formatting of addresses. It is however modified to replace return to lines with commas to accomodate the formatting of tracking messages in the front-end. task-3165293 closes odoo/odoo#114695 Signed-off-by: Warnon Aurélien (awa) --- addons/mail/models/res_partner.py | 12 +++++++++ addons/mail/tests/test_res_partner.py | 39 +++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/addons/mail/models/res_partner.py b/addons/mail/models/res_partner.py index 98eeccb79ed..516ffa9cb23 100644 --- a/addons/mail/models/res_partner.py +++ b/addons/mail/models/res_partner.py @@ -1,6 +1,8 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. +import re + from odoo import _, api, fields, models, tools from odoo.osv import expression @@ -20,6 +22,16 @@ class Partner(models.Model): vat = fields.Char(tracking=5) # channels channel_ids = fields.Many2many('mail.channel', 'mail_channel_member', 'partner_id', 'channel_id', string='Channels', copy=False) + # tracked field used for chatter logging purposes + # we need this to be readable inline as tracking messages use inline HTML nodes + contact_address_inline = fields.Char(compute='_compute_contact_address_inline', string='Inlined Complete Address', tracking=True) + + @api.depends('contact_address') + def _compute_contact_address_inline(self): + """Compute an inline-friendly address based on contact_address.""" + for partner in self: + # replace any successive \n with a single comma + partner.contact_address_inline = re.sub(r'\n(\s|\n)*', ', ', partner.contact_address).strip().strip(',') def _compute_im_status(self): super()._compute_im_status() diff --git a/addons/mail/tests/test_res_partner.py b/addons/mail/tests/test_res_partner.py index 1ebfdb2f235..0590df65092 100644 --- a/addons/mail/tests/test_res_partner.py +++ b/addons/mail/tests/test_res_partner.py @@ -90,6 +90,45 @@ class TestPartner(MailCommon): self.assertEqual(parsed[0], expected_name) self.assertEqual(parsed[1], expected_email) + + def test_res_partner_address_tracking(self): + company_partner = self.env.company.partner_id + # use some wacky formatting to check inlining + company_partner.country_id.address_format = """%(street)s + \n\n\n%(street2)s + %(city)s %(state_code)s %(zip)s + \n%(country_name)s\n + \n """ + company_partner.write({ + 'city': 'Some City Name', + 'street': 'Some Street Name', + 'type': 'contact', + }) + child_partner = self.env['res.partner'].create({ + 'name': 'Some Guy', + 'parent_id': company_partner.id, + }) + self.env.flush_all() + self.cr.precommit.run() + # keep track of setup messages + partners = (company_partner, child_partner) + partner_original_messages = (company_partner.message_ids, child_partner.message_ids) + + company_partner.street = 'Some Other Street Name' + company_partner.city = 'Some Other City Name' + self.env.flush_all() + self.cr.precommit.run() + for partner, original_messages in zip(partners, partner_original_messages): + change_messages = partner.message_ids - original_messages + self.assertEqual(len(change_messages), 1) + tracking_values = change_messages.tracking_value_ids + self.assertIn('YourCompany, Some Street Name, Some City Name CA 94134, United States', + tracking_values._get_old_display_value()) + self.assertIn('YourCompany, Some Other Street Name, Some Other City Name CA 94134, United States', + tracking_values._get_new_display_value()) + # none of the address fields are logged at the same time + self.assertEqual(set(), set(partner._address_fields()) & set(tracking_values.sudo().field.mapped('name'))) + def test_res_partner_find_or_create(self): PartnerModel = self.env['res.partner']