[WIP] Merge partners

This commit is contained in:
Dario Lodeiros
2019-02-07 11:34:53 +01:00
parent df6feb25b0
commit bd9269849b

View File

@@ -1,15 +1,13 @@
# Copyright 2017 Alexandre Díaz # Copyright 2017 Alexandre Díaz
# Copyright 2017 Dario Lodeiros # Copyright 2017 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from ast import literal_eval
import functools import functools
import itertools import itertools
import logging import logging
import psycopg2 import psycopg2
from odoo import api, fields, models from odoo import api, fields, models, _
from odoo.osv.expression import get_unaccent_wrapper from odoo.osv.expression import get_unaccent_wrapper
from odoo import SUPERUSER_ID, _
from odoo.exceptions import ValidationError, UserError from odoo.exceptions import ValidationError, UserError
from odoo.tools import mute_logger from odoo.tools import mute_logger
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
@@ -32,7 +30,8 @@ class ResPartner(models.Model):
('partner_id.id', '=', record.id) ('partner_id.id', '=', record.id)
]) ])
reservations_count = fields.Integer('Reservations', compute='_compute_reservations_count') reservations_count = fields.Integer('Reservations',
compute='_compute_reservations_count')
folios_count = fields.Integer('Folios', compute='_compute_folios_count') folios_count = fields.Integer('Folios', compute='_compute_folios_count')
unconfirmed = fields.Boolean('Unconfirmed', default=True) unconfirmed = fields.Boolean('Unconfirmed', default=True)
@@ -59,6 +58,15 @@ class ResPartner(models.Model):
self._cr.execute(query, (table,)) self._cr.execute(query, (table,))
return self._cr.fetchall() return self._cr.fetchall()
@api.multi
def write(self, vals):
for i, record in enumerate(self):
if record.unconfirmed is True:
partner_dst = self.env['res.partner']._check_duplicated_partner(record)
return
res = super(ResPartner, self).write(vals)
return res
@api.model @api.model
def name_search(self, name, args=None, operator='ilike', limit=100): def name_search(self, name, args=None, operator='ilike', limit=100):
result = super(ResPartner, self).name_search(name, args=None, result = super(ResPartner, self).name_search(name, args=None,
@@ -105,32 +113,33 @@ class ResPartner(models.Model):
result += self.browse(partner_ids).name_get() result += self.browse(partner_ids).name_get()
return result return result
@api.constrains('vat') @api.model
def _constrain_duplicated_partner(self): def _check_duplicated_partner(self, partner):
for record in self: duplicated_ids = self.env['res.partner']._get_duplicated_ids(partner)
domain = record._get_fields_domain_partner() if len(duplicated_ids) > 1:
if record.unconfirmed == True and len(domain) > 0: partners = self.env['res.partner'].browse(duplicated_ids)
partners = self.env['res.partner'].search(domain) return partner._merge(partners._ids)
record.update({'unconfirmed': False}) return partner
if len(partners) > 0:
with self.env.norecompute(): def _merge_fields(self):
record._merge(partners._ids) duplicated_fields = ['vat']
return duplicated_fields
@api.model @api.model
def _get_fields_domain_partner(self): def _get_duplicated_ids(self, partner):
self.ensure_one() partner_ids = []
domain = [] for field in self.env['res.partner']._merge_fields():
if self.vat: if partner[field]:
domain.append(('vat', '=', self.vat)) partner_ids += self.env['res.partner'].search([(field, '=', partner[field])]).ids
return domain return partner_ids
def _merge(self, partner_ids, dst_partner=None): def _merge(self, partner_ids, dst_partner=None):
""" private implementation of merge partner """ private implementation of merge partner
:param partner_ids : ids of partner to merge :param partner_ids : ids of partner to merge
:param dst_partner : record of destination res.partner :param dst_partner : record of destination res.partner
""" """
Partner = self.env['res.partner'] partner = self.env['res.partner']
partner_ids = Partner.browse(partner_ids).exists() partner_ids = partner.browse(partner_ids).exists()
if len(partner_ids) < 2: if len(partner_ids) < 2:
return return
@@ -140,7 +149,7 @@ class ResPartner(models.Model):
# check if the list of partners to merge contains child/parent relation # check if the list of partners to merge contains child/parent relation
child_ids = self.env['res.partner'] child_ids = self.env['res.partner']
for partner_id in partner_ids: for partner_id in partner_ids:
child_ids |= Partner.search([('id', 'child_of', [partner_id.id])]) - partner_id child_ids |= partner.search([('id', 'child_of', [partner_id.id])]) - partner_id
if partner_ids & child_ids: if partner_ids & child_ids:
raise UserError(_("You cannot merge a contact with one of his parent.")) raise UserError(_("You cannot merge a contact with one of his parent."))
@@ -162,7 +171,9 @@ class ResPartner(models.Model):
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))) 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 # delete source partner, since they are merged
src_partners.update({'active':False}) #~ src_partners.update({'active':False})
src_partners.unlink()
return dst_partner
@api.model @api.model
def _update_foreign_keys(self, src_partners, dst_partner): def _update_foreign_keys(self, src_partners, dst_partner):
@@ -173,7 +184,7 @@ class ResPartner(models.Model):
_logger.debug('_update_foreign_keys for dst_partner: %s for src_partners: %s', dst_partner.id, str(src_partners.ids)) _logger.debug('_update_foreign_keys for dst_partner: %s for src_partners: %s', dst_partner.id, str(src_partners.ids))
# find the many2one relation to a partner # find the many2one relation to a partner
Partner = self.env['res.partner'] partner = self.env['res.partner']
relations = self._get_fk_on('res_partner') relations = self._get_fk_on('res_partner')
for table, column in relations: for table, column in relations:
@@ -214,7 +225,7 @@ class ResPartner(models.Model):
self._cr.execute(query, (dst_partner.id, tuple(src_partners.ids),)) self._cr.execute(query, (dst_partner.id, tuple(src_partners.ids),))
# handle the recursivity with parent relation # handle the recursivity with parent relation
if column == Partner._parent_name and table == 'res_partner': if column == partner._parent_name and table == 'res_partner':
query = """ query = """
WITH RECURSIVE cycle(id, parent_id) AS ( WITH RECURSIVE cycle(id, parent_id) AS (
SELECT id, parent_id FROM res_partner SELECT id, parent_id FROM res_partner