Merge lp:~therp-nl/banking-addons/ba70-deprecate_iban_lookup into lp:banking-addons
- ba70-deprecate_iban_lookup
- Merge into banking-addons-70
Status: | Merged |
---|---|
Approved by: | Yannick Vaucher @ Camptocamp |
Approved revision: | 234 |
Merged at revision: | 234 |
Proposed branch: | lp:~therp-nl/banking-addons/ba70-deprecate_iban_lookup |
Merge into: | lp:banking-addons |
Diff against target: |
1285 lines (+593/-470) 20 files modified
account_banking/__init__.py (+2/-0) account_banking/__openerp__.py (+0/-6) account_banking/account_banking.py (+1/-409) account_banking/account_banking_view.xml (+0/-29) account_banking/res_bank.py (+31/-0) account_banking/res_partner_bank.py (+101/-0) account_banking/sepa/__init__.py (+0/-1) account_banking/wizard/banktools.py (+4/-14) account_banking_iban_lookup/__init__.py (+3/-0) account_banking_iban_lookup/__openerp__.py (+52/-0) account_banking_iban_lookup/model/__init__.py (+2/-0) account_banking_iban_lookup/model/res_bank.py (+63/-0) account_banking_iban_lookup/model/res_partner_bank.py (+271/-0) account_banking_iban_lookup/online.py (+2/-2) account_banking_iban_lookup/urlagent.py (+0/-1) account_banking_iban_lookup/view/res_bank.xml (+15/-0) account_banking_iban_lookup/view/res_partner_bank.xml (+23/-0) account_banking_nl_clieop/__openerp__.py (+4/-1) account_banking_nl_multibank/__openerp__.py (+1/-1) account_banking_payment/model/banking_import_transaction.py (+18/-6) |
To merge this branch: | bzr merge lp:~therp-nl/banking-addons/ba70-deprecate_iban_lookup |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Yannick Vaucher @ Camptocamp | Approve | ||
Raphaël Valyi - http://www.akretion.com | Approve | ||
Guewen Baconnier @ Camptocamp | Approve | ||
Holger Brunn (Therp) | code review | Approve | |
Review via email: mp+202520@code.launchpad.net |
Commit message
Description of the change
Splitting off the online account number (i.e. IBAN) lookup functionality into a separate module, and labelling this as deprecated. This was only ever functional for NL and maybe BE. The long diff mainly represents moving a single block of code around. Notable exception is a modification to the existing search extension on res.partner.bank which makes sure that spaces in IBANs are now ignored when searching for equivalence.
Holger Brunn (Therp) (hbrunn) : | # |
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) : | # |
Raphaël Valyi - http://www.akretion.com (rvalyi) wrote : | # |
Yannick Vaucher @ Camptocamp (yvaucher-c2c) wrote : | # |
You should remove unused import from account_banking.
account_
account_
account_
Plus I had a conflict on account_banking.py on removals of res_partner_bank and res_bank classes. Can you check that and if needed merge main branch in here to solve it.
- 228. By Stefan Rijnhart (Opener)
-
[FIX] Remove unused imports
- 229. By Stefan Rijnhart (Opener)
-
[MRG] lp:banking-addons/7.0, revno 225
- 230. By Stefan Rijnhart (Opener)
-
[MRG] Conflicting revision 226 of lp:banking-addons/7.0
- 231. By Stefan Rijnhart (Opener)
-
[RFR] Flake8
- 232. By Stefan Rijnhart (Opener)
-
[FIX] Flake8
- 233. By Stefan Rijnhart (Opener)
-
[RFR] Flake8
- 234. By Stefan Rijnhart (Opener)
-
[MRG] lp:banking-addons, revno 233
Stefan Rijnhart (Opener) (stefan-opener) wrote : | # |
Hi Yannick, thanks for the review! I removed the unused imports and carefully resolved the conflicts in revno. 226 by manually adapting the changes in code that was moved to other files.
Yannick Vaucher @ Camptocamp (yvaucher-c2c) wrote : | # |
Thanks for your changes
I'll proceed with the merge
Preview Diff
1 | === modified file 'account_banking/__init__.py' |
2 | --- account_banking/__init__.py 2013-11-17 19:45:48 +0000 |
3 | +++ account_banking/__init__.py 2014-03-15 16:07:41 +0000 |
4 | @@ -31,5 +31,7 @@ |
5 | import parsers |
6 | import wizard |
7 | import res_partner |
8 | +import res_bank |
9 | +import res_partner_bank |
10 | |
11 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
12 | |
13 | === modified file 'account_banking/__openerp__.py' |
14 | --- account_banking/__openerp__.py 2013-12-10 07:06:28 +0000 |
15 | +++ account_banking/__openerp__.py 2014-03-15 16:07:41 +0000 |
16 | @@ -33,7 +33,6 @@ |
17 | 'category': 'Banking addons', |
18 | 'depends': [ |
19 | 'account_voucher', |
20 | - 'account_iban_preserve_domestic', |
21 | ], |
22 | 'data': [ |
23 | 'security/ir.model.access.csv', |
24 | @@ -47,14 +46,9 @@ |
25 | 'js': [ |
26 | 'static/src/js/account_banking.js', |
27 | ], |
28 | - 'external_dependencies': { |
29 | - 'python' : ['BeautifulSoup'], |
30 | - }, |
31 | 'description': ''' |
32 | Module to do banking. |
33 | |
34 | - Note: This module is depending on BeautifulSoup. |
35 | - |
36 | This modules tries to combine all current banking import and export |
37 | schemes. Rationale for this is that it is quite common to have foreign |
38 | bank account numbers next to national bank account numbers. The current |
39 | |
40 | === modified file 'account_banking/account_banking.py' |
41 | --- account_banking/account_banking.py 2014-02-10 20:21:08 +0000 |
42 | +++ account_banking/account_banking.py 2014-03-15 16:07:41 +0000 |
43 | @@ -65,14 +65,8 @@ |
44 | from openerp.osv import orm, fields |
45 | from openerp.osv.osv import except_osv |
46 | from openerp.tools.translate import _ |
47 | -from openerp import netsvc, SUPERUSER_ID |
48 | +from openerp import netsvc |
49 | from openerp.addons.decimal_precision import decimal_precision as dp |
50 | -from openerp.addons.account_banking import sepa |
51 | -from openerp.addons.account_banking.wizard.banktools import get_or_create_bank |
52 | - |
53 | -def warning(title, message): |
54 | - '''Convenience routine''' |
55 | - return {'warning': {'title': title, 'message': message}} |
56 | |
57 | |
58 | class account_banking_account_settings(orm.Model): |
59 | @@ -559,408 +553,6 @@ |
60 | 'currency': _get_currency, |
61 | } |
62 | |
63 | -account_bank_statement_line() |
64 | - |
65 | - |
66 | -class res_partner_bank(orm.Model): |
67 | - ''' |
68 | - This is a hack to circumvent the very limited but widely used base_iban |
69 | - dependency. The usage of __mro__ requires inside information of |
70 | - inheritence. This code is tested and works - it bypasses base_iban |
71 | - altogether. Be sure to use 'super' for inherited classes from here though. |
72 | - |
73 | - Extended functionality: |
74 | - 1. BBAN and IBAN are considered equal |
75 | - 2. Online databases are checked when available |
76 | - 3. Banks are created on the fly when using IBAN |
77 | - 4. Storage is uppercase, not lowercase |
78 | - 5. Presentation is formal IBAN |
79 | - 6. BBAN's are generated from IBAN when possible |
80 | - 7. In the absence of online databanks, BBAN's are checked on format |
81 | - using IBAN specs. |
82 | - ''' |
83 | - _inherit = 'res.partner.bank' |
84 | - |
85 | - def __init__(self, *args, **kwargs): |
86 | - ''' |
87 | - Locate founder (first non inherited class) in inheritance tree. |
88 | - Defaults to super() |
89 | - Algorithm should prevent moving unknown classes between |
90 | - base.res_partner_bank and this module's res_partner_bank. |
91 | - ''' |
92 | - self._founder = super(res_partner_bank, self) |
93 | - self._founder.__init__(*args, **kwargs) |
94 | - mro = self.__class__.__mro__ |
95 | - for i in range(len(mro)): |
96 | - if mro[i].__module__.startswith('openerp.addons.base.'): |
97 | - self._founder = mro[i] |
98 | - break |
99 | - |
100 | - def init(self, cr): |
101 | - ''' |
102 | - Update existing iban accounts to comply to new regime |
103 | - ''' |
104 | - |
105 | - partner_bank_obj = self.pool.get('res.partner.bank') |
106 | - bank_ids = partner_bank_obj.search( |
107 | - cr, SUPERUSER_ID, [('state', '=', 'iban')], limit=0) |
108 | - for bank in partner_bank_obj.read(cr, SUPERUSER_ID, bank_ids): |
109 | - write_vals = {} |
110 | - if bank['state'] == 'iban': |
111 | - iban_acc = sepa.IBAN(bank['acc_number']) |
112 | - if iban_acc.valid: |
113 | - write_vals['acc_number_domestic'] = iban_acc.localized_BBAN |
114 | - write_vals['acc_number'] = str(iban_acc) |
115 | - elif bank['acc_number'] != bank['acc_number'].upper(): |
116 | - write_vals['acc_number'] = bank['acc_number'].upper() |
117 | - if write_vals: |
118 | - partner_bank_obj.write( |
119 | - cr, SUPERUSER_ID, bank['id'], write_vals) |
120 | - |
121 | - @staticmethod |
122 | - def _correct_IBAN(acc_number): |
123 | - ''' |
124 | - Routine to correct IBAN values and deduce localized values when valid. |
125 | - Note: No check on validity IBAN/Country |
126 | - ''' |
127 | - iban = sepa.IBAN(acc_number) |
128 | - return (str(iban), iban.localized_BBAN) |
129 | - |
130 | - def create(self, cr, uid, vals, context=None): |
131 | - ''' |
132 | - Create dual function IBAN account for SEPA countries |
133 | - ''' |
134 | - if vals.get('state') == 'iban': |
135 | - iban = (vals.get('acc_number') |
136 | - or vals.get('acc_number_domestic', False)) |
137 | - vals['acc_number'], vals['acc_number_domestic'] = ( |
138 | - self._correct_IBAN(iban)) |
139 | - return self._founder.create(self, cr, uid, vals, context) |
140 | - |
141 | - def write(self, cr, uid, ids, vals, context=None): |
142 | - ''' |
143 | - Create dual function IBAN account for SEPA countries |
144 | - |
145 | - Update the domestic account number when the IBAN is |
146 | - written, or clear the domestic number on regular account numbers. |
147 | - ''' |
148 | - if ids and isinstance(ids, (int, long)): |
149 | - ids = [ids] |
150 | - for account in self.read( |
151 | - cr, uid, ids, ['state', 'acc_number']): |
152 | - if 'state' in vals or 'acc_number' in vals: |
153 | - account.update(vals) |
154 | - if account['state'] == 'iban': |
155 | - vals['acc_number'], vals['acc_number_domestic'] = ( |
156 | - self._correct_IBAN(account['acc_number'])) |
157 | - else: |
158 | - vals['acc_number_domestic'] = False |
159 | - self._founder.write(self, cr, uid, account['id'], vals, context) |
160 | - return True |
161 | - |
162 | - def search(self, cr, uid, args, *rest, **kwargs): |
163 | - ''' |
164 | - Overwrite search, as both acc_number and iban now can be filled, so |
165 | - the original base_iban 'search and search again fuzzy' tactic now can |
166 | - result in doubled findings. Also there is now enough info to search |
167 | - for local accounts when a valid IBAN was supplied. |
168 | - |
169 | - Chosen strategy: create complex filter to find all results in just |
170 | - one search |
171 | - ''' |
172 | - |
173 | - def is_term(arg): |
174 | - '''Flag an arg as term or otherwise''' |
175 | - return isinstance(arg, (list, tuple)) and len(arg) == 3 |
176 | - |
177 | - def extended_filter_term(term): |
178 | - ''' |
179 | - Extend the search criteria in term when appropriate. |
180 | - ''' |
181 | - extra_term = None |
182 | - if term[0].lower() == 'acc_number' and term[1] in ('=', '=='): |
183 | - iban = sepa.IBAN(term[2]) |
184 | - if iban.valid: |
185 | - bban = iban.localized_BBAN |
186 | - # Prevent empty search filters |
187 | - if bban: |
188 | - extra_term = ('acc_number_domestic', term[1], bban) |
189 | - if extra_term: |
190 | - return ['|', term, extra_term] |
191 | - return [term] |
192 | - |
193 | - def extended_search_expression(args): |
194 | - ''' |
195 | - Extend the search expression in args when appropriate. |
196 | - The expression itself is in reverse polish notation, so recursion |
197 | - is not needed. |
198 | - ''' |
199 | - if not args: |
200 | - return [] |
201 | - |
202 | - all = [] |
203 | - if is_term(args[0]) and len(args) > 1: |
204 | - # Classic filter, implicit '&' |
205 | - all += ['&'] |
206 | - |
207 | - for arg in args: |
208 | - if is_term(arg): |
209 | - all += extended_filter_term(arg) |
210 | - else: |
211 | - all += arg |
212 | - return all |
213 | - |
214 | - # Extend search filter |
215 | - newargs = extended_search_expression(args) |
216 | - |
217 | - # Original search |
218 | - results = super(res_partner_bank, self).search( |
219 | - cr, uid, newargs, *rest, **kwargs) |
220 | - return results |
221 | - |
222 | - def read( |
223 | - self, cr, uid, ids, fields=None, context=None, load='_classic_read'): |
224 | - ''' |
225 | - Convert IBAN electronic format to IBAN display format |
226 | - SR 2012-02-19: do we really need this? Fields are converted upon write already. |
227 | - ''' |
228 | - if fields and 'state' not in fields: |
229 | - fields.append('state') |
230 | - records = self._founder.read(self, cr, uid, ids, fields, context, load) |
231 | - is_list = True |
232 | - if not isinstance(records, list): |
233 | - records = [records,] |
234 | - is_list = False |
235 | - for record in records: |
236 | - if 'acc_number' in record and record['state'] == 'iban': |
237 | - record['acc_number'] = unicode(sepa.IBAN(record['acc_number'])) |
238 | - if is_list: |
239 | - return records |
240 | - return records[0] |
241 | - |
242 | - def check_iban(self, cr, uid, ids, context=None): |
243 | - ''' |
244 | - Check IBAN number |
245 | - ''' |
246 | - for bank_acc in self.browse(cr, uid, ids, context=context): |
247 | - if bank_acc.state == 'iban' and bank_acc.acc_number: |
248 | - iban = sepa.IBAN(bank_acc.acc_number) |
249 | - if not iban.valid: |
250 | - return False |
251 | - return True |
252 | - |
253 | - def get_bban_from_iban(self, cr, uid, ids, context=None): |
254 | - ''' |
255 | - Return the local bank account number aka BBAN from the IBAN. |
256 | - ''' |
257 | - res = {} |
258 | - for record in self.browse(cr, uid, ids, context): |
259 | - if not record.state == 'iban': |
260 | - res[record.id] = False |
261 | - else: |
262 | - iban_acc = sepa.IBAN(record.acc_number) |
263 | - res[record.id] = iban_acc.localized_BBAN |
264 | - return res |
265 | - |
266 | - def onchange_acc_number( |
267 | - self, cr, uid, ids, acc_number, acc_number_domestic, |
268 | - state, partner_id, country_id, context=None): |
269 | - if state == 'iban': |
270 | - return self.onchange_iban( |
271 | - cr, uid, ids, acc_number, acc_number_domestic, |
272 | - state, partner_id, country_id, context=None |
273 | - ) |
274 | - else: |
275 | - return self.onchange_domestic( |
276 | - cr, uid, ids, acc_number, |
277 | - partner_id, country_id, context=None |
278 | - ) |
279 | - |
280 | - def onchange_domestic( |
281 | - self, cr, uid, ids, acc_number, |
282 | - partner_id, country_id, context=None): |
283 | - ''' |
284 | - Trigger to find IBAN. When found: |
285 | - 1. Reformat BBAN |
286 | - 2. Autocomplete bank |
287 | - |
288 | - TODO: prevent unnecessary assignment of country_ids and |
289 | - browsing of the country |
290 | - ''' |
291 | - if not acc_number: |
292 | - return {} |
293 | - |
294 | - values = {} |
295 | - country_obj = self.pool.get('res.country') |
296 | - country_ids = [] |
297 | - country = False |
298 | - |
299 | - # Pre fill country based on available data. This is just a default |
300 | - # which can be overridden by the user. |
301 | - # 1. Use provided country_id (manually filled) |
302 | - if country_id: |
303 | - country = country_obj.browse(cr, uid, country_id, context=context) |
304 | - country_ids = [country_id] |
305 | - # 2. Use country_id of found bank accounts |
306 | - # This can be usefull when there is no country set in the partners |
307 | - # addresses, but there was a country set in the address for the bank |
308 | - # account itself before this method was triggered. |
309 | - elif ids and len(ids) == 1: |
310 | - partner_bank_obj = self.pool.get('res.partner.bank') |
311 | - partner_bank_id = partner_bank_obj.browse(cr, uid, ids[0], context=context) |
312 | - if partner_bank_id.country_id: |
313 | - country = partner_bank_id.country_id |
314 | - country_ids = [country.id] |
315 | - # 3. Use country_id of default address of partner |
316 | - # The country_id of a bank account is a one time default on creation. |
317 | - # It originates in the same address we are about to check, but |
318 | - # modifications on that address afterwards are not transfered to the |
319 | - # bank account, hence the additional check. |
320 | - elif partner_id: |
321 | - partner_obj = self.pool.get('res.partner') |
322 | - country = partner_obj.browse(cr, uid, partner_id, context=context).country |
323 | - country_ids = country and [country.id] or [] |
324 | - # 4. Without any of the above, take the country from the company of |
325 | - # the handling user |
326 | - if not country_ids: |
327 | - user = self.pool.get('res.users').browse(cr, uid, uid, context=context) |
328 | - # Try user companies partner (user no longer has address in 6.1) |
329 | - if (user.company_id and |
330 | - user.company_id.partner_id and |
331 | - user.company_id.partner_id.country |
332 | - ): |
333 | - country_ids = [user.company_id.partner_id.country.id] |
334 | - else: |
335 | - if (user.company_id and user.company_id.partner_id and |
336 | - user.company_id.partner_id.country): |
337 | - country_ids = [user.company_id.partner_id.country.id] |
338 | - else: |
339 | - # Ok, tried everything, give up and leave it to the user |
340 | - return warning(_('Insufficient data'), |
341 | - _('Insufficient data to select online ' |
342 | - 'conversion database') |
343 | - ) |
344 | - result = {'value': values} |
345 | - # Complete data with online database when available |
346 | - if country_ids: |
347 | - country = country_obj.browse( |
348 | - cr, uid, country_ids[0], context=context) |
349 | - values['country_id'] = country_ids[0] |
350 | - if country and country.code in sepa.IBAN.countries: |
351 | - info = sepa.online.account_info(country.code, acc_number) |
352 | - if info: |
353 | - iban_acc = sepa.IBAN(info.iban) |
354 | - if iban_acc.valid: |
355 | - values['acc_number_domestic'] = iban_acc.localized_BBAN |
356 | - values['acc_number'] = unicode(iban_acc) |
357 | - values['state'] = 'iban' |
358 | - bank_id, country_id = get_or_create_bank( |
359 | - self.pool, cr, uid, |
360 | - info.bic or iban_acc.BIC_searchkey, |
361 | - name = info.bank |
362 | - ) |
363 | - if country_id: |
364 | - values['country_id'] = country_id |
365 | - values['bank'] = bank_id or False |
366 | - if info.bic: |
367 | - values['bank_bic'] = info.bic |
368 | - else: |
369 | - info = None |
370 | - if info is None: |
371 | - result.update(warning( |
372 | - _('Invalid data'), |
373 | - _('The account number appears to be invalid for %s') |
374 | - % country.name |
375 | - )) |
376 | - if info is False: |
377 | - if country.code in sepa.IBAN.countries: |
378 | - acc_number_fmt = sepa.BBAN(acc_number, country.code) |
379 | - if acc_number_fmt.valid: |
380 | - values['acc_number_domestic'] = str(acc_number_fmt) |
381 | - else: |
382 | - result.update(warning( |
383 | - _('Invalid format'), |
384 | - _('The account number has the wrong format ' |
385 | - 'for %(country)s') |
386 | - % {'country': country.name} |
387 | - )) |
388 | - return result |
389 | - |
390 | - def onchange_iban( |
391 | - self, cr, uid, ids, acc_number, acc_number_domestic, |
392 | - state, partner_id, country_id, context=None): |
393 | - ''' |
394 | - Trigger to verify IBAN. When valid: |
395 | - 1. Extract BBAN as local account |
396 | - 2. Auto complete bank |
397 | - ''' |
398 | - if not acc_number: |
399 | - return {} |
400 | - |
401 | - iban_acc = sepa.IBAN(acc_number) |
402 | - if iban_acc.valid: |
403 | - bank_id, country_id = get_or_create_bank( |
404 | - self.pool, cr, uid, iban_acc.BIC_searchkey, |
405 | - code=iban_acc.BIC_searchkey |
406 | - ) |
407 | - return { |
408 | - 'value': dict( |
409 | - acc_number_domestic = iban_acc.localized_BBAN, |
410 | - acc_number = unicode(iban_acc), |
411 | - country = country_id or False, |
412 | - bank = bank_id or False, |
413 | - ) |
414 | - } |
415 | - return warning(_('Invalid IBAN account number!'), |
416 | - _("The IBAN number doesn't seem to be correct") |
417 | - ) |
418 | - |
419 | -res_partner_bank() |
420 | - |
421 | - |
422 | -class res_bank(orm.Model): |
423 | - ''' |
424 | - Add a on_change trigger to automagically fill bank details from the |
425 | - online SWIFT database. Allow hand filled names to overrule SWIFT names. |
426 | - ''' |
427 | - _inherit = 'res.bank' |
428 | - |
429 | - def onchange_bic(self, cr, uid, ids, bic, name, context=None): |
430 | - ''' |
431 | - Trigger to auto complete other fields. |
432 | - ''' |
433 | - if not bic: |
434 | - return {} |
435 | - |
436 | - info, address = sepa.online.bank_info(bic) |
437 | - if not info: |
438 | - return {} |
439 | - |
440 | - if address and address.country_id: |
441 | - country_id = self.pool.get('res.country').search( |
442 | - cr, uid, [('code','=',address.country_id)] |
443 | - ) |
444 | - country_id = country_id and country_id[0] or False |
445 | - else: |
446 | - country_id = False |
447 | - |
448 | - return { |
449 | - 'value': dict( |
450 | - # Only the first eight positions of BIC are used for bank |
451 | - # transfers, so ditch the rest. |
452 | - bic = info.bic[:8], |
453 | - street = address.street, |
454 | - street2 = |
455 | - address.has_key('street2') and address.street2 or False, |
456 | - zip = address.zip, |
457 | - city = address.city, |
458 | - country = country_id, |
459 | - name = name and name or info.name, |
460 | - ) |
461 | - } |
462 | - |
463 | -res_bank() |
464 | - |
465 | |
466 | class invoice(orm.Model): |
467 | ''' |
468 | |
469 | === modified file 'account_banking/account_banking_view.xml' |
470 | --- account_banking/account_banking_view.xml 2014-03-03 11:21:17 +0000 |
471 | +++ account_banking/account_banking_view.xml 2014-03-15 16:07:41 +0000 |
472 | @@ -289,35 +289,6 @@ |
473 | </field> |
474 | </record> |
475 | |
476 | - <record id="view_partner_bank_account_banking_form_2" model="ir.ui.view"> |
477 | - <field name="name">res.partner.bank.form.banking-2</field> |
478 | - <field name="model">res.partner.bank</field> |
479 | - <field name="inherit_id" ref="base.view_partner_bank_form"/> |
480 | - <field name="priority" eval="24"/> |
481 | - <field name="arch" type="xml"> |
482 | - <data> |
483 | - <field name="acc_number" position="attributes"> |
484 | - <attribute name="on_change">onchange_acc_number(acc_number, acc_number_domestic, state, partner_id, country_id)</attribute> |
485 | - </field> |
486 | - <field name="acc_number_domestic" position="attributes"> |
487 | - <attribute name="on_change">onchange_domestic(acc_number_domestic, partner_id, country_id)</attribute> |
488 | - </field> |
489 | - </data> |
490 | - </field> |
491 | - </record> |
492 | - |
493 | - <!-- Set trigger on BIC in res_bank form --> |
494 | - <record id="view_res_bank_account_banking_form_1" model="ir.ui.view"> |
495 | - <field name="name">res.bank.form.banking-1</field> |
496 | - <field name="model">res.bank</field> |
497 | - <field name="inherit_id" ref="base.view_res_bank_form"/> |
498 | - <field name="arch" type="xml"> |
499 | - <field name="bic" position="replace"> |
500 | - <field name="bic" on_change="onchange_bic(bic, name)"/> |
501 | - </field> |
502 | - </field> |
503 | - </record> |
504 | - |
505 | <record model="ir.ui.view" id="view_bank_statement_line_tree"> |
506 | <field name="name">Bank statement line tree view</field> |
507 | <field name="model">account.bank.statement.line</field> |
508 | |
509 | === added file 'account_banking/res_bank.py' |
510 | --- account_banking/res_bank.py 1970-01-01 00:00:00 +0000 |
511 | +++ account_banking/res_bank.py 2014-03-15 16:07:41 +0000 |
512 | @@ -0,0 +1,31 @@ |
513 | +# -*- coding: utf-8 -*- |
514 | +############################################################################## |
515 | +# |
516 | +# Copyright 2011 - 2014 Therp BV (<http://therp.nl>). |
517 | +# |
518 | +# This program is free software: you can redistribute it and/or modify |
519 | +# it under the terms of the GNU Affero General Public License as |
520 | +# published by the Free Software Foundation, either version 3 of the |
521 | +# License, or (at your option) any later version. |
522 | +# |
523 | +# This program is distributed in the hope that it will be useful, |
524 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
525 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
526 | +# GNU Affero General Public License for more details. |
527 | +# |
528 | +# You should have received a copy of the GNU Affero General Public License |
529 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
530 | +# |
531 | +############################################################################## |
532 | +from openerp.osv import orm |
533 | + |
534 | + |
535 | +class ResBank(orm.Model): |
536 | + _inherit = 'res.bank' |
537 | + |
538 | + def online_bank_info(self, cr, uid, bic, context=None): |
539 | + """ |
540 | + API hook for legacy online lookup of BICs, |
541 | + to be removed in OpenERP 8.0. |
542 | + """ |
543 | + return False, False |
544 | |
545 | === added file 'account_banking/res_partner_bank.py' |
546 | --- account_banking/res_partner_bank.py 1970-01-01 00:00:00 +0000 |
547 | +++ account_banking/res_partner_bank.py 2014-03-15 16:07:41 +0000 |
548 | @@ -0,0 +1,101 @@ |
549 | +# -*- coding: utf-8 -*- |
550 | +############################################################################## |
551 | +# |
552 | +# Copyright (C) 2009 EduSense BV (<http://www.edusense.nl>). |
553 | +# (C) 2011 - 2014 Therp BV (<http://therp.nl>). |
554 | +# |
555 | +# This program is free software: you can redistribute it and/or modify |
556 | +# it under the terms of the GNU Affero General Public License as |
557 | +# published by the Free Software Foundation, either version 3 of the |
558 | +# License, or (at your option) any later version. |
559 | +# |
560 | +# This program is distributed in the hope that it will be useful, |
561 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
562 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
563 | +# GNU Affero General Public License for more details. |
564 | +# |
565 | +# You should have received a copy of the GNU Affero General Public License |
566 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
567 | +# |
568 | +############################################################################## |
569 | +from openerp.osv import orm |
570 | +from openerp.addons.account_banking import sepa |
571 | + |
572 | + |
573 | +class ResPartnerBank(orm.Model): |
574 | + _inherit = 'res.partner.bank' |
575 | + |
576 | + def online_account_info( |
577 | + self, cr, uid, country_code, acc_number, context=None): |
578 | + """ |
579 | + API hook for legacy online lookup of account info, |
580 | + to be removed in OpenERP 8.0. |
581 | + """ |
582 | + return False |
583 | + |
584 | + def search(self, cr, uid, args, *rest, **kwargs): |
585 | + """ |
586 | + When a complete IBAN is searched, also search for its BBAN |
587 | + if we have the domestic column. Disregard spaces |
588 | + when comparing IBANs. |
589 | + """ |
590 | + |
591 | + def is_term(arg): |
592 | + '''Flag an arg as term or otherwise''' |
593 | + return isinstance(arg, (list, tuple)) and len(arg) == 3 |
594 | + |
595 | + def extended_filter_term(term): |
596 | + ''' |
597 | + Extend the search criteria in term when appropriate. |
598 | + ''' |
599 | + result = [term] |
600 | + extra_terms = [] |
601 | + if term[0].lower() == 'acc_number' and term[1] in ('=', '=='): |
602 | + iban = sepa.IBAN(term[2]) |
603 | + if iban.valid: |
604 | + # Disregard spaces when comparing IBANs |
605 | + cr.execute( |
606 | + """ |
607 | + SELECT id FROM res_partner_bank |
608 | + WHERE replace(acc_number, ' ', '') = %s |
609 | + """, (term[2].replace(' ', ''),)) |
610 | + ids = [row[0] for row in cr.fetchall()] |
611 | + result = [('id', 'in', ids)] |
612 | + |
613 | + if 'acc_number_domestic' in self._columns: |
614 | + bban = iban.localized_BBAN |
615 | + # Prevent empty search filters |
616 | + if bban: |
617 | + extra_terms.append( |
618 | + ('acc_number_domestic', term[1], bban)) |
619 | + for extra_term in extra_terms: |
620 | + result = ['|'] + result + [extra_term] |
621 | + return result |
622 | + |
623 | + def extended_search_expression(args): |
624 | + ''' |
625 | + Extend the search expression in args when appropriate. |
626 | + The expression itself is in reverse polish notation, so recursion |
627 | + is not needed. |
628 | + ''' |
629 | + if not args: |
630 | + return [] |
631 | + |
632 | + result = [] |
633 | + if is_term(args[0]) and len(args) > 1: |
634 | + # Classic filter, implicit '&' |
635 | + result += ['&'] |
636 | + |
637 | + for arg in args: |
638 | + if is_term(arg): |
639 | + result += extended_filter_term(arg) |
640 | + else: |
641 | + result += arg |
642 | + return result |
643 | + |
644 | + # Extend search filter |
645 | + newargs = extended_search_expression(args) |
646 | + |
647 | + # Original search |
648 | + return super(ResPartnerBank, self).search( |
649 | + cr, uid, newargs, *rest, **kwargs) |
650 | |
651 | === modified file 'account_banking/sepa/__init__.py' |
652 | --- account_banking/sepa/__init__.py 2013-04-15 13:59:50 +0000 |
653 | +++ account_banking/sepa/__init__.py 2014-03-15 16:07:41 +0000 |
654 | @@ -19,6 +19,5 @@ |
655 | # |
656 | ############################################################################## |
657 | import iban |
658 | -import online |
659 | IBAN = iban.IBAN |
660 | BBAN = iban.BBAN |
661 | |
662 | === modified file 'account_banking/wizard/banktools.py' |
663 | --- account_banking/wizard/banktools.py 2013-09-14 11:54:23 +0000 |
664 | +++ account_banking/wizard/banktools.py 2014-03-15 16:07:41 +0000 |
665 | @@ -64,12 +64,6 @@ |
666 | ('acc_number', '=', account_number) |
667 | ]) |
668 | if not bank_account_ids: |
669 | - # SR 2012-02-19 does the search() override in res_partner_bank |
670 | - # provides this result on the previous query? |
671 | - bank_account_ids = partner_bank_obj.search(cr, uid, [ |
672 | - ('acc_number_domestic', '=', account_number) |
673 | - ]) |
674 | - if not bank_account_ids: |
675 | if not fail: |
676 | log.append( |
677 | _('Bank account %(account_no)s was not found in the database') |
678 | @@ -237,7 +231,7 @@ |
679 | bank_id = False |
680 | |
681 | if online: |
682 | - info, address = sepa.online.bank_info(bic) |
683 | + info, address = bank_obj.online_bank_info(cr, uid, bic, context=context) |
684 | if info: |
685 | bank_id = bank_obj.create(cr, uid, dict( |
686 | code = info.code, |
687 | @@ -301,7 +295,6 @@ |
688 | owner_name = holder_name, |
689 | country_id = country_id, |
690 | ) |
691 | - bankcode = None |
692 | |
693 | # Are we dealing with IBAN? |
694 | iban = sepa.IBAN(account_number) |
695 | @@ -309,23 +302,20 @@ |
696 | # Take as much info as possible from IBAN |
697 | values.state = 'iban' |
698 | values.acc_number = str(iban) |
699 | - values.acc_number_domestic = iban.BBAN |
700 | - bankcode = iban.bankcode + iban.countrycode |
701 | else: |
702 | # No, try to convert to IBAN |
703 | values.state = 'bank' |
704 | - values.acc_number = values.acc_number_domestic = account_number |
705 | + values.acc_number = account_number |
706 | |
707 | if country_id: |
708 | country_code = pool.get('res.country').read( |
709 | cr, uid, country_id, ['code'], context=context)['code'] |
710 | if country_code in sepa.IBAN.countries: |
711 | - account_info = sepa.online.account_info( |
712 | - country_code, values.acc_number) |
713 | + account_info = pool['res.partner.bank'].online_account_info( |
714 | + cr, uid, country_code, values.acc_number, context=context) |
715 | if account_info: |
716 | values.acc_number = iban = account_info.iban |
717 | values.state = 'iban' |
718 | - bankcode = account_info.code |
719 | bic = account_info.bic |
720 | |
721 | if bic: |
722 | |
723 | === added directory 'account_banking_iban_lookup' |
724 | === added file 'account_banking_iban_lookup/__init__.py' |
725 | --- account_banking_iban_lookup/__init__.py 1970-01-01 00:00:00 +0000 |
726 | +++ account_banking_iban_lookup/__init__.py 2014-03-15 16:07:41 +0000 |
727 | @@ -0,0 +1,3 @@ |
728 | +from . import online |
729 | +from . import urlagent |
730 | +from . import model |
731 | |
732 | === added file 'account_banking_iban_lookup/__openerp__.py' |
733 | --- account_banking_iban_lookup/__openerp__.py 1970-01-01 00:00:00 +0000 |
734 | +++ account_banking_iban_lookup/__openerp__.py 2014-03-15 16:07:41 +0000 |
735 | @@ -0,0 +1,52 @@ |
736 | +# -*- coding: utf-8 -*- |
737 | +############################################################################## |
738 | +# |
739 | +# Copyright (C) 2009 EduSense BV (<http://www.edusense.nl>). |
740 | +# (C) 2011 - 2014 Therp BV (<http://therp.nl>). |
741 | +# |
742 | +# This program is free software: you can redistribute it and/or modify |
743 | +# it under the terms of the GNU Affero General Public License as |
744 | +# published by the Free Software Foundation, either version 3 of the |
745 | +# License, or (at your option) any later version. |
746 | +# |
747 | +# This program is distributed in the hope that it will be useful, |
748 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
749 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
750 | +# GNU Affero General Public License for more details. |
751 | +# |
752 | +# You should have received a copy of the GNU Affero General Public License |
753 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
754 | +# |
755 | +############################################################################## |
756 | + |
757 | +{ |
758 | + 'name': 'Banking Addons - Iban lookup (legacy)', |
759 | + 'version': '0.1', |
760 | + 'license': 'AGPL-3', |
761 | + 'author': 'Banking addons community', |
762 | + 'website': 'https://launchpad.net/banking-addons', |
763 | + 'category': 'Banking addons', |
764 | + 'depends': [ |
765 | + 'account_banking', |
766 | + 'account_iban_preserve_domestic', |
767 | + ], |
768 | + 'data': [ |
769 | + 'view/res_bank.xml', |
770 | + 'view/res_partner_bank.xml', |
771 | + ], |
772 | + 'external_dependencies': { |
773 | + 'python': ['BeautifulSoup'], |
774 | + }, |
775 | + 'description': ''' |
776 | +This addons contains the legacy infrastructure for autocompletion of IBANs |
777 | +and BBANs. |
778 | + |
779 | +The autocompletion was implemented for Dutch IBANs, but as it turns out |
780 | +the online database that it consults does not get updated. As a result, |
781 | +the autocompletion will come up with outdated IBANs and BICs. |
782 | + |
783 | +This module is deprecated and will be dropped in OpenERP 8.0. |
784 | + ''', |
785 | + 'auto_install': False, |
786 | + 'installable': True, |
787 | +} |
788 | |
789 | === added directory 'account_banking_iban_lookup/model' |
790 | === added file 'account_banking_iban_lookup/model/__init__.py' |
791 | --- account_banking_iban_lookup/model/__init__.py 1970-01-01 00:00:00 +0000 |
792 | +++ account_banking_iban_lookup/model/__init__.py 2014-03-15 16:07:41 +0000 |
793 | @@ -0,0 +1,2 @@ |
794 | +from . import res_bank |
795 | +from . import res_partner_bank |
796 | |
797 | === added file 'account_banking_iban_lookup/model/res_bank.py' |
798 | --- account_banking_iban_lookup/model/res_bank.py 1970-01-01 00:00:00 +0000 |
799 | +++ account_banking_iban_lookup/model/res_bank.py 2014-03-15 16:07:41 +0000 |
800 | @@ -0,0 +1,63 @@ |
801 | +# -*- coding: utf-8 -*- |
802 | +############################################################################## |
803 | +# |
804 | +# Copyright (C) 2009 EduSense BV (<http://www.edusense.nl>). |
805 | +# (C) 2011 - 2014 Therp BV (<http://therp.nl>). |
806 | +# |
807 | +# This program is free software: you can redistribute it and/or modify |
808 | +# it under the terms of the GNU Affero General Public License as |
809 | +# published by the Free Software Foundation, either version 3 of the |
810 | +# License, or (at your option) any later version. |
811 | +# |
812 | +# This program is distributed in the hope that it will be useful, |
813 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
814 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
815 | +# GNU Affero General Public License for more details. |
816 | +# |
817 | +# You should have received a copy of the GNU Affero General Public License |
818 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
819 | +# |
820 | +############################################################################## |
821 | +from openerp.osv import orm |
822 | +from openerp.addons.account_banking_iban_lookup import online |
823 | + |
824 | + |
825 | +class ResBank(orm.Model): |
826 | + _inherit = 'res.bank' |
827 | + |
828 | + def online_bank_info(self, cr, uid, bic, context=None): |
829 | + """ |
830 | + Overwrite existing API hook from account_banking |
831 | + """ |
832 | + return online.bank_info(bic) |
833 | + |
834 | + def onchange_bic( |
835 | + self, cr, uid, ids, bic, name, context=None): |
836 | + |
837 | + if not bic: |
838 | + return {} |
839 | + |
840 | + info, address = online.bank_info(bic) |
841 | + if not info: |
842 | + return {} |
843 | + |
844 | + if address and address.country_id: |
845 | + country_ids = self.pool.get('res.country').search( |
846 | + cr, uid, [('code', '=', address.country_id)]) |
847 | + country_id = country_ids[0] if country_ids else False |
848 | + else: |
849 | + country_id = False |
850 | + |
851 | + return { |
852 | + 'value': dict( |
853 | + # Only the first eight positions of BIC are used for bank |
854 | + # transfers, so ditch the rest. |
855 | + bic=info.bic[:8], |
856 | + street=address.street, |
857 | + street2=address.get('street2', False), |
858 | + zip=address.zip, |
859 | + city=address.city, |
860 | + country=country_id, |
861 | + name=name or info.name, |
862 | + ) |
863 | + } |
864 | |
865 | === added file 'account_banking_iban_lookup/model/res_partner_bank.py' |
866 | --- account_banking_iban_lookup/model/res_partner_bank.py 1970-01-01 00:00:00 +0000 |
867 | +++ account_banking_iban_lookup/model/res_partner_bank.py 2014-03-15 16:07:41 +0000 |
868 | @@ -0,0 +1,271 @@ |
869 | +# -*- coding: utf-8 -*- |
870 | +############################################################################## |
871 | +# |
872 | +# Copyright (C) 2009 EduSense BV (<http://www.edusense.nl>). |
873 | +# (C) 2011 - 2014 Therp BV (<http://therp.nl>). |
874 | +# |
875 | +# All other contributions are (C) by their respective contributors |
876 | +# |
877 | +# All Rights Reserved |
878 | +# |
879 | +# This program is free software: you can redistribute it and/or modify |
880 | +# it under the terms of the GNU Affero General Public License as |
881 | +# published by the Free Software Foundation, either version 3 of the |
882 | +# License, or (at your option) any later version. |
883 | +# |
884 | +# This program is distributed in the hope that it will be useful, |
885 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
886 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
887 | +# GNU Affero General Public License for more details. |
888 | +# |
889 | +# You should have received a copy of the GNU Affero General Public License |
890 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
891 | +# |
892 | +############################################################################## |
893 | +from openerp import SUPERUSER_ID |
894 | +from openerp.osv import orm |
895 | +from openerp.tools.translate import _ |
896 | +from openerp.addons.account_banking_iban_lookup import online |
897 | +from openerp.addons.account_banking import sepa |
898 | +from openerp.addons.account_banking.wizard.banktools import get_or_create_bank |
899 | + |
900 | + |
901 | +def warning(title, message): |
902 | + '''Convenience routine''' |
903 | + return {'warning': {'title': title, 'message': message}} |
904 | + |
905 | + |
906 | +class res_partner_bank(orm.Model): |
907 | + ''' |
908 | + Extended functionality: |
909 | + 1. BBAN and IBAN are considered equal |
910 | + 2. Online lookup when an API is available (providing NL in this module) |
911 | + 3. Banks are created on the fly when using IBAN + online |
912 | + 4. IBAN formatting |
913 | + 5. BBAN's are generated from IBAN when possible |
914 | + ''' |
915 | + _inherit = 'res.partner.bank' |
916 | + |
917 | + def init(self, cr): |
918 | + ''' |
919 | + Update existing iban accounts to comply to new regime |
920 | + ''' |
921 | + |
922 | + partner_bank_obj = self.pool.get('res.partner.bank') |
923 | + bank_ids = partner_bank_obj.search( |
924 | + cr, SUPERUSER_ID, [('state', '=', 'iban')], limit=0) |
925 | + for bank in partner_bank_obj.read(cr, SUPERUSER_ID, bank_ids): |
926 | + write_vals = {} |
927 | + if bank['state'] == 'iban': |
928 | + iban_acc = sepa.IBAN(bank['acc_number']) |
929 | + if iban_acc.valid: |
930 | + write_vals['acc_number_domestic'] = iban_acc.localized_BBAN |
931 | + write_vals['acc_number'] = str(iban_acc) |
932 | + elif bank['acc_number'] != bank['acc_number'].upper(): |
933 | + write_vals['acc_number'] = bank['acc_number'].upper() |
934 | + if write_vals: |
935 | + partner_bank_obj.write( |
936 | + cr, SUPERUSER_ID, bank['id'], write_vals) |
937 | + |
938 | + @staticmethod |
939 | + def _correct_IBAN(acc_number): |
940 | + ''' |
941 | + Routine to correct IBAN values and deduce localized values when valid. |
942 | + Note: No check on validity IBAN/Country |
943 | + ''' |
944 | + iban = sepa.IBAN(acc_number) |
945 | + return (str(iban), iban.localized_BBAN) |
946 | + |
947 | + def create(self, cr, uid, vals, context=None): |
948 | + ''' |
949 | + Create dual function IBAN account for SEPA countries |
950 | + ''' |
951 | + if vals.get('state') == 'iban': |
952 | + iban = (vals.get('acc_number') |
953 | + or vals.get('acc_number_domestic', False)) |
954 | + vals['acc_number'], vals['acc_number_domestic'] = ( |
955 | + self._correct_IBAN(iban)) |
956 | + return super(res_partner_bank, self).create( |
957 | + cr, uid, vals, context) |
958 | + |
959 | + def write(self, cr, uid, ids, vals, context=None): |
960 | + ''' |
961 | + Create dual function IBAN account for SEPA countries |
962 | + |
963 | + Update the domestic account number when the IBAN is |
964 | + written, or clear the domestic number on regular account numbers. |
965 | + ''' |
966 | + if ids and isinstance(ids, (int, long)): |
967 | + ids = [ids] |
968 | + for account in self.read( |
969 | + cr, uid, ids, ['state', 'acc_number']): |
970 | + if 'state' in vals or 'acc_number' in vals: |
971 | + account.update(vals) |
972 | + if account['state'] == 'iban': |
973 | + vals['acc_number'], vals['acc_number_domestic'] = ( |
974 | + self._correct_IBAN(account['acc_number'])) |
975 | + else: |
976 | + vals['acc_number_domestic'] = False |
977 | + super(res_partner_bank, self).write( |
978 | + cr, uid, account['id'], vals, context) |
979 | + return True |
980 | + |
981 | + def onchange_acc_number( |
982 | + self, cr, uid, ids, acc_number, acc_number_domestic, |
983 | + state, partner_id, country_id, context=None): |
984 | + if state == 'iban': |
985 | + return self.onchange_iban( |
986 | + cr, uid, ids, acc_number, acc_number_domestic, |
987 | + state, partner_id, country_id, context=None |
988 | + ) |
989 | + else: |
990 | + return self.onchange_domestic( |
991 | + cr, uid, ids, acc_number, |
992 | + partner_id, country_id, context=None |
993 | + ) |
994 | + |
995 | + def onchange_domestic( |
996 | + self, cr, uid, ids, acc_number, |
997 | + partner_id, country_id, context=None): |
998 | + ''' |
999 | + Trigger to find IBAN. When found: |
1000 | + 1. Reformat BBAN |
1001 | + 2. Autocomplete bank |
1002 | + |
1003 | + TODO: prevent unnecessary assignment of country_ids and |
1004 | + browsing of the country |
1005 | + ''' |
1006 | + if not acc_number: |
1007 | + return {} |
1008 | + |
1009 | + values = {} |
1010 | + country_obj = self.pool.get('res.country') |
1011 | + country_ids = [] |
1012 | + country = False |
1013 | + |
1014 | + # Pre fill country based on available data. This is just a default |
1015 | + # which can be overridden by the user. |
1016 | + # 1. Use provided country_id (manually filled) |
1017 | + if country_id: |
1018 | + country = country_obj.browse(cr, uid, country_id, context=context) |
1019 | + country_ids = [country_id] |
1020 | + # 2. Use country_id of found bank accounts |
1021 | + # This can be usefull when there is no country set in the partners |
1022 | + # addresses, but there was a country set in the address for the bank |
1023 | + # account itself before this method was triggered. |
1024 | + elif ids and len(ids) == 1: |
1025 | + partner_bank_obj = self.pool.get('res.partner.bank') |
1026 | + partner_bank_id = partner_bank_obj.browse( |
1027 | + cr, uid, ids[0], context=context) |
1028 | + if partner_bank_id.country_id: |
1029 | + country = partner_bank_id.country_id |
1030 | + country_ids = [country.id] |
1031 | + # 3. Use country_id of default address of partner |
1032 | + # The country_id of a bank account is a one time default on creation. |
1033 | + # It originates in the same address we are about to check, but |
1034 | + # modifications on that address afterwards are not transfered to the |
1035 | + # bank account, hence the additional check. |
1036 | + elif partner_id: |
1037 | + partner_obj = self.pool.get('res.partner') |
1038 | + country = partner_obj.browse( |
1039 | + cr, uid, partner_id, context=context).country |
1040 | + country_ids = country and [country.id] or [] |
1041 | + # 4. Without any of the above, take the country from the company of |
1042 | + # the handling user |
1043 | + if not country_ids: |
1044 | + user = self.pool.get('res.users').browse( |
1045 | + cr, uid, uid, context=context) |
1046 | + # Try user companies partner (user no longer has address in 6.1) |
1047 | + if (user.company_id and |
1048 | + user.company_id.partner_id and |
1049 | + user.company_id.partner_id.country): |
1050 | + country_ids = [user.company_id.partner_id.country.id] |
1051 | + else: |
1052 | + if (user.company_id and user.company_id.partner_id and |
1053 | + user.company_id.partner_id.country): |
1054 | + country_ids = [user.company_id.partner_id.country.id] |
1055 | + else: |
1056 | + # Ok, tried everything, give up and leave it to the user |
1057 | + return warning(_('Insufficient data'), |
1058 | + _('Insufficient data to select online ' |
1059 | + 'conversion database') |
1060 | + ) |
1061 | + result = {'value': values} |
1062 | + # Complete data with online database when available |
1063 | + if country_ids: |
1064 | + country = country_obj.browse( |
1065 | + cr, uid, country_ids[0], context=context) |
1066 | + values['country_id'] = country_ids[0] |
1067 | + if country and country.code in sepa.IBAN.countries: |
1068 | + info = online.account_info(country.code, acc_number) |
1069 | + if info: |
1070 | + iban_acc = sepa.IBAN(info.iban) |
1071 | + if iban_acc.valid: |
1072 | + values['acc_number_domestic'] = iban_acc.localized_BBAN |
1073 | + values['acc_number'] = unicode(iban_acc) |
1074 | + values['state'] = 'iban' |
1075 | + bank_id, country_id = get_or_create_bank( |
1076 | + self.pool, cr, uid, |
1077 | + info.bic or iban_acc.BIC_searchkey, |
1078 | + name=info.bank) |
1079 | + if country_id: |
1080 | + values['country_id'] = country_id |
1081 | + values['bank'] = bank_id or False |
1082 | + if info.bic: |
1083 | + values['bank_bic'] = info.bic |
1084 | + else: |
1085 | + info = None |
1086 | + if info is None: |
1087 | + result.update(warning( |
1088 | + _('Invalid data'), |
1089 | + _('The account number appears to be invalid for %s') |
1090 | + % country.name |
1091 | + )) |
1092 | + if info is False: |
1093 | + if country.code in sepa.IBAN.countries: |
1094 | + acc_number_fmt = sepa.BBAN(acc_number, country.code) |
1095 | + if acc_number_fmt.valid: |
1096 | + values['acc_number_domestic'] = str(acc_number_fmt) |
1097 | + else: |
1098 | + result.update(warning( |
1099 | + _('Invalid format'), |
1100 | + _('The account number has the wrong format for %s') |
1101 | + % country.name |
1102 | + )) |
1103 | + return result |
1104 | + |
1105 | + def onchange_iban( |
1106 | + self, cr, uid, ids, acc_number, acc_number_domestic, |
1107 | + state, partner_id, country_id, context=None): |
1108 | + ''' |
1109 | + Trigger to verify IBAN. When valid: |
1110 | + 1. Extract BBAN as local account |
1111 | + 2. Auto complete bank |
1112 | + ''' |
1113 | + if not acc_number: |
1114 | + return {} |
1115 | + |
1116 | + iban_acc = sepa.IBAN(acc_number) |
1117 | + if iban_acc.valid: |
1118 | + bank_id, country_id = get_or_create_bank( |
1119 | + self.pool, cr, uid, iban_acc.BIC_searchkey, |
1120 | + code=iban_acc.BIC_searchkey |
1121 | + ) |
1122 | + return { |
1123 | + 'value': dict( |
1124 | + acc_number_domestic=iban_acc.localized_BBAN, |
1125 | + acc_number=unicode(iban_acc), |
1126 | + country=country_id or False, |
1127 | + bank=bank_id or False, |
1128 | + ) |
1129 | + } |
1130 | + return warning( |
1131 | + _('Invalid IBAN account number!'), |
1132 | + _("The IBAN number doesn't seem to be correct")) |
1133 | + |
1134 | + def online_account_info( |
1135 | + self, cr, uid, country_code, acc_number, context=None): |
1136 | + """ |
1137 | + Overwrite API hook from account_banking |
1138 | + """ |
1139 | + return online.account_info(country_code, acc_number) |
1140 | |
1141 | === renamed file 'account_banking/sepa/online.py' => 'account_banking_iban_lookup/online.py' |
1142 | --- account_banking/sepa/online.py 2014-02-10 20:21:08 +0000 |
1143 | +++ account_banking_iban_lookup/online.py 2014-03-15 16:07:41 +0000 |
1144 | @@ -1,4 +1,4 @@ |
1145 | -# -*- encoding: utf-8 -*- |
1146 | +# -*- coding: utf-8 -*- |
1147 | ############################################################################## |
1148 | # |
1149 | # Copyright (C) 2009 EduSense BV (<http://www.edusense.nl>). |
1150 | @@ -26,7 +26,7 @@ |
1151 | import urllib, urllib2 |
1152 | from BeautifulSoup import BeautifulSoup |
1153 | from openerp.addons.account_banking.sepa import postalcode |
1154 | -from openerp.addons.account_banking.sepa.urlagent import URLAgent, SoupForm |
1155 | +from openerp.addons.account_banking_iban_lookup.urlagent import URLAgent, SoupForm |
1156 | from openerp.addons.account_banking.sepa.iban import IBAN |
1157 | from openerp.addons.account_banking.struct import struct |
1158 | |
1159 | |
1160 | === renamed file 'account_banking/sepa/urlagent.py' => 'account_banking_iban_lookup/urlagent.py' |
1161 | --- account_banking/sepa/urlagent.py 2013-04-15 13:59:50 +0000 |
1162 | +++ account_banking_iban_lookup/urlagent.py 2014-03-15 16:07:41 +0000 |
1163 | @@ -25,7 +25,6 @@ |
1164 | ''' |
1165 | |
1166 | import urllib |
1167 | -from BeautifulSoup import BeautifulSoup |
1168 | |
1169 | __all__ = ['urlsplit', 'urljoin', 'pathbase', 'urlbase', 'SoupForm', |
1170 | 'URLAgent' |
1171 | |
1172 | === added directory 'account_banking_iban_lookup/view' |
1173 | === added file 'account_banking_iban_lookup/view/res_bank.xml' |
1174 | --- account_banking_iban_lookup/view/res_bank.xml 1970-01-01 00:00:00 +0000 |
1175 | +++ account_banking_iban_lookup/view/res_bank.xml 2014-03-15 16:07:41 +0000 |
1176 | @@ -0,0 +1,15 @@ |
1177 | +<?xml version="1.0" encoding="utf-8"?> |
1178 | +<openerp> |
1179 | + <data> |
1180 | + <record id="view_res_bank_account_banking_form_1" model="ir.ui.view"> |
1181 | + <field name="name">Add BIC lookup to bank form</field> |
1182 | + <field name="model">res.bank</field> |
1183 | + <field name="inherit_id" ref="base.view_res_bank_form"/> |
1184 | + <field name="arch" type="xml"> |
1185 | + <field name="bic" position="replace"> |
1186 | + <field name="bic" on_change="onchange_bic(bic, name)"/> |
1187 | + </field> |
1188 | + </field> |
1189 | + </record> |
1190 | + </data> |
1191 | +</openerp> |
1192 | |
1193 | === added file 'account_banking_iban_lookup/view/res_partner_bank.xml' |
1194 | --- account_banking_iban_lookup/view/res_partner_bank.xml 1970-01-01 00:00:00 +0000 |
1195 | +++ account_banking_iban_lookup/view/res_partner_bank.xml 2014-03-15 16:07:41 +0000 |
1196 | @@ -0,0 +1,23 @@ |
1197 | +<?xml version="1.0" encoding="utf-8"?> |
1198 | +<openerp> |
1199 | + <data> |
1200 | + <record id="view_partner_bank_account_banking_form_2" model="ir.ui.view"> |
1201 | + <field name="name">Add autocompletion methods to partner bank form</field> |
1202 | + <field name="model">res.partner.bank</field> |
1203 | + <field name="inherit_id" ref="base.view_partner_bank_form"/> |
1204 | + <field name="priority" eval="24"/> |
1205 | + <field name="arch" type="xml"> |
1206 | + <data> |
1207 | + <field name="acc_number" position="attributes"> |
1208 | + <attribute name="on_change">onchange_acc_number(acc_number, acc_number_domestic, state, partner_id, country_id)</attribute> |
1209 | + </field> |
1210 | + <field name="acc_number_domestic" position="attributes"> |
1211 | + <attribute name="on_change">onchange_domestic(acc_number_domestic, partner_id, country_id)</attribute> |
1212 | + </field> |
1213 | + </data> |
1214 | + </field> |
1215 | + </record> |
1216 | + </data> |
1217 | +</openerp> |
1218 | + |
1219 | + |
1220 | |
1221 | === modified file 'account_banking_nl_clieop/__openerp__.py' |
1222 | --- account_banking_nl_clieop/__openerp__.py 2013-05-28 15:18:26 +0000 |
1223 | +++ account_banking_nl_clieop/__openerp__.py 2014-03-15 16:07:41 +0000 |
1224 | @@ -24,7 +24,10 @@ |
1225 | 'author': 'EduSense BV', |
1226 | 'website': 'http://www.edusense.nl', |
1227 | 'category': 'Account Banking', |
1228 | - 'depends': ['account_banking_payment'], |
1229 | + 'depends': [ |
1230 | + 'account_banking_payment', |
1231 | + 'account_iban_preserve_domestic', |
1232 | + ], |
1233 | 'data': [ |
1234 | 'account_banking_nl_clieop.xml', |
1235 | 'wizard/export_clieop_view.xml', |
1236 | |
1237 | === modified file 'account_banking_nl_multibank/__openerp__.py' |
1238 | --- account_banking_nl_multibank/__openerp__.py 2013-04-15 13:56:18 +0000 |
1239 | +++ account_banking_nl_multibank/__openerp__.py 2014-03-15 16:07:41 +0000 |
1240 | @@ -20,7 +20,7 @@ |
1241 | ############################################################################## |
1242 | |
1243 | { |
1244 | - 'name': 'Account Banking', |
1245 | + 'name': 'Account Banking - NL Multibank import', |
1246 | 'version': '0.62', |
1247 | 'license': 'AGPL-3', |
1248 | 'author': 'EduSense BV', |
1249 | |
1250 | === modified file 'account_banking_payment/model/banking_import_transaction.py' |
1251 | --- account_banking_payment/model/banking_import_transaction.py 2013-06-04 13:44:24 +0000 |
1252 | +++ account_banking_payment/model/banking_import_transaction.py 2014-03-15 16:07:41 +0000 |
1253 | @@ -116,14 +116,26 @@ |
1254 | ''' |
1255 | # TODO: Not sure what side effects are created when payments are done |
1256 | # for credited customer invoices, which will be matched later on too. |
1257 | + |
1258 | + def bank_match(account, partner_bank): |
1259 | + """ |
1260 | + Returns whether a given account number is equivalent to a |
1261 | + partner bank in the database. We simply call the search method, |
1262 | + which checks IBAN, domestic and disregards from spaces in IBANs. |
1263 | + |
1264 | + :param account: string representation of a bank account number |
1265 | + :param partner_bank: browse record of model res.partner.bank |
1266 | + """ |
1267 | + return partner_bank.id in self.pool['res.partner.bank'].search( |
1268 | + cr, uid, [('acc_number', '=', account)]) |
1269 | + |
1270 | digits = dp.get_precision('Account')(cr)[1] |
1271 | candidates = [ |
1272 | - x for x in payment_lines |
1273 | - if x.communication == trans.reference |
1274 | - and round(x.amount, digits) == -round( |
1275 | - trans.statement_line_id.amount, digits) |
1276 | - and trans.remote_account in (x.bank_id.acc_number, |
1277 | - x.bank_id.acc_number_domestic) |
1278 | + line for line in payment_lines |
1279 | + if (line.communication == trans.reference |
1280 | + and round(line.amount, digits) == -round( |
1281 | + trans.statement_line_id.amount, digits) |
1282 | + and bank_match(trans.remote_account, line.bank_id)) |
1283 | ] |
1284 | if len(candidates) == 1: |
1285 | candidate = candidates[0] |
Thanks! this is terrific and will make account_banking easier to use here in Brazil!