l10n-switzerland-flectra/l10n_ch_qr_bill/models/res_bank.py

74 lines
2.7 KiB
Python
Raw Normal View History

# Copyright 2019-TODAY Flectra
# Copyright 2019-TODAY Camptocamp SA
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
import re
from flectra import api, fields, models, _
from flectra.addons.base_iban.models.res_partner_bank import (
normalize_iban, pretty_iban, validate_iban
)
from flectra.addons.base.models.res_bank import sanitize_account_number
from flectra.exceptions import ValidationError
class ResPartnerBank(models.Model):
_inherit = 'res.partner.bank'
l10n_ch_qr_iban = fields.Char(
string='QR-IBAN',
help=(
"Put the QR-IBAN here for your own bank accounts. That way, you"
" can still use the main IBAN in the Account Number while you will"
" see the QR-IBAN for the barcode."
)
)
def _check_qr_iban_range(self, iban):
if not iban or len(iban) < 9:
return False
iid_start_index = 4
iid_end_index = 8
iid = iban[iid_start_index : iid_end_index + 1]
# Those iid between 30000 and 31999 are reserved for QR-IBANs only
return (re.match(r'\d+', iid)
and 30000 <= int(iid) <= 31999)
def _validate_qr_iban(self, qr_iban):
# Check first if it's a valid IBAN.
validate_iban(qr_iban)
# We sanitize first so that _check_qr_iban_range()
# can extract correct IID from IBAN to validate it.
sanitized_qr_iban = sanitize_account_number(qr_iban)
# Now, check if it's valid QR-IBAN (based on its IID).
if not self._check_qr_iban_range(sanitized_qr_iban):
raise ValidationError(_("QR-IBAN '%s' is invalid.") % qr_iban)
return True
@api.model
def create(self, vals):
if vals.get('l10n_ch_qr_iban'):
self._validate_qr_iban(vals['l10n_ch_qr_iban'])
iban = pretty_iban(normalize_iban(vals['l10n_ch_qr_iban']))
vals['l10n_ch_qr_iban'] = iban
return super(ResPartnerBank, self).create(vals)
def write(self, vals):
if vals.get('l10n_ch_qr_iban'):
self._validate_qr_iban(vals['l10n_ch_qr_iban'])
iban = pretty_iban(normalize_iban(vals['l10n_ch_qr_iban']))
vals['l10n_ch_qr_iban'] = iban
return super(ResPartnerBank, self).write(vals)
def _is_qr_iban(self):
""" Tells whether or not this bank account has a QR-IBAN account number.
QR-IBANs are specific identifiers used in Switzerland as references in
QR-codes. They are formed like regular IBANs, but are actually something
different.
"""
return (
self.acc_type == "iban"
and self._check_qr_iban_range(self.sanitized_acc_number)
or self.l10n_ch_qr_iban
)