@ -36,11 +36,11 @@ def html_entity_decode(string):
return pattern . sub ( html_entity_decode_char , string )
def sanitize_email ( email ) :
assert isinstance ( email , basestring ) and email
def sanitize_email ( partner_ email) :
assert isinstance ( partner_ email, basestring ) and partner_ email
result = re . subn ( r ' ;|/|: ' , ' , ' ,
html_entity_decode ( email or ' ' ) ) [ 0 ] . split ( ' , ' )
html_entity_decode ( partner_ email or ' ' ) ) [ 0 ] . split ( ' , ' )
emails = [ parseaddr ( email ) [ 1 ]
for item in result
@ -63,6 +63,7 @@ class ResPartner(osv.Model):
' create_date ' : fields . datetime ( ' Create Date ' , readonly = True ) ,
}
class MergePartnerLine ( osv . TransientModel ) :
_name = ' base.partner.merge.line '
@ -78,9 +79,10 @@ class MergePartnerLine(osv.TransientModel):
class MergePartnerAutomatic ( osv . TransientModel ) :
"""
The idea behind this wizard is to create a list of potential partners to
merge . We use two objects , the first one is the wizard for the end - user .
And the second will contain the partner list to merge .
The idea behind this wizard is to create a list of potential partners to
merge . We use two objects , the first one is the wizard for the end - user .
And the second will contain the partner list to merge .
"""
_name = ' base.partner.merge.automatic.wizard '
@ -99,25 +101,34 @@ class MergePartnerAutomatic(osv.TransientModel):
readonly = True ,
required = True ) ,
' number_group ' : fields . integer ( " Group of Contacts " , readonly = True ) ,
' current_line_id ' : fields . many2one ( ' base.partner.merge.line ' , ' Current Line ' ) ,
' line_ids ' : fields . one2many ( ' base.partner.merge.line ' , ' wizard_id ' , ' Lines ' ) ,
' current_line_id ' : fields . many2one ( ' base.partner.merge.line ' ,
' Current Line ' ) ,
' line_ids ' : fields . one2many ( ' base.partner.merge.line ' ,
' wizard_id ' , ' Lines ' ) ,
' partner_ids ' : fields . many2many ( ' res.partner ' , string = ' Contacts ' ) ,
' dst_partner_id ' : fields . many2one ( ' res.partner ' , string = ' Destination Contact ' ) ,
' dst_partner_id ' : fields . many2one ( ' res.partner ' ,
string = ' Destination Contact ' ) ,
' exclude_contact ' : fields . boolean ( ' A user associated to the contact ' ) ,
' exclude_journal_item ' : fields . boolean ( ' Journal Items associated to the contact ' ) ,
' exclude_journal_item ' : fields . boolean ( ' Journal Items associated '
' to the contact ' ) ,
' maximum_group ' : fields . integer ( " Maximum of Group of Contacts " ) ,
}
def default_get ( self , cr , uid , fields , context = None ) :
if context is None :
context = { }
res = super ( MergePartnerAutomatic , self ) . default_get ( cr , uid , fields , context )
if context . get ( ' active_model ' ) == ' res.partner ' and context . get ( ' active_ids ' ) :
res = super ( MergePartnerAutomatic , self
) . default_get ( cr , uid , fields , context )
if ( context . get ( ' active_model ' ) == ' res.partner '
and context . get ( ' active_ids ' ) ) :
partner_ids = context [ ' active_ids ' ]
res [ ' state ' ] = ' selection '
res [ ' partner_ids ' ] = partner_ids
res [ ' dst_partner_id ' ] = self . _get_ordered_partner ( cr , uid , partner_ids , context = context ) [ - 1 ] . id
res [ ' dst_partner_id ' ] = self . _get_ordered_partner ( cr , uid ,
partner_ids ,
context = context
) [ - 1 ] . id
return res
_defaults = {
@ -143,8 +154,12 @@ class MergePartnerAutomatic(osv.TransientModel):
"""
return cr . execute ( q , ( table , ) )
def _update_foreign_keys ( self , cr , uid , src_partners , dst_partner , context = None ) :
_logger . debug ( ' _update_foreign_keys for dst_partner: %s for src_partners: %r ' , dst_partner . id , list ( map ( operator . attrgetter ( ' id ' ) , src_partners ) ) )
def _update_foreign_keys ( self , cr , uid , src_partners ,
dst_partner , context = None ) :
_logger . debug ( ' _update_foreign_keys for dst_partner: %s for '
' src_partners: %r ' ,
dst_partner . id ,
list ( map ( operator . attrgetter ( ' id ' ) , src_partners ) ) )
# find the many2one relation to a partner
proxy = self . pool . get ( ' res.partner ' )
@ -157,7 +172,8 @@ class MergePartnerAutomatic(osv.TransientModel):
continue
partner_ids = tuple ( map ( int , src_partners ) )
query = " SELECT column_name FROM information_schema.columns WHERE table_name LIKE ' %s ' " % ( table )
query = ( " SELECT column_name FROM information_schema.columns "
" WHERE table_name LIKE ' %s ' " ) % ( table )
cr . execute ( query , ( ) )
columns = [ ]
for data in cr . fetchall ( ) :
@ -184,57 +200,77 @@ class MergePartnerAutomatic(osv.TransientModel):
___tu . % ( value ) s = ___tw . % ( value ) s
) """ % query_dic
for partner_id in partner_ids :
cr . execute ( query , ( dst_partner . id , partner_id , dst_partner . id ) )
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
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 ' :
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 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
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 " )
cr . execute ( " ROLLBACK TO SAVEPOINT "
" recursive_partner_savepoint " )
finally :
cr . execute ( " RELEASE SAVEPOINT recursive_partner_savepoint " )
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 ) ) )
def update_records ( model , src , field_model = ' model ' , field_id = ' res_id ' , context = None ) :
cr . execute ( " RELEASE SAVEPOINT "
" recursive_partner_savepoint " )
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 ) ) )
def update_records ( model , src , field_model = ' model ' , field_id = ' res_id ' ,
context = None ) :
proxy = self . pool . get ( model )
if proxy is None :
return
domain = [ ( field_model , ' = ' , ' res.partner ' ) , ( field_id , ' = ' , src . id ) ]
ids = proxy . search ( cr , openerp . SUPERUSER_ID , domain , context = context )
return proxy . write ( cr , openerp . SUPERUSER_ID , ids , { field_id : dst_partner . id } , context = context )
domain = [ ( field_model , ' = ' , ' res.partner ' ) ,
( field_id , ' = ' , src . id ) ]
ids = proxy . search ( cr , openerp . SUPERUSER_ID ,
domain , context = context )
return proxy . write ( cr , openerp . SUPERUSER_ID , ids ,
{ field_id : dst_partner . id } , context = context )
update_records = functools . partial ( update_records , context = context )
for partner in src_partners :
update_records ( ' base.calendar ' , src = partner , field_model = ' model_id.model ' )
update_records ( ' ir.attachment ' , src = partner , field_model = ' res_model ' )
update_records ( ' mail.followers ' , src = partner , field_model = ' res_model ' )
update_records ( ' base.calendar ' , src = partner ,
field_model = ' model_id.model ' )
update_records ( ' ir.attachment ' , src = partner ,
field_model = ' res_model ' )
update_records ( ' mail.followers ' , src = partner ,
field_model = ' res_model ' )
update_records ( ' mail.message ' , src = partner )
update_records ( ' marketing.campaign.workitem ' , src = partner , field_model = ' object_id.model ' )
update_records ( ' marketing.campaign.workitem ' , src = partner ,
field_model = ' object_id.model ' )
update_records ( ' ir.model.data ' , src = partner )
proxy = self . pool [ ' ir.model.fields ' ]
domain = [ ( ' ttype ' , ' = ' , ' reference ' ) ]
record_ids = proxy . search ( cr , openerp . SUPERUSER_ID , domain , context = context )
record_ids = proxy . search ( cr , openerp . SUPERUSER_ID , domain ,
context = context )
for record in proxy . browse ( cr , openerp . SUPERUSER_ID , record_ids , context = context ) :
for record in proxy . browse ( cr , openerp . SUPERUSER_ID , record_ids ,
context = context ) :
try :
proxy_model = self . pool [ record . model ]
except KeyError :
@ -253,16 +289,22 @@ class MergePartnerAutomatic(osv.TransientModel):
domain = [
( record . name , ' = ' , ' res.partner, %d ' % partner . id )
]
model_ids = proxy_model . search ( cr , openerp . SUPERUSER_ID , domain , context = context )
model_ids = proxy_model . search ( cr , openerp . SUPERUSER_ID ,
domain , context = context )
values = {
record . name : ' res.partner, %d ' % dst_partner . id ,
}
proxy_model . write ( cr , openerp . SUPERUSER_ID , model_ids , values , context = context )
proxy_model . write ( cr , openerp . SUPERUSER_ID , model_ids , values ,
context = context )
def _update_values ( self , cr , uid , src_partners , dst_partner , context = None ) :
_logger . debug ( ' _update_values for dst_partner: %s for src_partners: %r ' , dst_partner . id , list ( map ( operator . attrgetter ( ' id ' ) , src_partners ) ) )
_logger . debug ( ' _update_values for dst_partner: %s for src_partners: '
' %r ' ,
dst_partner . id ,
list ( map ( operator . attrgetter ( ' id ' ) , src_partners ) ) )
columns = dst_partner . _columns
def write_serializer ( column , item ) :
if isinstance ( item , browse_record ) :
return item . id
@ -271,10 +313,12 @@ class MergePartnerAutomatic(osv.TransientModel):
values = dict ( )
for column , field in columns . iteritems ( ) :
if field . _type not in ( ' many2many ' , ' one2many ' ) and not isinstance ( field , fields . function ) :
if ( field . _type not in ( ' many2many ' , ' one2many ' )
and not isinstance ( field , fields . function ) ) :
for item in itertools . chain ( src_partners , [ dst_partner ] ) :
if item [ column ] :
values [ column ] = write_serializer ( column , item [ column ] )
values [ column ] = write_serializer ( column ,
item [ column ] )
values . pop ( ' id ' , None )
parent_id = values . pop ( ' parent_id ' , None )
@ -283,60 +327,98 @@ class MergePartnerAutomatic(osv.TransientModel):
try :
dst_partner . write ( { ' parent_id ' : parent_id } )
except ( osv . except_osv , orm . except_orm ) :
_logger . info ( ' Skip recursive partner hierarchies for parent_id %s of partner: %s ' , parent_id , dst_partner . id )
_logger . info ( ' Skip recursive partner hierarchies for '
' parent_id %s of partner: %s ' ,
parent_id , dst_partner . id )
@mute_logger ( ' openerp.osv.expression ' , ' openerp.osv.orm ' )
def _merge ( self , cr , uid , partner_ids , dst_partner = None , context = None ) :
proxy = self . pool . get ( ' res.partner ' )
partner_ids = proxy . exists ( cr , uid , list ( partner_ids ) , context = context )
partner_ids = proxy . exists ( cr , uid , list ( partner_ids ) ,
context = context )
if len ( partner_ids ) < 2 :
return
if len ( partner_ids ) > 3 :
raise osv . except_osv ( _ ( ' Error ' ) , _ ( " For safety reasons, you cannot merge more than 3 contacts together. You can re-open the wizard several times if needed. " ) )
if openerp . SUPERUSER_ID != uid and len ( set ( partner . email for partner in proxy . browse ( cr , uid , partner_ids , context = context ) ) ) > 1 :
raise osv . except_osv ( _ ( ' Error ' ) , _ ( " All contacts must have the same email. Only the Administrator can merge contacts with different emails. " ) )
raise osv . except_osv (
_ ( ' Error ' ) ,
_ ( " For safety reasons, you cannot merge more than 3 contacts "
" together. You can re-open the wizard several times if "
" needed. " ) )
if ( openerp . SUPERUSER_ID != uid
and len ( set ( partner . email for partner
in proxy . browse ( cr , uid , partner_ids ,
context = context ) ) ) > 1 ) :
raise osv . except_osv (
_ ( ' Error ' ) ,
_ ( " All contacts must have the same email. Only the "
" Administrator can merge contacts with different emails. " ) )
if dst_partner and dst_partner . id in partner_ids :
src_partners = proxy . browse ( cr , uid , [ id for id in partner_ids if id != dst_partner . id ] , context = context )
src_partners = proxy . browse ( cr , uid ,
[ id for id in partner_ids
if id != dst_partner . id ] ,
context = context )
else :
ordered_partners = self . _get_ordered_partner ( cr , uid , partner_ids , context )
ordered_partners = self . _get_ordered_partner ( cr , uid , partner_ids ,
context )
dst_partner = ordered_partners [ - 1 ]
src_partners = ordered_partners [ : - 1 ]
_logger . info ( " dst_partner: %s " , dst_partner . id )
if openerp . SUPERUSER_ID != uid and self . _model_is_installed ( cr , uid , ' account.move.line ' , context = context ) and \
self . pool . get ( ' account.move.line ' ) . search ( cr , openerp . SUPERUSER_ID , [ ( ' partner_id ' , ' in ' , [ partner . id for partner in src_partners ] ) ] , context = context ) :
raise osv . except_osv ( _ ( ' Error ' ) , _ ( " 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_it = lambda function : function ( cr , uid , src_partners , dst_partner ,
context = context )
if ( openerp . SUPERUSER_ID != uid
and self . _model_is_installed ( cr , uid , ' account.move.line ' ,
context = context )
and self . pool . get ( ' account.move.line '
) . search ( cr , openerp . SUPERUSER_ID ,
[ ( ' partner_id ' ,
' in ' ,
[ partner . id for partner
in src_partners ] ) ] ,
context = context ) ) :
raise osv . except_osv (
_ ( ' Error ' ) ,
_ ( " 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_it = lambda function : function ( cr , uid , src_partners ,
dst_partner , context = context )
call_it ( self . _update_foreign_keys )
call_it ( self . _update_reference_fields )
call_it ( self . _update_values )
_logger . info ( ' (uid = %s ) merged the partners %r with %s ' , uid , list ( map ( operator . attrgetter ( ' id ' ) , src_partners ) ) , 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 ) ) )
_logger . info ( ' (uid = %s ) merged the partners %r with %s ' ,
uid ,
list ( map ( operator . attrgetter ( ' id ' ) , src_partners ) ) ,
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 ) ) )
for partner in src_partners :
partner . unlink ( )
def clean_emails ( self , cr , uid , context = None ) :
"""
Clean the email address of the partner , if there is an email field with
a mimum of two addresses , the system will create a new partner , with the
information of the previous one and will copy the new cleaned email into
the email field .
Clean the email address of the partner , if there is an email field
with a min imum of two addresses , the system will create a new partner ,
with the information of the previous one and will copy the new cleaned
email into the email field .
"""
if context is None :
context = { }
proxy_model = self . pool [ ' ir.model.fields ' ]
field_ids = proxy_model . search ( cr , uid , [ ( ' model ' , ' = ' , ' res.partner ' ) ,
( ' ttype ' , ' like ' , ' % 2many ' ) ] ,
field_ids = proxy_model . search ( cr , uid ,
[ ( ' model ' , ' = ' , ' res.partner ' ) ,
( ' ttype ' , ' like ' , ' % 2many ' ) ] ,
context = context )
fields = proxy_model . read ( cr , uid , field_ids , context = context )
reset_fields = dict ( ( field [ ' name ' ] , [ ] ) for field in fields )
@ -374,7 +456,8 @@ class MergePartnerAutomatic(osv.TransientModel):
context = context )
except Exception :
_logger . exception ( " There is a problem with this partner: %r " , partner )
_logger . exception ( " There is a problem with this partner: %r " ,
partner )
raise
return True
@ -431,7 +514,8 @@ class MergePartnerAutomatic(osv.TransientModel):
if not groups :
raise osv . except_osv ( _ ( ' Error ' ) ,
_ ( " You have to specify a filter for your selection " ) )
_ ( " You have to specify a filter for your "
" selection " ) )
return groups
@ -446,10 +530,15 @@ class MergePartnerAutomatic(osv.TransientModel):
return self . _next_screen ( cr , uid , this , context )
def _get_ordered_partner ( self , cr , uid , partner_ids , context = None ) :
partners = self . pool . get ( ' res.partner ' ) . browse ( cr , uid , list ( partner_ids ) , context = context )
partners = self . pool . get ( ' res.partner '
) . browse ( cr , uid ,
list ( partner_ids ) ,
context = context )
ordered_partners = sorted ( sorted ( partners ,
key = operator . attrgetter ( ' create_date ' ) , reverse = True ) ,
key = operator . attrgetter ( ' active ' ) , reverse = True )
key = operator . attrgetter ( ' create_date ' ) ,
reverse = True ) ,
key = operator . attrgetter ( ' active ' ) ,
reverse = True )
return ordered_partners
def _next_screen ( self , cr , uid , this , context = None ) :
@ -462,7 +551,11 @@ class MergePartnerAutomatic(osv.TransientModel):
values . update ( {
' current_line_id ' : current_line . id ,
' partner_ids ' : [ ( 6 , 0 , current_partner_ids ) ] ,
' dst_partner_id ' : self . _get_ordered_partner ( cr , uid , current_partner_ids , context ) [ - 1 ] . id ,
' dst_partner_id ' : self . _get_ordered_partner (
cr , uid ,
current_partner_ids ,
context
) [ - 1 ] . id ,
' state ' : ' selection ' ,
} )
else :
@ -501,8 +594,8 @@ class MergePartnerAutomatic(osv.TransientModel):
def compute_models ( self , cr , uid , ids , context = None ) :
"""
Compute the different models needed by the system if you want to exclude
some partners .
Compute the different models needed by the system if you want to
exclude some partners .
"""
assert is_integer_list ( ids )
@ -512,7 +605,9 @@ class MergePartnerAutomatic(osv.TransientModel):
if this . exclude_contact :
models [ ' res.users ' ] = ' partner_id '
if self . _model_is_installed ( cr , uid , ' account.move.line ' , context = context ) and this . exclude_journal_item :
if ( self . _model_is_installed ( cr , uid , ' account.move.line ' ,
context = context )
and this . exclude_journal_item ) :
models [ ' account.move.line ' ] = ' partner_id '
return models
@ -528,7 +623,8 @@ class MergePartnerAutomatic(osv.TransientModel):
counter = 0
for min_id , aggr_ids in cr . fetchall ( ) :
if models and self . _partner_use_in ( cr , uid , aggr_ids , models , context = context ) :
if models and self . _partner_use_in ( cr , uid , aggr_ids , models ,
context = context ) :
continue
values = {
' wizard_id ' : this . id ,
@ -552,7 +648,8 @@ class MergePartnerAutomatic(osv.TransientModel):
"""
Start the process .
* Compute the selected groups ( with duplication )
* If the user has selected the ' exclude_XXX ' fields , avoid the partners .
* If the user has selected the ' exclude_XXX ' fields , avoid the
partners .
"""
assert is_integer_list ( ids )
@ -664,13 +761,31 @@ class MergePartnerAutomatic(osv.TransientModel):
self . parent_migration_process_cb ( cr , uid , ids , context = None )
list_merge = [
{ ' group_by_vat ' : True , ' group_by_email ' : True , ' group_by_name ' : True } ,
# {'group_by_name': True, 'group_by_is_company': True, 'group_by_parent_id': True},
# {'group_by_email': True, 'group_by_is_company': True, 'group_by_parent_id': True},
# {'group_by_name': True, 'group_by_vat': True, 'group_by_is_company': True, 'exclude_journal_item': True},
# {'group_by_email': True, 'group_by_vat': True, 'group_by_is_company': True, 'exclude_journal_item': True},
# {'group_by_email': True, 'group_by_is_company': True, 'exclude_contact': True, 'exclude_journal_item': True},
# {'group_by_name': True, 'group_by_is_company': True, 'exclude_contact': True, 'exclude_journal_item': True}
{ ' group_by_vat ' : True ,
' group_by_email ' : True ,
' group_by_name ' : True } ,
# {'group_by_name': True,
# 'group_by_is_company': True,
# 'group_by_parent_id': True},
# {'group_by_email': True,
# 'group_by_is_company': True,
# 'group_by_parent_id': True},
# {'group_by_name': True,
# 'group_by_vat': True,
# 'group_by_is_company': True,
# 'exclude_journal_item': True},
# {'group_by_email': True,
# 'group_by_vat': True,
# 'group_by_is_company': True,
# 'exclude_journal_item': True},
# {'group_by_email': True,
# 'group_by_is_company': True,
# 'exclude_contact': True,
# 'exclude_journal_item': True},
# {'group_by_name': True,
# 'group_by_is_company': True,
# 'exclude_contact': True,
# 'exclude_journal_item': True}
]
for merge_value in list_merge :
@ -722,7 +837,8 @@ class MergePartnerAutomatic(osv.TransientModel):
' target ' : ' new ' ,
}
self . _merge ( cr , uid , partner_ids , this . dst_partner_id , context = context )
self . _merge ( cr , uid , partner_ids , this . dst_partner_id ,
context = context )
if this . current_line_id :
this . current_line_id . unlink ( )
@ -735,8 +851,8 @@ class MergePartnerAutomatic(osv.TransientModel):
# select partner who have one least invoice
partner_treated = [ ' @gmail.com ' ]
cr . execute ( """ SELECT p.id, p.email
FROM res_partner as p
LEFT JOIN account_invoice as a
FROM res_partner as p
LEFT JOIN account_invoice as a
ON p . id = a . partner_id AND a . state in ( ' open ' , ' paid ' )
WHERE p . grade_id is NOT NULL
GROUP BY p . id
@ -750,11 +866,15 @@ class MergePartnerAutomatic(osv.TransientModel):
continue
partner_treated . append ( email )
# don't update the partners if they are more of one who have invoice
cr . execute ( """ SELECT *
FROM res_partner as p
WHERE p . id != % s AND p . email LIKE ' %% %s ' AND
EXISTS ( SELECT * FROM account_invoice as a WHERE p . id = a . partner_id AND a . state in ( ' open ' , ' paid ' ) )
# don't update the partners if they are more of one who have
# invoice
cr . execute ( """
SELECT *
FROM res_partner as p
WHERE p . id != % s AND p . email LIKE ' %% %s ' AND
EXISTS ( SELECT * FROM account_invoice as a
WHERE p . id = a . partner_id
AND a . state in ( ' open ' , ' paid ' ) )
""" % (id, email))
if len ( cr . fetchall ( ) ) > 1 :
@ -764,7 +884,8 @@ class MergePartnerAutomatic(osv.TransientModel):
# to display changed values
cr . execute ( """ SELECT id,email
FROM res_partner
WHERE parent_id != % s AND id != % s AND email LIKE ' %% %s '
WHERE parent_id != % s
AND id != % s AND email LIKE ' %% %s '
""" % (id, id, email))
_logger . info ( " %r " , cr . fetchall ( ) )