diff --git a/odoo/addons/base/models/res_partner.py b/odoo/addons/base/models/res_partner.py
index 1fb043ed1f4..8880b11ca54 100644
--- a/odoo/addons/base/models/res_partner.py
+++ b/odoo/addons/base/models/res_partner.py
@@ -235,6 +235,13 @@ class Partner(models.Model):
('check_name', "CHECK( (type='contact' AND name IS NOT NULL) or (type!='contact') )", 'Contacts require a name.'),
]
+ @api.multi
+ def toggle_active(self):
+ for partner in self:
+ if partner.active and partner.user_ids:
+ raise ValidationError(_('You cannot archive a contact linked to an internal user.'))
+ super(Partner, self).toggle_active()
+
@api.depends('is_company', 'name', 'parent_id.name', 'type', 'company_name')
def _compute_display_name(self):
diff = dict(show_address=None, show_address_only=None, show_email=None)
@@ -487,6 +494,10 @@ class Partner(models.Model):
@api.multi
def write(self, vals):
+ if vals.get('active') is False:
+ for partner in self:
+ if partner.active and partner.user_ids:
+ raise ValidationError(_('You cannot archive a contact linked to an internal user.'))
# res.partner must only allow to set the company_id of a partner if it
# is the same as the company of all users that inherit from this partner
# (this is to allow the code from res_users to write to the partner!) or
diff --git a/odoo/addons/base/models/res_users.py b/odoo/addons/base/models/res_users.py
index 68ba869b56e..9d31cf72bf8 100644
--- a/odoo/addons/base/models/res_users.py
+++ b/odoo/addons/base/models/res_users.py
@@ -356,6 +356,13 @@ class Users(models.Model):
if action_open_website and any(user.action_id.id == action_open_website.id for user in self):
raise ValidationError(_('The "App Switcher" action cannot be selected as home action.'))
+ @api.multi
+ def toggle_active(self):
+ for user in self:
+ if not user.active and not user.partner_id.active:
+ user.partner_id.toggle_active()
+ super(Users, self).toggle_active()
+
@api.multi
def read(self, fields=None, load='_classic_read'):
if fields and self == self.env.user:
@@ -412,6 +419,10 @@ class Users(models.Model):
elif user.id == self._uid:
raise UserError(_("You cannot deactivate the user you're currently logged in as."))
+ if values.get('active'):
+ for user in self:
+ if not user.active and not user.partner_id.active:
+ user.partner_id.toggle_active()
if self == self.env.user:
for key in list(values):
if not (key in self.SELF_WRITEABLE_FIELDS or key.startswith('context_')):
diff --git a/odoo/addons/base/tests/test_base.py b/odoo/addons/base/tests/test_base.py
index 5b8955828c0..69b9bbdeb8f 100644
--- a/odoo/addons/base/tests/test_base.py
+++ b/odoo/addons/base/tests/test_base.py
@@ -396,6 +396,27 @@ class TestBase(TransactionCase):
self.assertEqual([2, 4], [g['title_count'] for g in groups_data], 'Incorrect number of results')
self.assertEqual([-1, 10], [g['color'] for g in groups_data], 'Incorrect aggregation of int column')
+ def test_70_archive_internal_partners(self):
+ test_partner = self.env['res.partner'].create({'name':'test partner'})
+ test_user = self.env['res.users'].create({
+ 'login': 'test@odoo.com',
+ 'partner_id': test_partner.id,
+ })
+ # Cannot archive the partner
+ with self.assertRaises(ValidationError):
+ test_partner.toggle_active()
+
+ # Can archive the user but the partner stays active
+ test_user.toggle_active()
+ self.assertTrue(test_partner.active, 'Parter related to user should remain active')
+
+ # Now we can archive the partner
+ test_partner.toggle_active()
+
+ # Activate the user should reactivate the partner
+ test_user.toggle_active()
+ self.assertTrue(test_partner.active, 'Activating user must active related partner')
+
class TestPartnerRecursion(TransactionCase):
diff --git a/odoo/addons/base/views/res_users_views.xml b/odoo/addons/base/views/res_users_views.xml
index 4e7f9420839..ed7dc49bff5 100644
--- a/odoo/addons/base/views/res_users_views.xml
+++ b/odoo/addons/base/views/res_users_views.xml
@@ -162,6 +162,15 @@