Skip to content

Commit 6114eb0

Browse files
authored
Merge pull request OCA#472 from i-vyshnevska/fix-master
[11.0][FIX] refactor code to updates in bank-payment
2 parents 4bb38f1 + 7ddcafc commit 6114eb0

File tree

14 files changed

+370
-221
lines changed

14 files changed

+370
-221
lines changed

l10n_ch_bank/__init__.py

+2-6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
11
# Copyright 2015 Yannick Vaucher (Camptocamp SA)
22
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
33
from . import models
4+
from .hooks import import_csv_data
45

56

67
def post_init(cr, registry):
7-
"""Import CSV data as it is faster than xml and because we can't use
8-
noupdate anymore with csv"""
9-
from openerp.tools import convert_file
10-
filename = 'data/res.bank.csv'
11-
convert_file(cr, 'l10n_ch_bank', filename, None, mode='init',
12-
noupdate=True, kind='init', report=None)
8+
import_csv_data(cr, registry)

l10n_ch_bank/hooks.py

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Copyright 2019 Camptocamp SA
2+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
3+
4+
from odoo.tools import convert_file
5+
6+
7+
def import_csv_data(cr, registry):
8+
"""Import CSV data as it is faster than xml and because we can't use
9+
noupdate anymore with csv"""
10+
filenames = ['data/res.bank.csv']
11+
for filename in filenames:
12+
convert_file(
13+
cr, 'l10n_ch_bank',
14+
filename, None, mode='init', noupdate=True,
15+
kind='init', report=None,
16+
)

l10n_ch_base_bank/models/bank.py

+108-50
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,8 @@ def name_search(self, name, args=None, operator='ilike', limit=80):
152152
ids = self.search(
153153
args,
154154
limit=limit
155-
).ids
156-
# we sort by occurence
155+
).ids
156+
# we sort by occurrence
157157
to_ret_ids = list(set(ids))
158158
to_ret_ids = sorted(
159159
to_ret_ids,
@@ -167,6 +167,31 @@ class ResPartnerBank(models.Model, BankCommon):
167167
"""Inherit res.partner.bank class in order to add swiss specific fields
168168
and state controls
169169
170+
Statements:
171+
acc_type could be of 3 types:
172+
- postal
173+
- iban
174+
- bank
175+
176+
if account has ccp and acc_type = 'postal' we dropped acc_number and
177+
compute it based on ccp, and partner
178+
179+
if acc_number given in 'iban' format just transform to iban format, but no
180+
further modification on it, and acc_type = 'iban'
181+
182+
if given bank is a postal (acc_type = 'postal') and ccp != bank.ccp it's
183+
mean that ccp in account is ccp of this partner in it's could be different
184+
acc_number in this case recomputed by as partner_name + ccp
185+
186+
if given bank is a bank (acc_type = 'bank') then ccp in account should be
187+
the same as bank.ccp and acc_number recomputed
188+
189+
if given ccp and no bank_id:
190+
- check if we already have banks with the same ccp in db, if found set
191+
this bank to account, update the rest
192+
- if no matches this mean this is a postal type, it has no bank, we
193+
set acc_number to this ccp number
194+
170195
"""
171196
_inherit = 'res.partner.bank'
172197
_compile_check_isr_add_num = re.compile('[0-9]*$')
@@ -177,7 +202,7 @@ class ResPartnerBank(models.Model, BankCommon):
177202
help="Your Bank adherent number to be printed "
178203
"in references of your ISR. "
179204
"This is not a postal account number."
180-
)
205+
)
181206
acc_number = fields.Char(
182207
string='Account/IBAN Number'
183208
)
@@ -186,6 +211,11 @@ class ResPartnerBank(models.Model, BankCommon):
186211
store=True
187212
)
188213

214+
_sql_constraints = [
215+
('isr_adherent_uniq', 'unique (isr_adherent_num, ccp)',
216+
'The ISR adherent number/ccp pair must be unique !'),
217+
]
218+
189219
@api.depends('acc_number')
190220
def _compute_acc_type(self):
191221
todo = self.env['res.partner.bank']
@@ -236,34 +266,53 @@ def _check_postal_num(self):
236266
return True
237267

238268
@api.multi
239-
def _get_acc_name(self):
240-
""" Return an account name for a bank account
241-
to use with a ccp for ISR.
242-
This method makes sure to generate a unique name
243-
"""
244-
269+
def _update_acc_name(self):
270+
"""Check if number generated from ccp, if yes replace it on new """
245271
part_name = self.partner_id.name
246272
if not part_name and self.env.context.get('default_partner_id'):
247273
partner_id = self.env.context.get('default_partner_id')
248274
part_name = self.env['res.partner'].browse(partner_id)[0].name
275+
self.acc_number = self._compute_name_ccp(part_name, self.ccp)
249276

