Odoo18-Base/addons/l10n_ch/models/account_invoice.py
2025-01-06 10:57:38 +07:00

105 lines
4.2 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import re
from odoo import models, fields, api, _
from odoo.exceptions import UserError
from odoo.tools.misc import mod10r
L10N_CH_QRR_NUMBER_LENGTH = 27
class AccountMove(models.Model):
_inherit = 'account.move'
l10n_ch_is_qr_valid = fields.Boolean(compute='_compute_l10n_ch_qr_is_valid', help="Determines whether an invoice can be printed as a QR or not")
@api.depends('partner_id', 'currency_id')
def _compute_l10n_ch_qr_is_valid(self):
for move in self:
error_messages = move.partner_bank_id._get_error_messages_for_qr('ch_qr', move.partner_id, move.currency_id)
move.l10n_ch_is_qr_valid = move.move_type == 'out_invoice' and not error_messages
def get_l10n_ch_qrr_number(self):
"""Generates the QRR reference.
QRR references are 27 characters long.
The invoice sequence number is used, removing each of its non-digit characters,
and pad the unused spaces on the left of this number with zeros.
The last digit is a checksum (mod10r).
"""
self.ensure_one()
if self.partner_bank_id.l10n_ch_qr_iban and self.l10n_ch_is_qr_valid and self.name:
invoice_ref = re.sub(r'[^\d]', '', self.name)
return self._compute_qrr_number(invoice_ref)
else:
return False
@api.model
def _compute_qrr_number(self, invoice_ref):
# keep only the last digits if it exceed boundaries
ref_payload_len = L10N_CH_QRR_NUMBER_LENGTH - 1
extra = len(invoice_ref) - ref_payload_len
if extra > 0:
invoice_ref = invoice_ref[extra:]
internal_ref = invoice_ref.zfill(ref_payload_len)
return mod10r(internal_ref)
def _get_invoice_reference_ch_invoice(self):
""" This sets QRR reference number which is generated based on customer's `Bank Account` and set it as
`Payment Reference` of the invoice when invoice's journal is using Switzerland's communication standard
"""
self.ensure_one()
return self.get_l10n_ch_qrr_number()
def _get_invoice_reference_ch_partner(self):
""" This sets QRR reference number which is generated based on customer's `Bank Account` and set it as
`Payment Reference` of the invoice when invoice's journal is using Switzerland's communication standard
"""
self.ensure_one()
return self.get_l10n_ch_qrr_number()
@api.model
def space_qrr_reference(self, qrr_ref):
""" Makes the provided QRR reference human-friendly, spacing its elements
by blocks of 5 from right to left.
"""
spaced_qrr_ref = ''
i = len(qrr_ref) # i is the index after the last index to consider in substrings
while i > 0:
spaced_qrr_ref = qrr_ref[max(i-5, 0) : i] + ' ' + spaced_qrr_ref
i -= 5
return spaced_qrr_ref
@api.model
def space_scor_reference(self, iso11649_ref):
""" Makes the provided SCOR reference human-friendly, spacing its elements
by blocks of 5 from right to left.
"""
return ' '.join(iso11649_ref[i:i + 4] for i in range(0, len(iso11649_ref), 4))
def l10n_ch_action_print_qr(self):
'''
Checks that all invoices can be printed in the QR format.
If so, launches the printing action.
Else, triggers the l10n_ch wizard that will display the informations.
'''
if any(x.move_type != 'out_invoice' for x in self):
raise UserError(_("Only customers invoices can be QR-printed."))
if False in self.mapped('l10n_ch_is_qr_valid'):
return {
'name': (_("Some invoices could not be printed in the QR format")),
'type': 'ir.actions.act_window',
'res_model': 'l10n_ch.qr_invoice.wizard',
'view_mode': 'form',
'target': 'new',
'context': {'active_ids': self.ids},
}
return self.env.ref('account.account_invoices').report_action(self)
def _l10n_ch_dispatch_invoices_to_print(self):
qr_invs = self.filtered('l10n_ch_is_qr_valid')
return {
'qr': qr_invs,
'classic': self - qr_invs,
}