res_partner.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. # Part of Odoo. See LICENSE file for full copyright and licensing details.
  2. import enum
  3. import stdnum
  4. from odoo import _, api, fields, models
  5. from odoo.exceptions import ValidationError
  6. def verify_final_consumer(vat):
  7. return vat == '9' * 13 # final consumer is identified with 9999999999999
  8. class PartnerIdTypeEc(enum.Enum):
  9. """
  10. Ecuadorian partner identification type/code for ATS and SRI.
  11. """
  12. IN_RUC = '01'
  13. IN_CEDULA = '02'
  14. IN_PASSPORT = '03'
  15. OUT_RUC = '04'
  16. OUT_CEDULA = '05'
  17. OUT_PASSPORT = '06'
  18. FINAL_CONSUMER = '07'
  19. FOREIGN = '08'
  20. @classmethod
  21. def get_ats_code_for_partner(cls, partner, move_type):
  22. """
  23. Returns ID code for move and partner based on subset of Table 2 of SRI's ATS specification
  24. """
  25. partner_id_type = partner._l10n_ec_get_identification_type()
  26. if move_type.startswith('in_'):
  27. if partner_id_type == 'ruc': # includes final consumer
  28. return cls.IN_RUC
  29. elif partner_id_type == 'cedula':
  30. return cls.IN_CEDULA
  31. elif partner_id_type in ['foreign', 'passport']:
  32. return cls.IN_PASSPORT
  33. elif move_type.startswith('out_'):
  34. if partner_id_type == 'ruc': # includes final consumer
  35. return cls.OUT_RUC
  36. elif partner_id_type == 'cedula':
  37. return cls.OUT_CEDULA
  38. elif partner_id_type in ['foreign', 'passport']:
  39. return cls.OUT_PASSPORT
  40. class ResPartner(models.Model):
  41. _inherit = "res.partner"
  42. l10n_ec_vat_validation = fields.Char(
  43. string="VAT Error message validation",
  44. compute="_compute_l10n_ec_vat_validation",
  45. help="Error message when validating the Ecuadorian VAT",
  46. )
  47. @api.constrains("vat", "country_id", "l10n_latam_identification_type_id")
  48. def check_vat(self):
  49. it_ruc = self.env.ref("l10n_ec.ec_ruc", False)
  50. it_dni = self.env.ref("l10n_ec.ec_dni", False)
  51. ecuadorian_partners = self.filtered(
  52. lambda x: x.country_id == self.env.ref("base.ec")
  53. )
  54. for partner in ecuadorian_partners:
  55. if partner.vat:
  56. if partner.l10n_latam_identification_type_id.id in (
  57. it_ruc.id,
  58. it_dni.id,
  59. ):
  60. if partner.l10n_latam_identification_type_id.id == it_dni.id and len(partner.vat) != 10:
  61. raise ValidationError(_('If your identification type is %s, it must be 10 digits')
  62. % it_dni.display_name)
  63. if partner.l10n_latam_identification_type_id.id == it_ruc.id and len(partner.vat) != 13:
  64. raise ValidationError(_('If your identification type is %s, it must be 13 digits')
  65. % it_ruc.display_name)
  66. return super(ResPartner, self - ecuadorian_partners).check_vat()
  67. @api.depends("vat", "country_id", "l10n_latam_identification_type_id")
  68. def _compute_l10n_ec_vat_validation(self):
  69. it_ruc = self.env.ref("l10n_ec.ec_ruc", False)
  70. it_dni = self.env.ref("l10n_ec.ec_dni", False)
  71. ruc = stdnum.util.get_cc_module("ec", "ruc")
  72. ci = stdnum.util.get_cc_module("ec", "ci")
  73. for partner in self:
  74. partner.l10n_ec_vat_validation = False
  75. if partner and partner.l10n_latam_identification_type_id in (it_ruc, it_dni) and partner.vat:
  76. final_consumer = verify_final_consumer(partner.vat)
  77. if not final_consumer:
  78. if partner.l10n_latam_identification_type_id.id == it_dni.id and not ci.is_valid(partner.vat):
  79. partner.l10n_ec_vat_validation = _("The VAT %s seems to be invalid as the tenth digit doesn't comply with the validation algorithm "
  80. "(could be an old VAT number)") % partner.vat
  81. if partner.l10n_latam_identification_type_id.id == it_ruc.id and not ruc.is_valid(partner.vat):
  82. partner.l10n_ec_vat_validation = _("The VAT %s seems to be invalid as the tenth digit doesn't comply with the validation algorithm "
  83. "(SRI has stated that this validation is not required anymore for some VAT numbers)") % partner.vat
  84. def _l10n_ec_get_identification_type(self):
  85. """Maps Odoo identification types to Ecuadorian ones.
  86. Useful for document type domains, electronic documents, ats, others.
  87. """
  88. self.ensure_one()
  89. def id_type_in(*args):
  90. return any([self.l10n_latam_identification_type_id == self.env.ref(arg) for arg in args])
  91. if id_type_in('l10n_ec.ec_dni'):
  92. return 'cedula' # DNI
  93. elif id_type_in('l10n_ec.ec_ruc'):
  94. return 'ruc' # RUC
  95. elif id_type_in('l10n_latam_base.it_pass'):
  96. return 'passport' # Pasaporte
  97. elif id_type_in('l10n_latam_base.it_fid', 'l10n_latam_base.it_vat') \
  98. or self.l10n_latam_identification_type_id.country_id != self.env.ref('base.ec'):
  99. return 'foreign' # Identificacion del exterior