From d93365c684593bdf788e8a5d6962f1b51d415d0e Mon Sep 17 00:00:00 2001 From: Christopher Ormaza Date: Thu, 2 Sep 2021 14:36:01 +0000 Subject: [PATCH] [IMP] base_vat: CI and Ruc Validation for Ecuadorian Context - Added own implementation, for CI and RUC Validation Part-of: odoo/odoo#75055 --- addons/base_vat/models/res_partner.py | 61 +++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/addons/base_vat/models/res_partner.py b/addons/base_vat/models/res_partner.py index c6dc7d5cd19..24e6d0759c7 100644 --- a/addons/base_vat/models/res_partner.py +++ b/addons/base_vat/models/res_partner.py @@ -7,6 +7,8 @@ import re import stdnum from stdnum.eu.vat import check_vies from stdnum.exceptions import InvalidComponent +from stdnum.util import clean + import logging from odoo import api, models, tools, _ @@ -258,6 +260,65 @@ class ResPartner(models.Model): return check == int(num[8]) return False + def _checksum_ci_ec(self, number): + """Calculate a checksum over the number.""" + fold = lambda x: x - 9 if x > 9 else x + return sum(fold((2, 1)[i % 2] * int(n)) + for i, n in enumerate(number)) % 10 + + def _checksum_ruc_ec(self, number, weights): + """Calculate a checksum over the number given the weights.""" + return sum(w * int(n) for w, n in zip(weights, number)) % 11 + + def is_valid_ci_ec(self, vat): + """Check if the number provided is a valid CI number. This checks the + length, formatting and check digit.""" + if len(vat) != 10: + return False + if not vat.isdecimal(): + return False + if (vat[:2] < '01' or vat[:2] > '24') and (vat[:2] not in ('30', '50')): + return False + if vat[2] > '6': + return False + if self._checksum_ci_ec(vat) != 0: + return False + return True + + def is_valid_ruc_ec(self, vat): + """Check if the number provided is a valid RUC number. This checks the + length, formatting, check digit and check sum.""" + if len(vat) != 13: + return False + if not vat.isdecimal(): + return False + if (vat[:2] < '01' or vat[:2] > '24') and (vat[:2] not in ('30', '50')): + return False + if vat[2] <= '5': + # 0..5 = natural RUC: CI plus establishment number + if vat[-3:] == '000': + return False + return self.is_valid_ci_ec(vat[:10]) + elif vat[2] == '6': + # 6 = public RUC + #if vat[-4:] == '0000': + # return False + if self._checksum_ruc_ec(vat[:9], (3, 2, 7, 6, 5, 4, 3, 2, 1)) != 0: + return False + elif vat[2] == '9': + # 9 = juridical RUC + if vat[-3:] == '000': + return False + if self._checksum_ruc_ec(vat[:10], (4, 3, 2, 7, 6, 5, 4, 3, 2, 1)) != 0: + return False + else: + return False + return True + + def check_vat_ec(self, vat): + vat = clean(vat, ' -.').upper().strip() + return self.is_valid_ruc_ec(vat) + def _ie_check_char(self, vat): vat = vat.zfill(8) extra = 0