250-
if part_name:
251-
acc_name = _("Bank/CCP {}").format(part_name)
277+
@api.multi
278+
def _compute_name_ccp(self, partner_name, ccp):
279+
"""This method makes sure to generate a unique name"""
280+
if partner_name and ccp:
281+
acc_name = _("{}/CCP {}").format(partner_name, ccp)
282+
elif ccp:
283+
acc_name = _("CCP {}").format(ccp)
252284
else:
253-
acc_name = _("Bank/CCP Undefined")
285+
return ''
254286

255287
exist_count = self.env['res.partner.bank'].search_count(
256288
[('acc_number', '=like', acc_name)])
289+
# if acc_number not unique iterate on bank_accounts while not get
290+
# unique number
257291
if exist_count:
258292
name_exist = exist_count
259293
while name_exist:
260-
new_name = acc_name + " ({})".format(exist_count)
294+
new_name = acc_name + " #{}".format(exist_count)
261295
name_exist = self.env['res.partner.bank'].search_count(
262296
[('acc_number', '=', new_name)])
263297
exist_count += 1
264298
acc_name = new_name
265299
return acc_name
266300

301+
@api.model
302+
def create(self, vals):
303+
"""
304+
acc_number is mandatory for model, but in localization it could be not
305+
mandatory when we have ccp number, so we compute acc_number in onchange
306+
methods and check it here also
307+
"""
308+
if not vals.get('acc_number') and vals.get('ccp'):
309+
partner = self.env['res.partner'].browse(vals.get('partner_id'))
310+
vals['acc_number'] = self._compute_name_ccp(
311+
partner.name,
312+
vals['ccp']
313+
)
314+
return super().create(vals)
315+
267316
@api.multi
268317
def _get_ch_bank_from_iban(self):
269318
""" Extract clearing number from iban to find the bank """
@@ -273,7 +322,7 @@ def _get_ch_bank_from_iban(self):
273322
return clearing and self.env['res.bank'].search(
274323
[('clearing', '=', clearing)], limit=1)
275324

276-
@api.onchange('acc_number', 'acc_type')
325+
@api.onchange('acc_number')
277326
def onchange_acc_number_set_swiss_bank(self):
278327
""" Set the bank when possible
279328
and set ccp when undefined
@@ -287,6 +336,10 @@ def onchange_acc_number_set_swiss_bank(self):
287336
- a bank account with CCP on the bank, we use ccp of the bank
288337
- otherwise there is no CCP to use
289338
"""
339+
if not self.acc_number:
340+
# if account number was flashed in UI
341+
self._update_acc_name()
342+
290343
bank = self.bank_id
291344
ccp = False
292345
if self.acc_type == 'postal':
@@ -298,8 +351,6 @@ def onchange_acc_number_set_swiss_bank(self):
298351
bank or
299352
self.env['res.bank'].search([('bic', '=', 'POFICHBEXXX')],
300353
limit=1))
301-
if not bank.is_swiss_post():
302-
self.acc_number = self._get_acc_name()
303354
elif self.acc_type == 'iban':
304355
if not bank:
305356
bank = self._get_ch_bank_from_iban()
@@ -308,58 +359,65 @@ def onchange_acc_number_set_swiss_bank(self):
308359
ccp = self._convert_iban_to_ccp(self.acc_number.strip())
309360
else:
310361
ccp = bank.ccp
362+
311363
elif self.bank_id.ccp:
312364
ccp = self.bank_id.ccp
313365
self.bank_id = bank
366+
314367
if not self.ccp:
315368
self.ccp = ccp
316369

317370
@api.onchange('ccp')
318-
def onchange_ccp_set_empty_acc_number(self):
319-
""" If acc_number is empty and bank ccp is defined fill it """
320-
if self.bank_id:
321-
if not self.acc_number and self.ccp:
322-
if self.bank_id.is_swiss_post():
323-
self.acc_number = self.ccp
324-
else:
325-
self.acc_number = self._get_acc_name()
371+
def onchange_ccp_set_acc_number(self):
372+
"""If ccp changes and it's a postal bank update acc_number to ccp
373+
we don't want make acc_number as computed to have possibility set it
374+
manually and also avoid to shadow other logic on acc_number if exist
375+
"""
376+
if self.acc_type == 'iban':
377+
return
378+
379+
if self.ccp:
380+
if self.acc_type == 'postal':
381+
# flash bank if it was previously setup, also trigger acc_type
382+
# changing
383+
self.bank_id = ''
384+
self._update_acc_name()
385+
else:
386+
# flash bank if it was previously setup
387+
self.acc_number = ''
388+
389+
if self.bank_id.is_swiss_post():
390+
self.acc_number = self.ccp
326391
return
327392

