Browse Source
[MIG] crm_deduplicate_acl: Migration to 11.0
[MIG] crm_deduplicate_acl: Migration to 11.0
* Don't overwrite code, but use inheritance system * Add testspull/721/head
Pedro M. Baeza
7 years ago
19 changed files with 194 additions and 300 deletions
-
2partner_deduplicate_acl/README.rst
-
1partner_deduplicate_acl/__init__.py
-
11partner_deduplicate_acl/__manifest__.py
-
18partner_deduplicate_acl/i18n/de.po
-
18partner_deduplicate_acl/i18n/es.po
-
62partner_deduplicate_acl/i18n/hr.po
-
54partner_deduplicate_acl/i18n/nl_NL.po
-
56partner_deduplicate_acl/i18n/pt_BR.po
-
17partner_deduplicate_acl/i18n/sk.po
-
18partner_deduplicate_acl/i18n/sl.po
-
57partner_deduplicate_acl/i18n/tr.po
-
3partner_deduplicate_acl/models/__init__.py
-
16partner_deduplicate_acl/models/res_partner.py
-
3partner_deduplicate_acl/tests/__init__.py
-
50partner_deduplicate_acl/tests/test_crm_deduplicate_acl.py
-
6partner_deduplicate_acl/views/base_partner_merge_view.xml
-
1partner_deduplicate_acl/wizards/__init__.py
-
94partner_deduplicate_acl/wizards/partner_merge.py
-
7partner_deduplicate_acl/wizards/partner_merge_view.xml
@ -1,4 +1,5 @@ |
|||||
# -*- coding: utf-8 -*- |
# -*- coding: utf-8 -*- |
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from . import models |
||||
from . import wizards |
from . import wizards |
@ -0,0 +1,3 @@ |
|||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from . import res_partner |
@ -0,0 +1,16 @@ |
|||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from odoo import api, models |
||||
|
|
||||
|
|
||||
|
class ResPartner(models.Model): |
||||
|
_inherit = 'res.partner' |
||||
|
|
||||
|
@api.returns('self', lambda value: value.id) |
||||
|
def message_post(self, *args, **kwargs): |
||||
|
"""Change user who is posting the message if set by context.""" |
||||
|
if self.env.context.get('message_post_user'): |
||||
|
obj = self.sudo(self.env.context['message_post_user']) |
||||
|
else: |
||||
|
obj = self |
||||
|
return super(ResPartner, obj).message_post(*args, **kwargs) |
@ -0,0 +1,3 @@ |
|||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from . import test_crm_deduplicate_acl |
@ -0,0 +1,50 @@ |
|||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from odoo import exceptions |
||||
|
from odoo.tests import common |
||||
|
|
||||
|
|
||||
|
class TestCrmDeduplicateAcl(common.TransactionCase): |
||||
|
def setUp(self): |
||||
|
super(TestCrmDeduplicateAcl, self).setUp() |
||||
|
self.partner_1 = self.env['res.partner'].create({ |
||||
|
'name': 'Partner 1', |
||||
|
'email': 'partner1@example.org', |
||||
|
'is_company': True, |
||||
|
'parent_id': False, |
||||
|
}) |
||||
|
self.partner_2 = self.partner_1.copy() |
||||
|
self.partner_2.write({ |
||||
|
'name': 'Partner 1', |
||||
|
'email': 'partner2@example.org' |
||||
|
}) |
||||
|
self.user = self.env['res.users'].create({ |
||||
|
'login': 'test_crm_deduplicate_acl', |
||||
|
'name': 'test_crm_deduplicate_acl', |
||||
|
'email': 'crm_deduplicate_acl@example.org', |
||||
|
'groups_id': [ |
||||
|
(4, self.env.ref('base.group_user').id), |
||||
|
(4, self.env.ref('base.group_partner_manager').id), |
||||
|
] |
||||
|
}) |
||||
|
self.wizard = self.env['base.partner.merge.automatic.wizard'].sudo( |
||||
|
self.user, |
||||
|
).create({ |
||||
|
'group_by_name': True, |
||||
|
}) |
||||
|
|
||||
|
def test_same_email_restriction(self): |
||||
|
self.wizard.action_start_manual_process() |
||||
|
with self.assertRaises(exceptions.UserError): |
||||
|
self.wizard.action_merge() |
||||
|
self.user.groups_id = [ |
||||
|
(4, self.env.ref('crm_deduplicate_acl.group_unrestricted').id), |
||||
|
] |
||||
|
# Now there shouldn't be error |
||||
|
self.wizard.action_merge() |
||||
|
# Check that the posted message has correct user |
||||
|
resulting_partner = (self.partner_1 + self.partner_2).exists() |
||||
|
self.assertEqual( |
||||
|
resulting_partner.message_ids[0].author_id, |
||||
|
self.user.partner_id, |
||||
|
) |
@ -1,4 +1,3 @@ |
|||||
# -*- coding: utf-8 -*- |
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
from . import partner_merge |
from . import partner_merge |
@ -1,87 +1,27 @@ |
|||||
# -*- coding: utf-8 -*- |
|
||||
# © 2016 Tecnativa, S.L. - Jairo Llopis |
|
||||
# © 2016 Tecnativa, S.L. - Vicent Cubells |
|
||||
|
# Copyright 2016 Tecnativa - Jairo Llopis |
||||
|
# Copyright 2016 Tecnativa - Vicent Cubells |
||||
|
# Copyright 2017 Tecnativa - Pedro M. Baeza |
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
from odoo import _, SUPERUSER_ID, models |
|
||||
from odoo.exceptions import UserError |
|
||||
import logging |
|
||||
|
|
||||
|
|
||||
_logger = logging.getLogger('base.partner.merge') |
|
||||
|
from odoo import models |
||||
|
|
||||
|
|
||||
class BasePartnerMergeAutomaticWizard(models.TransientModel): |
class BasePartnerMergeAutomaticWizard(models.TransientModel): |
||||
_inherit = "base.partner.merge.automatic.wizard" |
_inherit = "base.partner.merge.automatic.wizard" |
||||
|
|
||||
def _merge(self, partner_ids, dst_partner=None): |
def _merge(self, partner_ids, dst_partner=None): |
||||
""" private implementation of merge partner |
|
||||
:param partner_ids : ids of partner to merge |
|
||||
:param dst_partner : record of destination res.partner |
|
||||
|
"""Perform the operation as admin if you have unrestricted merge |
||||
|
rights to avoid the rise of exceptions. An special context key is |
||||
|
passed for preserving the message author. |
||||
""" |
""" |
||||
Partner = self.env['res.partner'] |
|
||||
partner_ids = Partner.browse(partner_ids).exists() |
|
||||
if len(partner_ids) < 2: |
|
||||
return |
|
||||
|
|
||||
if len(partner_ids) > 3: |
|
||||
raise UserError(_("For safety reasons, you cannot merge more than" |
|
||||
" 3 contacts together. You can re-open" |
|
||||
" the wizard several times if needed.")) |
|
||||
|
|
||||
# check if the list of partners to merge contains child/parent relation |
|
||||
child_ids = self.env['res.partner'] |
|
||||
for partner_id in partner_ids: |
|
||||
child_ids |= Partner.search( |
|
||||
[('id', 'child_of', [partner_id.id])]) - partner_id |
|
||||
if partner_ids & child_ids: |
|
||||
raise UserError(_("You cannot merge a contact with one" |
|
||||
" of his parent.")) |
|
||||
|
|
||||
user = self.env.user |
|
||||
|
|
||||
if SUPERUSER_ID != self.env.uid and not user.has_group( |
|
||||
'crm_deduplicate_acl.group_unrestricted') and\ |
|
||||
len(set(partner.email for partner in partner_ids)) > 1: |
|
||||
raise UserError(_("All contacts must have the same email." |
|
||||
" Only the Administrator can merge contacts" |
|
||||
" with different emails.")) |
|
||||
|
|
||||
# remove dst_partner from partners to merge |
|
||||
if dst_partner and dst_partner in partner_ids: |
|
||||
src_partners = partner_ids - dst_partner |
|
||||
|
if self.env.user.has_group('crm_deduplicate_acl.group_unrestricted'): |
||||
|
obj = self.sudo().with_context(message_post_user=self.env.uid) |
||||
|
if dst_partner: |
||||
|
dst_partner = dst_partner.with_context( |
||||
|
message_post_user=self.env.uid, |
||||
|
) |
||||
else: |
else: |
||||
ordered_partners = self._get_ordered_partner(partner_ids.ids) |
|
||||
dst_partner = ordered_partners[-1] |
|
||||
src_partners = ordered_partners[:-1] |
|
||||
_logger.info("dst_partner: %s", dst_partner.id) |
|
||||
|
|
||||
# FIXME: is it still required to make and exception for |
|
||||
# account.move.line since accounting v9.0 ? |
|
||||
if SUPERUSER_ID != self.env.uid and not user.has_group( |
|
||||
'crm_deduplicate_acl.group_unrestricted') and\ |
|
||||
'account.move.line' in self.env and\ |
|
||||
self.env[ |
|
||||
'account.move.line' |
|
||||
].sudo().search([('partner_id', 'in', [partner.id for |
|
||||
partner in src_partners |
|
||||
])]): |
|
||||
raise UserError(_("Only the destination contact may be linked to" |
|
||||
" existing Journal Items. Please ask the" |
|
||||
" Administrator if you need to merge several" |
|
||||
" contacts linked to existing Journal Items.")) |
|
||||
|
|
||||
# call sub methods to do the merge |
|
||||
self._update_foreign_keys(src_partners, dst_partner) |
|
||||
self._update_reference_fields(src_partners, dst_partner) |
|
||||
self._update_values(src_partners, dst_partner) |
|
||||
|
|
||||
_logger.info('(uid = %s) merged the partners %r with %s', |
|
||||
self._uid, src_partners.ids, dst_partner.id) |
|
||||
dst_partner.message_post(body='%s %s' % (_( |
|
||||
"Merged with the following partners:"), ", ".join( |
|
||||
'%s <%s> (ID %s)' % (p.name, p.email or 'n/a', p.id) |
|
||||
for p in src_partners))) |
|
||||
|
|
||||
# delete source partner, since they are merged |
|
||||
src_partners.unlink() |
|
||||
|
obj = self |
||||
|
return super(BasePartnerMergeAutomaticWizard, obj)._merge( |
||||
|
partner_ids, dst_partner=dst_partner, |
||||
|
) |
Write
Preview
Loading…
Cancel
Save
Reference in new issue