Files
enterprise-addons/l10n_nl_reports/wizard/vat_pay_wizard.py
T

78 lines
3.1 KiB
Python

from stdnum.nl.btw import validate
from odoo import models, _
from odoo.exceptions import UserError
class VATPayWizard(models.TransientModel):
_name = 'l10n_nl_reports.vat.pay.wizard'
_inherit = ['qr.code.payment.wizard']
_description = "Payment instructions for VAT"
def _generate_communication(self):
company = self.return_id.company_id
periodicity = self.return_id.type_id._get_periodicity(company)
try:
nl_vat = company.l10n_nl_reports_sbr_ob_nummer or company.vat
vat = validate(nl_vat)
except Exception as e:
raise UserError(_(
"Something went wrong while validating the VAT number: %s. You can modify it in the company settings.",
nl_vat
)) from e
head, tail = vat.split("B")
date = self.return_id.date_from
period_code_map = {
'monthly': f'{date.month:02}',
'trimester': f'{20 + date.month}',
'year': '40',
}
if periodicity not in period_code_map:
raise UserError(_(
"Invalid tax periodicity. Please use one of the following: %s.",
', '.join(
label
for value, label in self.return_id.type_id._fields['deadline_periodicity']._description_selection(self.env)
if value in period_code_map
)
))
block_1 = f"{head[:3]}"
block_2 = f"{head[3:7]}"
block_3 = f"{head[7:8]}1{str(date.year)[-1]}{tail[0]}"
block_4 = f"{tail[1]}{period_code_map[periodicity]}0"
blocks = [block_1, block_2, block_3, block_4]
checksum = self._l10n_nl_get_modulo_11_checksum("".join(blocks))
return checksum + ".".join(blocks)
def _l10n_nl_get_modulo_11_checksum(self, number):
"""
Calculates the Modulo 11 checksum for a given numeric string using a predefined set of weights.
The function iterates over each digit in the input string from right to left, applying the corresponding weight
in a cyclic manner. The checksum is computed as the weighted sum of the digits modulo 11.
Source: https://www.betaalvereniging.nl/betalingsverkeer/giraal-betalingsverkeer/betalingskenmerken/specificaties-nl-betalingskenmerk/
:param str number: A string representing a numeric input for which the checksum needs to be calculated.
:returns: The Modulo 11 checksum as a string.
Returns '0' or '1' if the remainder is 0 or 1,
otherwise returns the complement of the remainder (i.e., 11 - remainder).
:rtype: str.
"""
n = len(number)
weights = [2, 4, 8, 5, 10, 9, 7, 3, 6, 1]
remainder = sum(int(number[n - i - 1]) * weights[i % len(weights)] for i in range(n)) % 11
if remainder in (0, 1):
return str(remainder)
return str(11 - remainder)
def action_send_email_instructions(self):
self.ensure_one()
template = self.env.ref('l10n_nl_reports.email_template_vat_payment_instructions', raise_if_not_found=False)
return self.return_id.action_send_email_instructions(self, template)