From 54857ec409d2cd2a565ad73b069a8641046aedac Mon Sep 17 00:00:00 2001
From: Martin Trigaux <mat@openerp.com>
Date: Thu, 7 Aug 2014 16:50:38 +0200
Subject: [PATCH] [IMP] crm: clean after partner merge

When trying to merge partners, an sql error may be violated (e.g. unique constraints).
In this case, catch the error and delete the problematic record as it will no longer be relevant with the old partner and left unconsistant data in the database.
---
 addons/crm/base_partner_merge.py | 44 +++++++++++++++++---------------
 1 file changed, 23 insertions(+), 21 deletions(-)

diff --git a/addons/crm/base_partner_merge.py b/addons/crm/base_partner_merge.py
index 11cacc57ce62..72a9e12435a1 100644
--- a/addons/crm/base_partner_merge.py
+++ b/addons/crm/base_partner_merge.py
@@ -6,6 +6,7 @@ import htmlentitydefs
 import itertools
 import logging
 import operator
+import psycopg2
 import re
 from ast import literal_eval
 from openerp.tools import mute_logger
@@ -186,28 +187,29 @@ class MergePartnerAutomatic(osv.TransientModel):
                 for partner_id in partner_ids:
                     cr.execute(query, (dst_partner.id, partner_id, dst_partner.id))
             else:
-                cr.execute("SAVEPOINT recursive_partner_savepoint")
                 try:
-                    query = 'UPDATE "%(table)s" SET %(column)s = %%s WHERE %(column)s IN %%s' % query_dic
-                    cr.execute(query, (dst_partner.id, partner_ids,))
-
-                    if column == proxy._parent_name and table == 'res_partner':
-                        query = """
-                            WITH RECURSIVE cycle(id, parent_id) AS (
-                                    SELECT id, parent_id FROM res_partner
-                                UNION
-                                    SELECT  cycle.id, res_partner.parent_id
-                                    FROM    res_partner, cycle
-                                    WHERE   res_partner.id = cycle.parent_id AND
-                                            cycle.id != cycle.parent_id
-                            )
-                            SELECT id FROM cycle WHERE id = parent_id AND id = %s
-                        """
-                        cr.execute(query, (dst_partner.id,))
-                        if cr.fetchall():
-                            cr.execute("ROLLBACK TO SAVEPOINT recursive_partner_savepoint")
-                finally:
-                    cr.execute("RELEASE SAVEPOINT recursive_partner_savepoint")
+                    with mute_logger('openerp.sql_db'), cr.savepoint():
+                        query = 'UPDATE "%(table)s" SET %(column)s = %%s WHERE %(column)s IN %%s' % query_dic
+                        cr.execute(query, (dst_partner.id, partner_ids,))
+
+                        if column == proxy._parent_name and table == 'res_partner':
+                            query = """
+                                WITH RECURSIVE cycle(id, parent_id) AS (
+                                        SELECT id, parent_id FROM res_partner
+                                    UNION
+                                        SELECT  cycle.id, res_partner.parent_id
+                                        FROM    res_partner, cycle
+                                        WHERE   res_partner.id = cycle.parent_id AND
+                                                cycle.id != cycle.parent_id
+                                )
+                                SELECT id FROM cycle WHERE id = parent_id AND id = %s
+                            """
+                            cr.execute(query, (dst_partner.id,))
+                except psycopg2.Error:
+                    # updating fails, most likely due to a violated unique constraint
+                    # keeping record with nonexistent partner_id is useless, better delete it
+                    query = 'DELETE FROM %(table)s WHERE %(column)s = %%s' % query_dic
+                    cr.execute(query, (partner_id,))
 
     def _update_reference_fields(self, cr, uid, src_partners, dst_partner, context=None):
         _logger.debug('_update_reference_fields for dst_partner: %s for src_partners: %r', dst_partner.id, list(map(operator.attrgetter('id'), src_partners)))
-- 
GitLab