RUT in Identifier and message/exceptions

This commit is contained in:
Alnus Tmp 2020-11-20 17:27:29 -05:00
parent 0c38c5dbfe
commit aa909bbffc
6 changed files with 129 additions and 35 deletions

View file

@ -2,6 +2,7 @@ from trytond.pool import Pool
from . import party
from . import country
from . import rut
__all__ = ['register']

9
exceptions.py Normal file
View file

@ -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

View file

@ -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"

19
message.xml Normal file
View file

@ -0,0 +1,19 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<tryton>
<data grouped="1">
<record model="ir.message" id="msg_invalid_vat">
<field name="text">The value of the code "%(code)s" is not valid</field>
</record>
<record model="ir.message" id="msg_not_identifier">
<field name="text">The party has to have a identifier</field>
</record>
<record model="ir.message" id="msg_stdnum_error">
<field name="text">Is required module stdnum</field>
</record>
<record model="ir.message" id="msg_invalid_vat_str">
<field name="text">The value of the code can only be numbers</field>
</record>
</data>
</tryton>

111
party.py
View file

@ -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

View file

@ -8,6 +8,7 @@ xml:
party.xml
address.xml
rut.xml
message.xml
subdivisions_colombia.xml
municipalities_colombia.xml
address_subdivision_types_colombia.xml