res_partner.py 3.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. # -*- coding: utf-8 -*-
  2. # Part of Odoo. See LICENSE file for full copyright and licensing details.
  3. from odoo import _, api, fields, models
  4. from odoo.exceptions import ValidationError
  5. import re
  6. class ResPartner(models.Model):
  7. _inherit = 'res.partner'
  8. l10n_br_cpf_code = fields.Char(string="CPF", help="Natural Persons Register.")
  9. l10n_br_ie_code = fields.Char(string="IE", help="State Tax Identification Number. Should contain 9-14 digits.")
  10. l10n_br_im_code = fields.Char(string="IM", help="Municipal Tax Identification Number")
  11. l10n_br_isuf_code = fields.Char(string="SUFRAMA code", help="SUFRAMA registration number.")
  12. @api.constrains("vat")
  13. def check_vat(self):
  14. '''
  15. Example of a Brazilian CNPJ number: 76.634.583/0001-74.
  16. The 13th digit is the check digit of the previous 12 digits.
  17. The check digit is calculated by multiplying the first 12 digits by weights and calculate modulo 11 of the result.
  18. The 14th digit is the check digit of the previous 13 digits. Calculated the same way.
  19. Both remainders are appended to the first 12 digits.
  20. '''
  21. def _l10n_br_calculate_mod_11(check, weights):
  22. result = (sum([i*j for (i, j) in zip(check, weights)])) % 11
  23. if result <= 1:
  24. return 0
  25. return 11 - result
  26. def _l10n_br_is_valid_cnpj(vat_clean):
  27. weights = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]
  28. vat_check = vat_clean[:12]
  29. vat_check.append(_l10n_br_calculate_mod_11(vat_check, weights[1:]))
  30. vat_check.append(_l10n_br_calculate_mod_11(vat_check, weights))
  31. return vat_check == vat_clean
  32. def _l10n_br_is_valid_cpf(vat_clean): #http://www.receita.fazenda.gov.br/aplicacoes/atcta/cpf/funcoes.js
  33. total_sum = 0
  34. # If the CPF list contains all zeros, it's not valid
  35. if vat_clean == [0] * 11:
  36. return False
  37. # Calculate the sum for the first verification digit
  38. for i in range(1, 10):
  39. total_sum = total_sum + vat_clean[i - 1] * (11 - i)
  40. remainder = (total_sum * 10) % 11
  41. # If the remainder is 10 or 11, set it to 0
  42. if remainder in (10, 11):
  43. remainder = 0
  44. # Check the first verification digit
  45. if remainder != vat_clean[9]:
  46. return False
  47. total_sum = 0
  48. # Calculate the sum for the second verification digit
  49. for i in range(1, 11):
  50. total_sum = total_sum + vat_clean[i - 1] * (12 - i)
  51. remainder = (total_sum * 10) % 11
  52. # If the remainder is 10 or 11, set it to 0
  53. if remainder in (10, 11):
  54. remainder = 0
  55. # Check the second verification digit
  56. if remainder != vat_clean[10]:
  57. return False
  58. return True
  59. for partner in self:
  60. if not partner.vat:
  61. return
  62. if not partner.country_code == 'BR':
  63. return super().check_vat()
  64. vat_clean = list(map(int, re.sub("[^0-9]", "", partner.vat)))
  65. if len(vat_clean) == 14:
  66. if not _l10n_br_is_valid_cnpj(vat_clean):
  67. raise ValidationError(_("Invalid CNPJ. Make sure that all the digits are entered correctly."))
  68. elif len(vat_clean) == 11:
  69. if not _l10n_br_is_valid_cpf(vat_clean):
  70. raise ValidationError(_("Invalid CPF. Make sure that all the digits are entered correctly."))
  71. else:
  72. raise ValidationError(_("Invalid CNPJ/CPF. Make sure that the CNPJ is a 14 digits number or CPF is a 11 digits number."))