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']