from odoo import api, models, _ class ResPartnerBank(models.Model): _inherit = 'res.partner.bank' @api.model def _get_available_qr_methods(self): rslt = super()._get_available_qr_methods() # Nižšia sequence ako natívny EPC/SCT QR (sequence 20 v # account_qr_code_sepa) - SPAYD sa uprednostní, keď je eligible. rslt.append(('spayd', _("SPAYD (Czech QR Platba)"), 6)) return rslt def _get_error_messages_for_qr(self, qr_method, debtor_partner, currency): if qr_method == 'spayd': if currency.name not in ('CZK', 'EUR'): return _("SPAYD podporuje len menu CZK alebo EUR.") if not self._spayd_to_iban(): return _("Bankový účet nemá platné číslo účtu ani IBAN pre SPAYD.") if debtor_partner and debtor_partner.country_id and debtor_partner.country_id.code != 'CZ': return _("SPAYD je určený pre zákazníkov z Českej republiky.") return None return super()._get_error_messages_for_qr(qr_method, debtor_partner, currency) def _check_for_qr_code_errors(self, qr_method, amount, currency, debtor_partner, free_communication, structured_communication): if qr_method == 'spayd': return None return super()._check_for_qr_code_errors(qr_method, amount, currency, debtor_partner, free_communication, structured_communication) def _get_qr_code_generation_params(self, qr_method, amount, currency, debtor_partner, free_communication, structured_communication): if qr_method == 'spayd': iban = self._spayd_to_iban() vs_source = structured_communication or free_communication or '' vs = ''.join(filter(str.isdigit, vs_source))[-10:] spayd = f"SPD*1.0*ACC:{iban}*AM:{amount:.2f}*CC:{currency.name}*X-VS:{vs}" return { 'barcode_type': 'QR', 'quiet': 0, 'width': 128, 'height': 128, 'humanreadable': 0, 'value': spayd, } return super()._get_qr_code_generation_params(qr_method, amount, currency, debtor_partner, free_communication, structured_communication) def _spayd_to_iban(self): """Vráti IBAN pre tento bankový účet, vhodný pre SPAYD QR (ACC pole). Podporuje český lokálny formát ('123-456/0800' alebo '456/0800') aj priamo zadaný IBAN (akejkoľvek krajiny). """ self.ensure_one() acc_number = self.acc_number if not acc_number: return '' clean_acc = acc_number.replace(' ', '').upper() # Už IBAN (ľubovoľná krajina): 2 písmená + 2-číslicový kontrolný súčet. if len(clean_acc) >= 4 and clean_acc[:2].isalpha() and clean_acc[2:4].isdigit(): return clean_acc try: parts = clean_acc.split('/') if len(parts) != 2: return clean_acc # nie je český formát ani IBAN - vrátime pôvodné bank_code = parts[1].zfill(4) account_parts = parts[0].split('-') if len(account_parts) == 2: prefix = account_parts[0].zfill(6) main = account_parts[1].zfill(10) else: prefix = '000000' main = account_parts[0].zfill(10) # ISO 7064 mod 97-10: BBAN + krajina ako čísla (C=12, Z=35) + '00'. check_string = f"{bank_code}{prefix}{main}123500" checksum = 98 - (int(check_string) % 97) return f"CZ{str(checksum).zfill(2)}{bank_code}{prefix}{main}" except (ValueError, IndexError): return clean_acc