From aa909bbffcfdb5bc7f9d614911db5ceeefd15cff Mon Sep 17 00:00:00 2001 From: Alnus Tmp Date: Fri, 20 Nov 2020 17:27:29 -0500 Subject: [PATCH] RUT in Identifier and message/exceptions --- __init__.py | 1 + exceptions.py | 9 ++++ locale/es.po | 23 +++++++++++ message.xml | 19 +++++++++ party.py | 111 ++++++++++++++++++++++++++++++++++---------------- tryton.cfg | 1 + 6 files changed, 129 insertions(+), 35 deletions(-) create mode 100644 exceptions.py create mode 100644 message.xml diff --git a/__init__.py b/__init__.py index 6dca2d6..9a663d3 100644 --- a/__init__.py +++ b/__init__.py @@ -2,6 +2,7 @@ from trytond.pool import Pool from . import party from . import country from . import rut + __all__ = ['register'] diff --git a/exceptions.py b/exceptions.py new file mode 100644 index 0000000..8634065 --- /dev/null +++ b/exceptions.py @@ -0,0 +1,9 @@ +# This file is part of Tryton. The COPYRIGHT file at the top level of +# this repository contains the full copyright notices and license terms. + +from trytond.exceptions import UserError +from trytond.model.exceptions import ValidationError + + +class PartyIdentifierError(ValidationError): + pass diff --git a/locale/es.po b/locale/es.po index c6ea79d..9f703c7 100644 --- a/locale/es.po +++ b/locale/es.po @@ -54,3 +54,26 @@ msgctxt "view:party.party:" msgid "Economic Activity" msgstr "Actividad Económica" +msgctxt "model:ir.message,text:msg_invalid_vat" +msgid "" +"The value of the code \"%(code)s\" is not valid" +msgstr "" +"El valor del código \"%(code)s\" no es valido" + +msgctxt "model:ir.message,text:msg_invalid_vat_str" +msgid "" +"The value of the code can only be numbers" +msgstr "" +"El valor del código solo pueden ser números" + +msgctxt "model:ir.message,text:msg_not_identifier" +msgid "" +"The party has to have a identifier" +msgstr "" +"El tercero debe tener un identificador" + +msgctxt "model:ir.message,text:msg_stdnum_error" +msgid "" +"Is required module stdnum" +msgstr "" +"El módulo stdnum es requerido" \ No newline at end of file diff --git a/message.xml b/message.xml new file mode 100644 index 0000000..14fd95b --- /dev/null +++ b/message.xml @@ -0,0 +1,19 @@ + + + + + + The value of the code "%(code)s" is not valid + + + The party has to have a identifier + + + Is required module stdnum + + + The value of the code can only be numbers + + + diff --git a/party.py b/party.py index bfe3b2f..16873b2 100644 --- a/party.py +++ b/party.py @@ -1,8 +1,11 @@ from trytond.model import fields, ModelSQL, ModelView, Unique, sequence_ordered from trytond.pool import PoolMeta, Pool -from trytond.pyson import Eval, Not, Equal -import logging +from trytond.pyson import Eval, Not, Equal, Or, And +from trytond.i18n import gettext from trytond.exceptions import UserError +from .exceptions import PartyIdentifierError + +import logging logger = logging.getLogger(__name__) @@ -18,7 +21,7 @@ TAX_CO_IDENTIFIERS = [ ('22', 'Cedula de Extranjeria'), ('31', 'NIT'), ('41', 'Pasaporte'), - ('42', 'Tipo de Documento Extrangero'), + ('42', 'Tipo de Documento Extranjero'), ('43', 'Documento de identificación extranjero'), ('50', 'NIT de otro país'), ('91', 'NUIP') @@ -34,16 +37,16 @@ class Party(ModelSQL,ModelView): __metaclass__ = PoolMeta first_name = fields.Char("Primer Nombre",states={ - 'invisible': Not(Eval('type_person') == 'persona_natural'),} + 'invisible': Not(Eval('type_person') == '2'),} ) second_name = fields.Char("Segundo Nombre",states={ - 'invisible': Not(Eval('type_person') == 'persona_natural'),} + 'invisible': Not(Eval('type_person') == '2'),} ) first_surname = fields.Char("Primer Apellido",states={ - 'invisible': Not(Eval('type_person') == 'persona_natural'),} + 'invisible': Not(Eval('type_person') == '2'),} ) second_surname = fields.Char("Segundo Apellido",states={ - 'invisible': Not(Eval('type_person') == 'persona_natural'),}, + 'invisible': Not(Eval('type_person') == '2'),}, depends=['type_person']) birth_date = fields.Date('Fecha de nacimiento') tax_regime = fields.Selection([ @@ -75,21 +78,23 @@ class Party(ModelSQL,ModelView): 'on_change_with_type_tax_identifier') tax_level_code =fields.Many2Many('party.party_tax_level_code','party', 'tax_level_code', "TaxLevelCode") + @classmethod + def __setup__(cls): + super(Party, cls).__setup__() + cls.name.required = True @staticmethod def default_type_person(): - return 'persona_natural' + return '2' @classmethod def tax_identifier_types(cls): - #return ['11', '12', '13', '21', '22', '31', '41', '42', '43', '50', '91'] - return ['31'] + return ['12','13','31'] @classmethod def get_tax_level_code(cls): pool = Pool() TaxLevelCode = pool.get('party.tax_level_code') - #raise UserError(str(TaxLevelCode.fields_get(['code'])['code'])) return TaxLevelCode.fields_get(['code'])['code'] @fields.depends('birth_date') @@ -104,9 +109,9 @@ class Party(ModelSQL,ModelView): @fields.depends('name','first_name','second_name','first_surname', 'second_surname','type_person') def on_change_type_person(self): - if self.type_person == 'persona_natural': + if self.type_person == '2': self.on_change_name() - if self.type_person == 'persona_juridica': + if self.type_person == '1': pass @fields.depends('name','first_name','second_name','first_surname', @@ -138,7 +143,7 @@ class Party(ModelSQL,ModelView): """reconstruye los campos relacionados con el nombre dependiendo de estos y del tipo de persona.""" - if self.type_person == 'persona_natural': + if self.type_person == '2': if not (self.first_name or self.second_name \ or self.first_surname or self.second_surname): if self.name: @@ -148,7 +153,7 @@ class Party(ModelSQL,ModelView): return else: self.name = self.get_full_name() - if self.type_person == 'persona_juridica': + if self.type_person == '1': if self.name: self.clean_split_name() else: @@ -200,7 +205,7 @@ class Party(ModelSQL,ModelView): return types def get_full_name(self, name=None): - if self.type_person == 'persona_natural': + if self.type_person == '2': name_list = [self.first_name, self.second_name, self.first_surname,self.second_surname] return " ".join([x for x in name_list if x]) @@ -214,8 +219,10 @@ class Party(ModelSQL,ModelView): def pre_validate(self): super(Party, self).pre_validate() if not self.identifiers: - self.raise_user_error("El tercero debe tener un documento de identidad") + raise PartyIdentifierError(gettext( + 'account_co_co.msg_not_identifier')) + class PartyIdentifier(ModelSQL, ModelView): "Party Identifier Colombian" @@ -228,67 +235,101 @@ class PartyIdentifier(ModelSQL, ModelView): domain=[('parent', '!=', None)], states = {'invisible':Not(Equal(Eval('type'),'13'))} ) - rut = fields.Boolean('Rut') + rut = fields.Boolean('Rut', + states = {'invisible':And(Not(Equal(Eval('type'),('12'))), + Not(Equal(Eval('type'),('13'))), + Not(Equal(Eval('type'),('31')))), + 'readonly':Equal(Eval('type'),('31'))}) check_digit = fields.Function(fields.Integer('DV', - help='Digito de Verificacion colombiano', - states = {'invisible':Not(Equal(Eval('type'),'31'))}) - ,'on_change_with_check_digit') + help='Digito de Verificacion colombiano', + states = {'invisible':~Eval('rut', False)}) + ,'on_change_with_check_digit') @classmethod def __setup__(cls): super(PartyIdentifier, cls).__setup__() cls.type.selection = TAX_CO_IDENTIFIERS + cls.type.required = True table = cls.__table__() cls._sql_constraints += [ ('UniqueIdentifier', Unique(table, table.code,table.type), 'La identificacion ya existe') ] + @fields.depends('rut','type') + def on_change_type(self): + if self.type == '31': + self.rut = True + @fields.depends('type','code') def on_change_with_check_digit(self,name=None): try: import stdnum.co.nit #la version debe ser mayor a la 1.2 o 1.3 except: - self.raise_user_error('Se requiere modulo stdnum.co.nit') + raise PartyIdentifierError(gettext( + 'account_co_co.msg_stdnum_error')) if self.type and self.code: - if self.type in ('31'): + if self.type in ('12','13','31') and self.code.isdigit(): return int(stdnum.co.nit.calc_check_digit(self.code)) - @fields.depends('type', 'party', 'code') + @fields.depends('type', 'party', 'code', 'rut') def check_code(self): + + #if self.code.isdigit() is not True: + #raise UserError(str('33333')) super(PartyIdentifier, self).check_code() + tax_identifiers = ['12', '13', '31'] + if self.type == '31': + self.rut = True + if self.rut != False and self.type in tax_identifiers: #generalizar multiples paises #puede ser por el country del party de la company actual try: import stdnum.co.nit #la version debe ser mayor a la 1.2 o 1.3 except: - self.raise_user_error('Se requiere modulo stdnum.co.nit') + raise PartyIdentifierError(gettext( + 'account_co_co.msg_stdnum_error')) + + if self.code.isdigit() is not True: + raise PartyIdentifierError(gettext( + 'account_co_co.msg_invalid_vat_str')) if not stdnum.co.nit.is_valid(self.code + str(self.check_digit)): if self.party and self.party.id > 0: party = self.party.rec_name else: party = '' - self.raise_user_error('invalid_vat', { - 'code': self.code, - 'party': party, - }) - if self.type in ['12','13','31'] and not self.code.isdigit(): + raise PartyIdentifierError( + gettext('account_co_co.msg_invalid_vat', + code=self.code)) + #raise UserError(str('sdfsd')) + #self.raise_user_error('invalid_vat', { + #'code': self.code, + #'party': party, + #}) + if self.type in tax_identifiers and not self.code.isdigit(): if self.party and self.party.id > 0: party = self.party.rec_name else: party = '' - self.raise_user_error('invalid_vat',{ - 'code':self.code, - 'party':party - }) + raise PartyIdentifierError( + gettext('account_co_co.msg_invalid_vat', + code=self.code)) + #self.raise_user_error('invalid_vat',{ + #code=self.code, + #'party':party + #}) @staticmethod def default_type_document(): return '13' - + + @staticmethod + def default_rut(): + return False + def get_rec_name(self,name=None): if self.code: return self.code diff --git a/tryton.cfg b/tryton.cfg index c08a669..97a099c 100644 --- a/tryton.cfg +++ b/tryton.cfg @@ -8,6 +8,7 @@ xml: party.xml address.xml rut.xml + message.xml subdivisions_colombia.xml municipalities_colombia.xml address_subdivision_types_colombia.xml