From a762d335dcbf6e8e41fb799f7fe11459ac1cd873 Mon Sep 17 00:00:00 2001
From: "Pieter J. Kersten"
Date: Thu, 25 Feb 2010 10:25:45 +0100
Subject: [PATCH] [FIX] account_banking: empty BBAN's could lead to full search
in res.partner.bank [FIX] account_banking: complex
search filters were not supported [IMP] account_banking: equivalent BBAN's
and IBAN's are now found in one search [IMP] account_banking: BBAN's for
countries that use IBAN now return IBAN
---
account_banking/account_banking.py | 108 +++++++++++++++++++---------
account_banking/sepa/iban.py | 4 +-
account_banking/wizard/banktools.py | 8 +--
3 files changed, 82 insertions(+), 38 deletions(-)
diff --git a/account_banking/account_banking.py b/account_banking/account_banking.py
index 2b3c91071..cd681d095 100644
--- a/account_banking/account_banking.py
+++ b/account_banking/account_banking.py
@@ -956,42 +956,88 @@ class res_partner_bank(osv.osv):
the original base_iban 'search and search again fuzzy' tactic now can
result in doubled findings. Also there is now enough info to search
for local accounts when a valid IBAN was supplied.
+
+ Chosen strategy: create complex filter to find all results in just
+ one search
'''
- def uniq(lst):
+
+ def extended_simple_filter(args):
'''
- Create a list of unique elements in lst
+ Extend the simple search filter in args when appropriate.
'''
- d = dict(zip(lst, lst))
- return d.keys()
+ extra_args = None
+ if args[0].lower() == 'iban' and args[1] in ('=', '=='):
+ iban = sepa.IBAN(args[2])
+ if iban.valid:
+ # Some countries can't convert to BBAN
+ try:
+ bban = iban.localized_BBAN
+ # Prevent empty search filters
+ if bban:
+ extra_args = ('acc_number', args[1], bban)
+ except:
+ pass
+ if extra_args:
+ return [args, extra_args]
+ return [args]
- extras = []
+ def extended_search_filter(args):
+ '''
+ Extend the search filter in args when appropriate.
+ Is used recursively to allow complex search filters.
+ '''
+ if not args:
+ return []
- # Match acc_number searches as IBAN searches
- iban_equiv = [('iban',) + x[1:] for x in args if x[0] == 'acc_number']
- if iban_equiv:
- extras.append(iban_equiv)
+ all = []
+ if isinstance(args[0], (str, unicode)) and isinstance(args[1], (list, tuple)):
+ # Complex expression
- # Add local account search for IBAN searches
- extra_args = []
- for x in [x for x in args if x[0] == 'iban' and x[1] in ('=', '==')]:
- iban = sepa.IBAN(x[2])
- if iban.valid:
- # There are countries that have no localized_BBAN
- try:
- extra_args.append(('acc_number', '=', iban.localized_BBAN))
- except:
- pass
- if extra_args:
- extras.append(extra_args)
+ if args[0] == '&':
+ # For 'and', copy group and 'or' it with the modified one
+ mod = []
+ for term in args[1:]:
+ extra = extended_search_filter(term)
+ if extra != [term]:
+ mod.append(['|'] + extra)
+ else:
+ mod.append(term)
+ if mod and mod != [args[1:]]:
+ all += ['|', args, ['&'] + mod]
+ elif args[0] == '|':
+ # For 'or', just add the modified terms
+ mod = [args[0]]
+ for term in args[1:]:
+ mod += extended_search_filter(term)
+ all += mod
+
+ else:
+ # Implicit '|'
+ extra = []
+ if isinstance(args, (tuple, list)) and len(args) == 3:
+ extra += extended_simple_filter(args)
+ else:
+ for arg in args:
+ extra += extended_search_filter(arg)
+ if extra:
+ all += extra
+
+ return all
+
+ # Extend search filter
+ newargs = extended_search_filter(args)
+
# Original search (_founder)
- results = self._founder.search(self, cursor, uid, args, *rest, **kwargs)
- for extra in extras:
- results += self._founder.search(self, cursor, uid, extra, *rest,
- **kwargs)
- return isinstance(results, list) and uniq(results) or results
+ results = self._founder.search(self, cursor, uid, newargs,
+ *rest, **kwargs
+ )
+ return results
def read(self, *args, **kwargs):
+ '''
+ Convert IBAN electronic format to IBAN display format
+ '''
records = self._founder.read(self, *args, **kwargs)
for record in records:
if 'iban' in record and record['iban']:
@@ -1079,21 +1125,17 @@ class res_partner_bank(osv.osv):
if not iban:
return {}
- country_obj = self.pool.get('res.country')
- partner_obj = self.pool.get('res.partner')
- country_ids = []
-
iban_acc = sepa.IBAN(iban)
if iban_acc.valid:
bank_id, country_id = get_or_create_bank(
- self.pool, cursor, uid, iban_acc.BIC_searchkey
+ self.pool, cursor, uid, iban_acc.BIC_searchkey,
+ code=iban_acc.BIC_searchkey
)
return {
'value': {
'acc_number': iban_acc.localized_BBAN,
'iban': unicode(iban_acc),
- 'country':
- country_id or country_ids and country_ids[0] or False,
+ 'country': country_id or False,
'bank': bank_id or False,
}
}
diff --git a/account_banking/sepa/iban.py b/account_banking/sepa/iban.py
index e4a8d429d..7f92f311a 100644
--- a/account_banking/sepa/iban.py
+++ b/account_banking/sepa/iban.py
@@ -160,7 +160,9 @@ class BBANFormat(object):
if self._bban[i] == '%':
i += 1
parm = self._bban[i]
- if parm in 'BCDPTVWX':
+ if parm == 'I':
+ res += unicode(iban)
+ elif parm in 'BCDPTVWX':
res += self.__extract__(parm, iban)
elif parm == 'A':
res += self.account(iban)
diff --git a/account_banking/wizard/banktools.py b/account_banking/wizard/banktools.py
index cee2cc2fa..28748a97a 100644
--- a/account_banking/wizard/banktools.py
+++ b/account_banking/wizard/banktools.py
@@ -222,6 +222,9 @@ def get_or_create_bank(pool, cursor, uid, bic, online=False, code=None,
country_ids = country_obj.search(
cursor, uid, [('code', '=', bic[4:6])]
)
+ country_id = country_ids and country_ids[0] or False
+ bank_id = False
+
if online:
info, address = sepa.online.bank_info(bic)
if info:
@@ -232,15 +235,12 @@ def get_or_create_bank(pool, cursor, uid, bic, online=False, code=None,
street2 = address.street2,
zip = address.zip,
city = address.city,
- country = country_ids and country_ids[0] or False,
+ country = country_id,
bic = info.bic[:8],
))
- else:
- bank_id = False
else:
info = struct(name=name, code=code)
- country_id = country_ids and country_ids[0] or False
if info.code and ((not online) or not bank_id):
bank_id = bank_obj.create(cursor, uid, dict(
code = info.code,