From c6003af73409e2cd124f641fb7714fefa9dc8b01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Thu, 27 Feb 2020 10:15:25 +0000 Subject: [PATCH] [IMP] event: set an explicit onchange on partner_id of registration RATIONALE Manual onchange is necessary because you spot an issue (or customer complains). Automatic update through computed feild is only there to try to add missing pieces of information but cannot decide which is the correct field value to keep. SPECIFICATIONS Keep an explicit onchange on partner_id. Rationale : if user explicitly changes the partner in interface, he wants to update the whole customer information. If partner_id is updated in code (e.g. updating your personal information after registeration in website_event_sale) fields with a value should not be reset as we do not know which one is the correct one. How it should behave as following * computed fields based on partner_id should only update missing information. Indeed automated code cannot decide which information is more accurate; * interface should allow to update all customer related information at once. We consider event users really want to update all fields Tests are added to ensure behavior is not modified without notice. LINKS Task ID 2089156 Community PR odoo/odoo#42911 --- addons/event/models/event_registration.py | 28 +++++++++-- addons/event/tests/test_event_flow.py | 60 +++++++++++++++++++++++ 2 files changed, 84 insertions(+), 4 deletions(-) diff --git a/addons/event/models/event_registration.py b/addons/event/models/event_registration.py index b9d88dab020..e22283172e2 100644 --- a/addons/event/models/event_registration.py +++ b/addons/event/models/event_registration.py @@ -31,10 +31,10 @@ class EventRegistration(models.Model): states={'done': [('readonly', True)]}) name = fields.Char( string='Attendee Name', index=True, - compute='_compute_contact_info', copy=True, readonly=False, store=True, tracking=True) - email = fields.Char(string='Email', compute='_compute_contact_info', copy=True, readonly=False, store=True) - phone = fields.Char(string='Phone', compute='_compute_contact_info', copy=True, readonly=False, store=True) - mobile = fields.Char(string='Mobile', compute='_compute_contact_info', copy=True, readonly=False, store=True) + compute='_compute_contact_info', copy=True, readonly=False, store=True, tracking=10) + email = fields.Char(string='Email', compute='_compute_contact_info', copy=True, readonly=False, store=True, tracking=11) + phone = fields.Char(string='Phone', compute='_compute_contact_info', copy=True, readonly=False, store=True, tracking=12) + mobile = fields.Char(string='Mobile', compute='_compute_contact_info', copy=True, readonly=False, store=True, tracking=13) # organization date_open = fields.Datetime(string='Registration Date', readonly=True, default=lambda self: fields.Datetime.now()) # weird crash is directly now date_closed = fields.Datetime( @@ -50,6 +50,26 @@ class EventRegistration(models.Model): ('open', 'Confirmed'), ('done', 'Attended')], string='Status', default='draft', readonly=True, copy=False, tracking=True) + @api.onchange('partner_id') + def _onchange_partner_id(self): + """ Keep an explicit onchange on partner_id. Rationale : if user explicitly + changes the partner in interface, he want to update the whole customer + information. If partner_id is updated in code (e.g. updating your personal + information after having registered in website_event_sale) fields with a + value should not be reset as we don't know which one is the right one. + + In other words + * computed fields based on partner_id should only update missing + information. Indeed automated code cannot decide which information + is more accurate; + * interface should allow to update all customer related information + at once. We consider event users really want to update all fields + related to the partner; + """ + for registration in self: + if registration.partner_id: + registration.update(registration._synchronize_partner_values(registration.partner_id)) + @api.depends('partner_id') def _compute_contact_info(self): for registration in self: diff --git a/addons/event/tests/test_event_flow.py b/addons/event/tests/test_event_flow.py index 1ec9208e1b3..ff114bb4196 100644 --- a/addons/event/tests/test_event_flow.py +++ b/addons/event/tests/test_event_flow.py @@ -7,9 +7,69 @@ from dateutil.relativedelta import relativedelta from odoo.addons.event.tests.common import TestEventCommon from odoo.exceptions import ValidationError +from odoo.tests.common import Form from odoo.tools import mute_logger +class TestEventUI(TestEventCommon): + + def test_event_registration_partner_sync(self): + """ Ensure onchange on partner_id is kept for interface, not for computed + fields. """ + registration_form = Form(self.env['event.registration'].with_context( + default_name='WrongName', + default_event_id=self.event_0.id + )) + self.assertEqual(registration_form.event_id, self.event_0) + self.assertEqual(registration_form.name, 'WrongName') + self.assertFalse(registration_form.email) + self.assertFalse(registration_form.phone) + self.assertFalse(registration_form.mobile) + + # trigger onchange + registration_form.partner_id = self.customer + self.assertEqual(registration_form.name, self.customer.name) + self.assertEqual(registration_form.email, self.customer.email) + self.assertEqual(registration_form.phone, self.customer.phone) + self.assertEqual(registration_form.mobile, self.customer.mobile) + + # save, check record matches Form values + registration = registration_form.save() + self.assertEqual(registration.partner_id, self.customer) + self.assertEqual(registration.name, self.customer.name) + self.assertEqual(registration.email, self.customer.email) + self.assertEqual(registration.phone, self.customer.phone) + self.assertEqual(registration.mobile, self.customer.mobile) + + # allow writing on some fields independently from customer config + registration.write({'phone': False, 'mobile': False}) + self.assertFalse(registration.phone) + self.assertFalse(registration.mobile) + + # reset partner should not reset other fields + registration.write({'partner_id': False}) + self.assertEqual(registration.partner_id, self.env['res.partner']) + self.assertEqual(registration.name, self.customer.name) + self.assertEqual(registration.email, self.customer.email) + self.assertFalse(registration.phone) + self.assertFalse(registration.mobile) + + # update to a new partner not through UI -> update only void feilds + customer2 = self.env['res.partner'].create({ + 'name': 'Constantin Customer 2', + 'email': 'constantin2@test.example.com', + 'country_id': self.env.ref('base.be').id, + 'phone': '0456987654', + 'mobile': '0456654321', + }) + registration.write({'partner_id': customer2.id}) + self.assertEqual(registration.partner_id, customer2) + self.assertEqual(registration.name, self.customer.name) + self.assertEqual(registration.email, self.customer.email) + self.assertEqual(registration.phone, customer2.phone) + self.assertEqual(registration.mobile, customer2.mobile) + + class TestEventFlow(TestEventCommon): @mute_logger('odoo.addons.base.models.ir_model', 'odoo.models')