Codigo de Error Python
Codigo de Error Python
class MissformedDNI(Exception):
pass
class PlaceholderDocument(Exception):
pass
class PersonalDocumentType(models.Model):
name = models.TextField(verbose_name='Nombre')
short_name = models.TextField(verbose_name='Abreviacion')
class Meta:
managed = False
db_table = 'personal_document_type'
verbose_name = 'Tipo de documento personal'
class Person(models.Model):
entity = models.ForeignKey(Entity, models.DO_NOTHING, blank=True, null=True)
personal_document_type = models.ForeignKey(PersonalDocumentType, models.DO_NOTHING,
blank=True, null=True)
personal_document = models.TextField(verbose_name='Numero de documento')
names = models.TextField(blank=True, null=True, verbose_name='Nombres')
paternal_lastname = models.TextField(blank=True, null=True, verbose_name='Apellido paterno')
maternal_lastname = models.TextField(blank=True, null=True, verbose_name='Apellido materno')
fullname = models.TextField(blank=True, null=True, verbose_name='Nombres completos')
birth_date = models.DateField(blank=True, null=True, verbose_name='Fecha de nacimiento')
class Meta:
managed = False
db_table = 'person'
unique_together = (('personal_document_type', 'personal_document'),)
@classmethod
def create(cls,**kwargs):
kwargs = dict(**kwargs)
names = kwargs['names']
doc_num = kwargs['personal_document']
bypass_placeholder_document = kwargs.pop('bypass_placeholder_document', False)
if names:
kwargs['names'] = " ".join(sorted(names.split(" "))) # ordenando nombres alfabeticamente, si el
campo esta claro
for k in cls.NAMES_FIELDS:
kwargs[k] = cls.clean_a_name( kwargs[k] )
if kwargs['personal_document_type'].name == "DNI":
if len(doc_num) != 8 or (not doc_num.isdigit()) or int(doc_num) < 0:
raise MissformedDNI(doc_num)
if (len(set(doc_num)) < 3 or doc_num == "12345678") and not bypass_placeholder_document:
# NOTE: important to bypass this Exception on trustable sources, such as Infogob
raise PlaceholderDocument(doc_num)
return cls.objects.create(**kwargs)
@classmethod
def get_create_update(
cls, document_type:str, document_number:str,
names:str=None, paternal_lastname:str=None, maternal_lastname:str=None, fullname:str=None,
birth_date:datetime.date=None,
bypass_placeholder_document = False
) -> Tuple['Person', Entity]:
"""
If Person already exists
Return Person and Entity
If we have any new data
Update it
If Person doesnt exists
Create new Person and Entity
entity = person.entity
else:
# NOTE: attempt to correct if pseudo DNI was inserted previously
if doc_type.name == "DNI":
person, entity, found = cls.try_to_match_document_number_and_names(document_number,
fullname, cls.DOC_TYPES_MAPPER['PSEUDO DNI'])
if found:
person.personal_document_type = cls.DOC_TYPES_MAPPER['DNI']
person.save()
else:
found = False
if not found:
entity = Entity.objects.create()
# NOTE: Hay un error de insercion raro, intenta insertar el mismo doc a pesar que no deberia enrar a
este if
# try:
# with transaction.atomic():
person = cls.create(
personal_document_type = doc_type,
personal_document = document_number.strip(),
entity = entity,
names = names,
paternal_lastname = paternal_lastname,
maternal_lastname = maternal_lastname,
fullname = fullname,
birth_date = birth_date,
bypass_placeholder_document = bypass_placeholder_document
)
# except django.db.utils.IntegrityError as e:
# import code
# code.interact(local=dict(locals(), **globals()))
# raise e
@classmethod
def try_to_match_document_number_and_names(cls, nro_doc:str, fullname:str,
doc_type:PersonalDocumentType) -> Tuple['Person', Entity, bool]:
"""
Used when the document number has 8 characters but the type is misspecified or not specified
Check perfilprov 'OTRO DOCUMENTO', "DOCUMENTO PROVISIONAL DE IDENTIDAD"
It maybe a DNI, and we check past data
"""
nro_doc = nro_doc.strip()
assert len(nro_doc) == 8, "document_number has not got 8 numbers"
try:
person = Person.objects.filter(personal_document_type = doc_type, personal_document =
nro_doc).select_related('entity')[0]
if cls.check_if_names_are_close(person.fullname, fullname):
entity, found = person.entity, True
else:
entity, found = None, False
except:
person, entity, found = None, None, False
@classmethod
def insert_likely_dni(cls, nro_doc:str, fullname:str) -> Tuple['Person', Entity]:
"""
To use when the document type is not explicit
Tries to match an existing DNI.
If not found inserts with a special document_type to be corrected manually later on
"""
assert len(nro_doc) == 8, "document_number has not got 8 numbers"
person, entity, found = cls.try_to_match_document_number_and_names(nro_doc, fullname,
cls.DOC_TYPES_MAPPER['DNI'])
if not found:
person, entity = Person.get_create_update('PSEUDO DNI', nro_doc, fullname=fullname)
return person, entity
@classmethod
def clean_a_name(cls, s:str) -> str:
if s:
s = s.strip()
s = " ".join(s.split(None))
return s
class PersonSerializer(serializers.ModelSerializer):
class Meta:
model = Person
fields = [ 'fullname', 'birth_date', 'personal_document' ]
read_only_fields = fields
class PersonSearchSerializer(serializers.ModelSerializer):
personal_document_type = serializers.CharField(source='personal_document_type.short_name',
read_only=True)
class Meta:
model = Person
fields = [i.name for i in Person._meta.fields]
read_only_fields = fields
"""
-- fix de error al insertar primeros records de contraloria
UPDATE person
SET fullname = concat_ws(' ', names, paternal_lastname, maternal_lastname)
-- fullname = " ".join([parsed['nombres'] , parsed['apellido_paterno'] , parsed['apellido_materno']])
WHERE id IN (
SELECT id
FROM person, lateral (select max(char_length(x)) as max_l from
unnest(regexp_split_to_array(fullname, ' ')) as x) b
WHERE max_l > 10
) AND paternal_lastname is not null;
"""
"""
CREATE TABLE personal_document_type(
id serial primary key,
name text not null,
short_name text not null
);
--"INSERT INTO (,) VALUES (" + "), (".join([ "'" + i["name_short"]+ "'" + ",'" + i["name"] +"'" for i in
doc_types]) + ")"
INSERT INTO personal_document_type(name, short_name)
VALUES ('DNI','Documento nacional de identidad'), ('DPI','Documento provisional de identidad'), ('C.
FFAA','Carnét de fuerzas armadas'), ('C. FFPP','Carnét de fuerzas policiales'), ('RUC','Registro único del
contribuyente'), ('DT.S/RUC','Destinatario sin RUC'), ('C. EXT','Carnét de extranjería'), ('C.
IDENT','Cédula diplomática de identidad'), ('PASAPORTE','Pasaporte'), ('C. PTP','Carnét de permiso
temporal de permanencia'), ('L.T.','Libreta tributaria')
names text,
paternal_lastname text,
maternal_lastname text,
fullname text,
birth_date date
);