trytondo-account_co_co/party.py
2020-11-16 12:06:49 -05:00

352 lines
13 KiB
Python

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.exceptions import UserError
logger = logging.getLogger(__name__)
__all__ = ['PartyIdentifier','Party','ContactMechanism','Address','PartyTaxLevelCode']
CO_IDENTIFIERS = [
(None, ''),
('11', 'Registro Civil'),
('12', 'Tarjeta de Identidad'),
('13', 'Cedula de Ciudadania'),
('21', 'Tarjeta de Extranjeria'),
('22', 'Cedula de Extranjeria'),
('31', 'NIT'),
('41', 'Pasaporte'),
('42', 'Tipo de Documento Extrangero'),
('43', 'Documento de identificación extranjero'),
('50', 'NIT de otro país'),
('91', 'NUIP')
]
CO_CONTACT_MECHANISM_TYPES = [
('sms','SMS')
]
class Party(ModelSQL,ModelView):
"Party Colombian"
__name__='party.party'
__metaclass__ = PoolMeta
first_name = fields.Char("Primer Nombre",states={
'invisible': Not(Eval('type_person') == 'persona_natural'),}
)
second_name = fields.Char("Segundo Nombre",states={
'invisible': Not(Eval('type_person') == 'persona_natural'),}
)
first_surname = fields.Char("Primer Apellido",states={
'invisible': Not(Eval('type_person') == 'persona_natural'),}
)
second_surname = fields.Char("Segundo Apellido",states={
'invisible': Not(Eval('type_person') == 'persona_natural'),},
depends=['type_person'])
birth_date = fields.Date('Fecha de nacimiento')
regime_tax = fields.Selection([
(None, ''),
('regimen_simplificado', 'Regimen Simplificado'),
('regimen_comun', 'Regimen Comun'),
('gran_contribuyente', 'Gran Contribuyente'),
('entidad_estatal', 'Entidad Estatal'),
('domiciliado_extranjero', 'Domiciliado en Extranjero'),
], 'Regimen de Impuestos')
type_person = fields.Selection([
(None, ''),
('persona_natural', 'Persona Natural'),
('persona_juridica', 'Persona Juridica'),
], 'Tipo de Persona')
self_withholding = fields.Boolean('Self Withholding')
declarant = fields.Boolean('Declarant')
main_ciiu_code = fields.Char('Main CIIU Code', size=4)
secondary_ciiu_code = fields.Char('Secondary CIIU Code', size=4)
other_ciiu_code = fields.Char('Other CIIU Code', size=4)
age = fields.Function(fields.Integer('Edad'),'on_change_with_age')
type_tax_identifier = fields.Function(fields.Selection('get_types_identifier',
'Tipo de Identidad'),
'on_change_with_type_tax_identifier')
tax_level_code =fields.Many2Many('party.party_tax_level_code','party', 'tax_level_code', "TaxLevelCode")
@staticmethod
def default_type_person():
return 'persona_natural'
@classmethod
def tax_identifier_types(cls):
#return ['11', '12', '13', '21', '22', '31', '41', '42', '43', '50', '91']
return ['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')
def on_change_with_age(self,name=None):
if self.birth_date:
Date = Pool().get('ir.date')
today = Date.today()
age = today.year - self.birth_date.year
age -= (today.month, today.day) < (self.birth_date.month, self.birth_date.day)
return age
@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':
self.on_change_name()
if self.type_person == 'persona_juridica':
pass
@fields.depends('name','first_name','second_name','first_surname',
'second_surname','type_person')
def on_change_name(self):
self.rebuild_name()
@fields.depends('name','first_name','second_name','first_surname',
'second_surname','type_person')
def on_change_first_name(self):
self.rebuild_name()
@fields.depends('name','first_name','second_name','first_surname',
'second_surname','type_person')
def on_change_second_name(self):
self.rebuild_name()
@fields.depends('name','first_name','second_name','first_surname',
'second_surname','type_person')
def on_change_second_surname(self):
self.rebuild_name()
@fields.depends('name','first_name','second_name','first_surname',
'second_surname','type_person')
def on_change_first_surname(self):
self.rebuild_name()
def rebuild_name(self):
"""reconstruye los campos relacionados con el nombre dependiendo de
estos y del tipo de persona."""
if self.type_person == 'persona_natural':
if not (self.first_name or self.second_name \
or self.first_surname or self.second_surname):
if self.name:
self.first_name, self.second_name, self.first_surname, \
self.second_surname = self.split_name(self.name)
else:
return
else:
self.name = self.get_full_name()
if self.type_person == 'persona_juridica':
if self.name:
self.clean_split_name()
else:
self.name = self.get_full_name()
def clean_split_name(self):
self.first_name = self.second_name = self.first_surname = self.second_surname = ''
@staticmethod
def split_name(name):
"""Divide un nombre completo en una lista de 4 elementos"""
second_surname = None
first_surname = None
second_name = None
first_name = None
names = name.split(' ')
if len(names) > 0:
first_name = names[0]
if len(names) == 2:
second_surname = None
first_surname = names[1]
elif len(names) == 3:
first_surname = names[1]
second_surname = names[2]
elif len(names) >= 4:
second_name = names[1]
first_surname = names[2]
second_surname = " ".join(names[3:])
return [first_name,second_name,first_surname, second_surname]
@fields.depends('identifiers')
def on_change_with_type_tax_identifier(self,name=None):
types = self._tax_identifier_types()
if self.identifiers:
for identifier in self.identifiers:
if identifier.type in types:
return identifier.type
@fields.depends('identifiers')
def on_change_with_tax_identifier(self,name=None):
if self.identifiers:
return self.get_tax_identifier(name)
@classmethod
def _tax_identifier_types(cls):
types = super(Party, cls).tax_identifier_types()
types.extend(['31','13'])
return types
def get_full_name(self, name=None):
if self.type_person == 'persona_natural':
name_list = [self.first_name, self.second_name,
self.first_surname,self.second_surname]
return " ".join([x for x in name_list if x])
return self.name
@staticmethod
def get_types_identifier():
PartyIdentifier = Pool().get('party.identifier')
return PartyIdentifier.type.selection
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")
class PartyIdentifier(ModelSQL, ModelView):
"Party Identifier Colombian"
__name__ = "party.identifier"
__metaclass__ = PoolMeta
expedition_city = fields.Many2One("country.subdivision",
'Ciudad de Expedicion',
help="Lugar donde fue expedido el documento de identidad",
domain=[('parent', '!=', None)],
states = {'invisible':Not(Equal(Eval('type'),'13'))}
)
rut = fields.Boolean('Rut')
check_digit = fields.Function(fields.Integer('DV',
help='Digito de Verificacion colombiano',
states = {'invisible':Not(Equal(Eval('type'),'31'))})
,'on_change_with_check_digit')
@classmethod
def __setup__(cls):
super(PartyIdentifier, cls).__setup__()
cls.type.selection = CO_IDENTIFIERS
table = cls.__table__()
cls._sql_constraints += [
('UniqueIdentifier', Unique(table, table.code,table.type),
'La identificacion ya existe')
]
@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')
if self.type and self.code:
if self.type in ('31'):
return int(stdnum.co.nit.calc_check_digit(self.code))
@fields.depends('type', 'party', 'code')
def check_code(self):
super(PartyIdentifier, self).check_code()
if self.type == '31':
#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')
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():
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
})
@staticmethod
def default_type_document():
return '13'
def get_rec_name(self,name=None):
if self.code:
return self.code
elif self.id:
return self.id
return ''
class PartyTaxLevelCode(ModelSQL, ModelView):
"Party Tax Level Code"
__name__ = 'party.party_tax_level_code'
party = fields.Many2One('party.party', 'Party', select=True)
tax_level_code = fields.Many2One('party.tax_level_code', 'TaxLevelCode', select=True)
class ContactMechanism(sequence_ordered(), ModelSQL, ModelView):
"Contact Mechanism"
__name__ = 'party.contact_mechanism'
__metaclass__ = PoolMeta
@classmethod
def __setup__(cls):
super(ContactMechanism, cls).__setup__()
cls.type.selection.extend(CO_CONTACT_MECHANISM_TYPES)
class Address(ModelSQL, ModelView):
"Address"
__metaclass__ = PoolMeta
__name__ = 'party.address'
subdivision_municipality = fields.Many2One("country.subdivision",
'Municipality',
domain=[
('country', '=', Eval('country', -1)),
('parent', '=', Eval('subdivision', -1)),
('type', '=', 'municipality')
],
depends=['country', 'subdivision', 'city'],
)
@fields.depends('subdivision', 'subdivision_municipality', 'country')
def on_change_country(self):
super(Address, self).on_change_country()
if (self.subdivision_municipality
and self.subdivision_municipality.parent != self.subdivision):
self.subdivision_municipality = None
@fields.depends('subdivision', 'subdivision_municipality')
def on_change_subdivision(self):
if hasattr(super(Address, self), 'on_change_subdivision'):
super(Address, self).on_change_subdivision()
if (self.subdivision_municipality
and self.subdivision_municipality.parent != self.subdivision):
self.subdivision_municipality = None
@fields.depends('city', 'subdivision_municipality')
def on_change_subdivision_municipality(self):
if self.subdivision_municipality:
self.city = self.subdivision_municipality.name
else:
self.city = None