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 party
from . import country from . import country
from . import rut from . import rut
__all__ = ['register'] __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" msgid "Economic Activity"
msgstr "Actividad Económica" 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>

105
party.py
View File

@ -1,8 +1,11 @@
from trytond.model import fields, ModelSQL, ModelView, Unique, sequence_ordered from trytond.model import fields, ModelSQL, ModelView, Unique, sequence_ordered
from trytond.pool import PoolMeta, Pool from trytond.pool import PoolMeta, Pool
from trytond.pyson import Eval, Not, Equal from trytond.pyson import Eval, Not, Equal, Or, And
import logging from trytond.i18n import gettext
from trytond.exceptions import UserError from trytond.exceptions import UserError
from .exceptions import PartyIdentifierError
import logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -18,7 +21,7 @@ TAX_CO_IDENTIFIERS = [
('22', 'Cedula de Extranjeria'), ('22', 'Cedula de Extranjeria'),
('31', 'NIT'), ('31', 'NIT'),
('41', 'Pasaporte'), ('41', 'Pasaporte'),
('42', 'Tipo de Documento Extrangero'), ('42', 'Tipo de Documento Extranjero'),
('43', 'Documento de identificación extranjero'), ('43', 'Documento de identificación extranjero'),
('50', 'NIT de otro país'), ('50', 'NIT de otro país'),
('91', 'NUIP') ('91', 'NUIP')
@ -34,16 +37,16 @@ class Party(ModelSQL,ModelView):
__metaclass__ = PoolMeta __metaclass__ = PoolMeta
first_name = fields.Char("Primer Nombre",states={ 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={ 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={ 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={ second_surname = fields.Char("Segundo Apellido",states={
'invisible': Not(Eval('type_person') == 'persona_natural'),}, 'invisible': Not(Eval('type_person') == '2'),},
depends=['type_person']) depends=['type_person'])
birth_date = fields.Date('Fecha de nacimiento') birth_date = fields.Date('Fecha de nacimiento')
tax_regime = fields.Selection([ tax_regime = fields.Selection([
@ -75,21 +78,23 @@ class Party(ModelSQL,ModelView):
'on_change_with_type_tax_identifier') 'on_change_with_type_tax_identifier')
tax_level_code =fields.Many2Many('party.party_tax_level_code','party', 'tax_level_code', "TaxLevelCode") 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 @staticmethod
def default_type_person(): def default_type_person():
return 'persona_natural' return '2'
@classmethod @classmethod
def tax_identifier_types(cls): def tax_identifier_types(cls):
#return ['11', '12', '13', '21', '22', '31', '41', '42', '43', '50', '91'] return ['12','13','31']
return ['31']
@classmethod @classmethod
def get_tax_level_code(cls): def get_tax_level_code(cls):
pool = Pool() pool = Pool()
TaxLevelCode = pool.get('party.tax_level_code') TaxLevelCode = pool.get('party.tax_level_code')
#raise UserError(str(TaxLevelCode.fields_get(['code'])['code']))
return TaxLevelCode.fields_get(['code'])['code'] return TaxLevelCode.fields_get(['code'])['code']
@fields.depends('birth_date') @fields.depends('birth_date')
@ -104,9 +109,9 @@ class Party(ModelSQL,ModelView):
@fields.depends('name','first_name','second_name','first_surname', @fields.depends('name','first_name','second_name','first_surname',
'second_surname','type_person') 'second_surname','type_person')
def on_change_type_person(self): def on_change_type_person(self):
if self.type_person == 'persona_natural': if self.type_person == '2':
self.on_change_name() self.on_change_name()
if self.type_person == 'persona_juridica': if self.type_person == '1':
pass pass
@fields.depends('name','first_name','second_name','first_surname', @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 """reconstruye los campos relacionados con el nombre dependiendo de
estos y del tipo de persona.""" 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 \ if not (self.first_name or self.second_name \
or self.first_surname or self.second_surname): or self.first_surname or self.second_surname):
if self.name: if self.name:
@ -148,7 +153,7 @@ class Party(ModelSQL,ModelView):
return return
else: else:
self.name = self.get_full_name() self.name = self.get_full_name()
if self.type_person == 'persona_juridica': if self.type_person == '1':
if self.name: if self.name:
self.clean_split_name() self.clean_split_name()
else: else:
@ -200,7 +205,7 @@ class Party(ModelSQL,ModelView):
return types return types
def get_full_name(self, name=None): 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, name_list = [self.first_name, self.second_name,
self.first_surname,self.second_surname] self.first_surname,self.second_surname]
return " ".join([x for x in name_list if x]) return " ".join([x for x in name_list if x])
@ -214,7 +219,9 @@ class Party(ModelSQL,ModelView):
def pre_validate(self): def pre_validate(self):
super(Party, self).pre_validate() super(Party, self).pre_validate()
if not self.identifiers: 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): class PartyIdentifier(ModelSQL, ModelView):
"Party Identifier Colombian" "Party Identifier Colombian"
@ -228,67 +235,101 @@ class PartyIdentifier(ModelSQL, ModelView):
domain=[('parent', '!=', None)], domain=[('parent', '!=', None)],
states = {'invisible':Not(Equal(Eval('type'),'13'))} 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', check_digit = fields.Function(fields.Integer('DV',
help='Digito de Verificacion colombiano', help='Digito de Verificacion colombiano',
states = {'invisible':Not(Equal(Eval('type'),'31'))}) states = {'invisible':~Eval('rut', False)})
,'on_change_with_check_digit') ,'on_change_with_check_digit')
@classmethod @classmethod
def __setup__(cls): def __setup__(cls):
super(PartyIdentifier, cls).__setup__() super(PartyIdentifier, cls).__setup__()
cls.type.selection = TAX_CO_IDENTIFIERS cls.type.selection = TAX_CO_IDENTIFIERS
cls.type.required = True
table = cls.__table__() table = cls.__table__()
cls._sql_constraints += [ cls._sql_constraints += [
('UniqueIdentifier', Unique(table, table.code,table.type), ('UniqueIdentifier', Unique(table, table.code,table.type),
'La identificacion ya existe') 'La identificacion ya existe')
] ]
@fields.depends('rut','type')
def on_change_type(self):
if self.type == '31':
self.rut = True
@fields.depends('type','code') @fields.depends('type','code')
def on_change_with_check_digit(self,name=None): def on_change_with_check_digit(self,name=None):
try: try:
import stdnum.co.nit #la version debe ser mayor a la 1.2 o 1.3 import stdnum.co.nit #la version debe ser mayor a la 1.2 o 1.3
except: 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 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)) 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): def check_code(self):
#if self.code.isdigit() is not True:
#raise UserError(str('33333'))
super(PartyIdentifier, self).check_code() super(PartyIdentifier, self).check_code()
tax_identifiers = ['12', '13', '31']
if self.type == '31': if self.type == '31':
self.rut = True
if self.rut != False and self.type in tax_identifiers:
#generalizar multiples paises #generalizar multiples paises
#puede ser por el country del party de la company actual #puede ser por el country del party de la company actual
try: try:
import stdnum.co.nit #la version debe ser mayor a la 1.2 o 1.3 import stdnum.co.nit #la version debe ser mayor a la 1.2 o 1.3
except: 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 not stdnum.co.nit.is_valid(self.code + str(self.check_digit)):
if self.party and self.party.id > 0: if self.party and self.party.id > 0:
party = self.party.rec_name party = self.party.rec_name
else: else:
party = '' party = ''
self.raise_user_error('invalid_vat', { raise PartyIdentifierError(
'code': self.code, gettext('account_co_co.msg_invalid_vat',
'party': party, code=self.code))
}) #raise UserError(str('sdfsd'))
if self.type in ['12','13','31'] and not self.code.isdigit(): #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: if self.party and self.party.id > 0:
party = self.party.rec_name party = self.party.rec_name
else: else:
party = '' party = ''
self.raise_user_error('invalid_vat',{ raise PartyIdentifierError(
'code':self.code, gettext('account_co_co.msg_invalid_vat',
'party':party code=self.code))
}) #self.raise_user_error('invalid_vat',{
#code=self.code,
#'party':party
#})
@staticmethod @staticmethod
def default_type_document(): def default_type_document():
return '13' return '13'
@staticmethod
def default_rut():
return False
def get_rec_name(self,name=None): def get_rec_name(self,name=None):
if self.code: if self.code:
return self.code return self.code

View File

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