RUT in Identifier and message/exceptions
This commit is contained in:
parent
0c38c5dbfe
commit
aa909bbffc
6 changed files with 129 additions and 35 deletions
|
@ -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
9
exceptions.py
Normal 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
|
23
locale/es.po
23
locale/es.po
|
@ -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
19
message.xml
Normal 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
111
party.py
|
@ -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,8 +219,10 @@ 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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue