mirror of
https://github.com/OCA/pms.git
synced 2025-01-29 00:17:45 +02:00
[WIP] Merge partners
This commit is contained in:
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user