[IMP] crm: clean after partner merge
authorMartin Trigaux <mat@openerp.com>
Thu, 7 Aug 2014 14:50:38 +0000 (16:50 +0200)
committerMartin Trigaux <mat@openerp.com>
Thu, 7 Aug 2014 16:17:39 +0000 (18:17 +0200)
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

index 11cacc5..72a9e12 100644 (file)
@@ -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)))