393+
# try to find appropriate bank
328394
ccp = self.ccp
329-
if ccp and self.is_swiss_postal_num(ccp):
330-
bank = (
331-
self.env['res.bank'].search([('ccp', '=', ccp)], limit=1) or
332-
self.env['res.bank'].search([('bic', '=', 'POFICHBEXXX')],
333-
limit=1))
334-
if not self.acc_number:
335-
if not bank.is_swiss_post():
336-
self.acc_number = self._get_acc_name()
337-
else:
338-
self.acc_number = self.ccp
395+
if ccp and self.is_swiss_postal_num(ccp) and not self.bank_id.id:
396+
bank = (self.env['res.bank'].search([('ccp', '=', ccp)], limit=1)
397+
or
398+
self.env['res.bank'].search([('bic', '=', 'POFICHBEXXX')],
399+
limit=1))
400+
if not bank.is_swiss_post():
401+
self._update_acc_name()
402+
else:
403+
self.acc_number = self.ccp
339404
self.bank_id = bank
340405

341406
@api.onchange('bank_id')
342407
def onchange_bank_set_acc_number(self):
343-
""" If acc_number is empty and bank ccp is defined fill it """
344-
if not self.bank_id:
408+
""" Track bank change to update acc_name if needed"""
409+
if not self.bank_id or self.acc_type == 'iban':
345410
return
346411
if self.bank_id.is_swiss_post():
347-
if not self.acc_number:
348-
self.acc_number = self.ccp
349-
elif not self.ccp and self.is_swiss_postal_num(self.acc_number):
350-
self.ccp = self.acc_number
412+
self.acc_number = self.ccp
351413
else:
352-
if not self.acc_number and self.ccp:
353-
self.acc_number = self._get_acc_name()
354-
elif self.acc_number and self.is_swiss_postal_num(self.acc_number):
355-
self.ccp = self.acc_number
356-
self.acc_number = self._get_acc_name()
414+
self._update_acc_name()
357415

358416
@api.onchange('partner_id')
359417
def onchange_partner_set_acc_number(self):
418+
"""
419+
when acc_number was computed automatically we call regeneration
420+
as partner name is part of acc_number
421+
"""
360422
if self.acc_type == 'bank' and self.ccp:
361-
if 'Bank/CCP' in self.acc_number:
362-
self.acc_number = self._get_acc_name()
363-
364-
_sql_constraints = [('isr_adherent_uniq', 'unique (isr_adherent_num, ccp)',
365-
'The ISR adherent number/ccp pair must be unique !')]
423+
self._update_acc_name()

l10n_ch_base_bank/models/invoice.py

+29-4
Original file line numberDiff line numberDiff line change
@@ -121,15 +121,40 @@ def _check_isr(self):
121121
invoice._is_isr_reference()
122122
return True
123123

124+
def write(self, vals):
125+
"""Override to update partner_bank_id before constraints if needed and
126+
to be consistent with create
127+
"""
128+
if not self.partner_bank_id or not vals.get('partner_bank_id'):
129+
type_defined = vals.get('type') or self.type
130+
if type_defined == 'out_invoice':
131+
banks = self.partner_banks_to_show()
132+
if banks:
133+
vals['partner_bank_id'] = banks[0].id
134+
return super().write(vals)
135+
124136
@api.model
125137
def create(self, vals):
126138
"""We override create in order to have customer invoices
127139
generated by the comercial flow as on change partner is
128140
not systemtically call"""
129141
type_defined = vals.get('type') or self.env.context.get('type', False)
130142
if type_defined == 'out_invoice' and not vals.get('partner_bank_id'):
131-
user = self.env.user
132-
bank_ids = user.company_id.partner_id.bank_ids
133-
if bank_ids:
134-
vals['partner_bank_id'] = bank_ids[0].id
143+
partner = self.env.user.company_id.partner_id
144+
vals['partner_bank_id'] = self._get_bank_id(
145+
partner, vals.get('journal_id'), vals.get('reference_type'),
146+
)
135147
return super(AccountInvoice, self).create(vals)
148+
149+
def _get_bank_id(self, partner, journal_id, ref_type):
150+
if journal_id:
151+
return self.env['account.journal'].browse(journal_id). \
152+
bank_account_id.id
153+
if ref_type == 'isr':
154+
bank_ids = partner.bank_ids.filtered(
155+
lambda s: s.acc_type == 'postal'
156+
)
157+
else:
158+
bank_ids = partner.bank_ids
159+
if bank_ids:
160+
return bank_ids[0].id

0 commit comments

Comments
 (0)