[FIX] crm_lead: improve synchronization between lead and partner_id

PURPOSE

Distinguish synchronization of partner values on lead: address fields (all
or none), classic fields (propagate if set) and special cases (names-alike).

SPECIFICATIONS

Follow up of https://github.com/odoo/odoo/commit/f8179007f9aa662be7318edeb18426ea1c906c15

Context: many fields are now synchronized from the partner_id: address fields
as well as other contact fields. A first commit 9c9f477f04e8f4ee9b18092fe894890c2ab31b58 kept the value
from the lead if the value from the partner was empty. This lead to mixed
address fields.

A second commit fixed that behavior f8179007f9aa662be7318edeb18426ea1c906c15 by taking the value from
the partner only when it was set.

Problem: This erases too much information.

```
>>> lead.partner_name
'testtest'
>>> partner_id.name
'testtest@mailinator.com'
>>> partner_id.parent_id
res.partner()
>>> partner_id.is_company
False
>>> lead.write({'partner_id': partner_id.id})
>>> lead.partner_name
False
```

We indeed need a consistent address but for the other fields we want to keep
the maximum of data.

SOLUTION

For the address fields, take all the values from the partner if one of the
address fields is defined, otherwise keep the information defined on the lead.
For all the other fields keep the lead information if the partner information
is empty.

LINKS

Task ID-2316828
PR #55825
X-original-commit https://github.com/odoo/odoo/pull/55194/commits/f53fba6663a34e8e6b13354dde3dc225f5814de3
X-original-PR #55194

