diff --git a/openerp/addons/base/res/res_bank.py b/openerp/addons/base/res/res_bank.py index b04dc37ef86..9f14e3a35c4 100644 --- a/openerp/addons/base/res/res_bank.py +++ b/openerp/addons/base/res/res_bank.py @@ -19,6 +19,8 @@ # ############################################################################## +import re + from openerp.osv import fields, osv from openerp.tools.translate import _ from openerp.exceptions import UserError @@ -113,8 +115,51 @@ class res_partner_bank(osv.osv): value = address.get(field, value) return value + # Courtesy of lmignon (acsone) + + def _sanitize_account_number(self, acc_number): + if acc_number: + return re.sub(r'\W+', '', acc_number).upper() + return False + + def _get_sanitized_account_number( + self, cr, uid, ids, field_name, arg, context): + """Compute sanitized version off account number. + + This is needed for reliable search and uniqueness test.""" + res = {} + for this_obj in self.browse(cr, uid, ids, context = context): + res[this_obj.id] = ( + self._sanitize_account_number(this_obj.acc_number)) + return res + + def search(self, cr, user, args, offset=0, limit=None, order=None, + context=None, count=False): + pos = 0 + while pos < len(args): + if args[pos][0] == 'acc_number': + op = args[pos][1] + value = args[pos][2] + if hasattr(value, '__iter__'): + value = [self._sanitize_account_number(i) for i in value] + else: + value = self._sanitize_account_number(value) + if 'like' in op: + value = '%' + value + '%' + args[pos] = ('sanitized_acc_number', op, value) + pos += 1 + return super(res_partner_bank, self).search( + cr, user, args, offset=0, limit=None, order=None, context=None, + count=False) + _columns = { 'acc_number': fields.char('Account Number', required=True), + 'sanitized_acc_number': fields.function( + _get_sanitized_account_number, + string='Sanitized Account Number', + type='char', size=64, readonly=True, + store=True, + ), 'bank': fields.many2one('res.bank', 'Bank'), 'bank_bic': fields.char('Bank Identifier Code'), 'bank_name': fields.char('Bank Name'), @@ -135,6 +180,10 @@ class res_partner_bank(osv.osv): 'footer': fields.boolean("Display on Reports", help="Display this bank account on the footer of printed documents like invoices and sales orders."), 'currency_id': fields.many2one('res.currency', string='Currency', help="Currency of the bank account and its related journal."), } + _sql_constraints = [ + ('unique_number', 'unique(sanitized_acc_number)', + 'Account Number must be unique'), + ] _defaults = { 'owner_name': lambda obj, cursor, user, context: obj._default_value( diff --git a/openerp/addons/base/tests/__init__.py b/openerp/addons/base/tests/__init__.py index 82b79cfc693..d58e4931ec7 100644 --- a/openerp/addons/base/tests/__init__.py +++ b/openerp/addons/base/tests/__init__.py @@ -25,3 +25,4 @@ import test_translate import test_view_validation import test_views import test_xmlrpc +import test_res_partner_bank diff --git a/openerp/addons/base/tests/test_res_partner_bank.py b/openerp/addons/base/tests/test_res_partner_bank.py new file mode 100644 index 00000000000..d93d855dc4d --- /dev/null +++ b/openerp/addons/base/tests/test_res_partner_bank.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# This file is part of account_bank_statement_import, +# an Odoo module. +# +# Copyright (c) 2015 ACSONE SA/NV () +# +# account_bank_statement_import is free software: +# you can redistribute it and/or modify it under the terms of the GNU +# Affero General Public License as published by the Free Software +# Foundation,either version 3 of the License, or (at your option) any +# later version. +# +# account_bank_statement_import is distributed +# in the hope that it will be useful, but WITHOUT ANY WARRANTY; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +# PURPOSE. See the GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with account_bank_statement_import_coda. +# If not, see . +# +############################################################################## +from openerp.tests.common import TransactionCase + + +class TestResPartnerBank(TransactionCase): + """Tests acc_number + """ + + def test_sanitized_acc_number(self): + partner_bank_model = self.env['res.partner.bank'] + acc_number = " BE-001 2518823 03 " + vals = partner_bank_model.search([('acc_number', '=', acc_number)]) + self.assertEquals(0, len(vals)) + partner_bank = partner_bank_model.create({ + 'acc_number': acc_number, + 'partner_id': self.ref('base.res_partner_2'), + 'state': 'bank', + }) + vals = partner_bank_model.search([('acc_number', '=', acc_number)]) + self.assertEquals(1, len(vals)) + self.assertEquals(partner_bank, vals[0]) + vals = partner_bank_model.search([('acc_number', 'in', [acc_number])]) + self.assertEquals(1, len(vals)) + self.assertEquals(partner_bank, vals[0]) + + self.assertEqual(partner_bank.acc_number, acc_number) + + # sanitaze the acc_number + sanitized_acc_number = 'BE001251882303' + vals = partner_bank_model.search( + [('acc_number', '=', sanitized_acc_number)]) + self.assertEquals(1, len(vals)) + self.assertEquals(partner_bank, vals[0]) + vals = partner_bank_model.search( + [('acc_number', 'in', [sanitized_acc_number])]) + self.assertEquals(1, len(vals)) + self.assertEquals(partner_bank, vals[0]) + self.assertEqual(partner_bank.sanitized_acc_number, + sanitized_acc_number) + + # search is case insensitive + vals = partner_bank_model.search( + [('acc_number', '=', sanitized_acc_number.lower())]) + self.assertEquals(1, len(vals)) + vals = partner_bank_model.search( + [('acc_number', '=', acc_number.lower())]) + self.assertEquals(1, len(vals))