X-original-commit: b136df8530279a54c9be96beeea9bdda01643000
This commit is contained in:
Thibault Francois
2020-08-13 07:43:28 +00:00
committed by Thibault Delavallée
parent 0158fd90f7
commit 6ea7a9a975
2 changed files with 82 additions and 18 deletions
+24 -10
View File
@@ -48,17 +48,22 @@ CRM_LEAD_FIELDS_TO_MERGE = [
'email_cc',
'website']
# Subset of partner fields: sync any of those
PARTNER_FIELDS_TO_SYNC = [
'mobile',
'title',
'function',
'website',
]
# Subset of partner fields: sync all or none to avoid mixed addresses
PARTNER_ADDRESS_FIELDS_TO_SYNC = [
'street',
'street2',
'city',
'zip',
'state_id',
'country_id',
'mobile',
'zip',
'function',
'website',
]
# Those values have been determined based on benchmark to minimise
@@ -429,18 +434,27 @@ class Lead(models.Model):
self.mobile = self.phone_format(self.mobile)
def _prepare_values_from_partner(self, partner):
""" Get a dictionary with values coming from customer information to
copy on a lead. Email_from and phone fields get the current lead
values to avoid being reset if customer has no value for them. """
""" Get a dictionary with values coming from partner information to
copy on a lead. Non-address fields get the current lead
values to avoid being reset if partner has no value for them. """
# Sync all address fields from partner, or none, to avoid mixing them.
if any(partner[f] for f in PARTNER_ADDRESS_FIELDS_TO_SYNC):
values = {f: partner[f] for f in PARTNER_ADDRESS_FIELDS_TO_SYNC}
else:
values = {f: self[f] for f in PARTNER_ADDRESS_FIELDS_TO_SYNC}
# For other fields, get the info from the partner, but only if set
values.update({f: partner[f] or self[f] for f in PARTNER_FIELDS_TO_SYNC})
# Fields with specific logic
partner_name = partner.parent_id.name
if not partner_name and partner.is_company:
partner_name = partner.name
contact_name = False if partner.is_company else partner.name
values = {f: partner[f] if partner else self[f] for f in PARTNER_FIELDS_TO_SYNC}
values.update({
'partner_name': partner_name or self.partner_name,
'contact_name': False if partner.is_company else partner.name or self.contact_name,
'contact_name': contact_name or self.contact_name,
})
return self._convert_to_write(values)
+58 -8
View File
@@ -59,24 +59,74 @@ class TestCRMLead(TestCrmCommon):
self.assertEqual(lead.zip, self.contact_1.zip)
self.assertEqual(lead.country_id, self.contact_1.country_id)
def test_crm_lead_creation_partner_no_info(self):
def test_crm_lead_creation_partner_address(self):
""" Test that an address erases all lead address fields (avoid mixed addresses) """
other_country = self.env.ref('base.fr')
empty_partner = self.env['res.partner'].create({
'name': 'Empty partner',
'is_company': True
'country_id': other_country.id,
})
lead_data = {
'name': 'Test',
'street': 'My street',
'street2': 'My street',
'city': 'My city',
'zip': 'test@odoo.com',
'state_id': self.env['res.country.state'].create({
'name': 'My state',
'country_id': self.country_ref.id,
'code': 'MST',
}).id,
'country_id': self.country_ref.id,
'email_from': self.test_email,
'phone': self.test_phone,
}
lead = self.env['crm.lead'].create(lead_data)
lead.partner_id = empty_partner
self.assertEqual(lead.country_id, self.env['res.country'], "Country should be empty")
self.assertEqual(lead.contact_name, False, "Contact name should be empty")
self.assertEqual(lead.email_from, self.test_email, "Email From should keep its initial value")
self.assertEqual(lead.phone, self.test_phone, "Phone should keep its initial value")
# PARTNER_ADDRESS_FIELDS_TO_SYNC
self.assertEqual(lead.street, empty_partner.street, "Street should be sync from the Partner")
self.assertEqual(lead.street2, empty_partner.street2, "Street 2 should be sync from the Partner")
self.assertEqual(lead.city, empty_partner.city, "City should be sync from the Partner")
self.assertEqual(lead.zip, empty_partner.zip, "Zip should be sync from the Partner")
self.assertEqual(lead.state_id, empty_partner.state_id, "State should be sync from the Partner")
self.assertEqual(lead.country_id, empty_partner.country_id, "Country should be sync from the Partner")
def test_crm_lead_creation_partner_no_address(self):
""" Test that an empty address on partner does not void its lead values """
empty_partner = self.env['res.partner'].create({
'name': 'Empty partner',
'is_company': True,
'mobile': '123456789',
'title': self.env.ref('base.res_partner_title_mister').id,
'function': 'My function',
})
lead_data = {
'name': 'Test',
'contact_name': 'Test',
'street': 'My street',
'country_id': self.country_ref.id,
'email_from': self.test_email,
'phone': self.test_phone,
'mobile': '987654321',
'website': 'http://mywebsite.org',
}
lead = self.env['crm.lead'].create(lead_data)
lead.partner_id = empty_partner
# SPECIFIC FIELDS
self.assertEqual(lead.contact_name, lead_data['contact_name'], "Contact should remain")
self.assertEqual(lead.email_from, lead_data['email_from'], "Email From should keep its initial value")
self.assertEqual(lead.partner_name, empty_partner.name, "Partner name should be set as contact is a company")
# PARTNER_ADDRESS_FIELDS_TO_SYNC
self.assertEqual(lead.street, lead_data['street'], "Street should remain since partner has no address field set")
self.assertEqual(lead.street2, False, "Street2 should remain since partner has no address field set")
self.assertEqual(lead.country_id, self.country_ref, "Country should remain since partner has no address field set")
self.assertEqual(lead.city, False, "City should remain since partner has no address field set")
self.assertEqual(lead.zip, False, "Zip should remain since partner has no address field set")
self.assertEqual(lead.state_id, self.env['res.country.state'], "State should remain since partner has no address field set")
# PARTNER_FIELDS_TO_SYNC
self.assertEqual(lead.phone, lead_data['phone'], "Phone should keep its initial value")
self.assertEqual(lead.mobile, empty_partner.mobile, "Mobile from partner should be set on the lead")
self.assertEqual(lead.title, empty_partner.title, "Title from partner should be set on the lead")
self.assertEqual(lead.function, empty_partner.function, "Function from partner should be set on the lead")
self.assertEqual(lead.website, lead_data['website'], "Website should keep its initial value")
@users('user_sales_manager')
def test_crm_lead_partner_sync(self):