0% found this document useful (0 votes)
34 views

Codigo de Error Python

This document contains Python code for handling personal document data in Django models. It includes: 1. Models for representing personal document types, entities, and people with fields for names, document numbers, etc. 2. Functions for validating document numbers, looking up/creating person and entity records, and cleaning name fields. 3. Serializers for person data and search results. 4. SQL commands for initializing the personal_document_type lookup table and sample data.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
34 views

Codigo de Error Python

This document contains Python code for handling personal document data in Django models. It includes: 1. Models for representing personal document types, entities, and people with fields for names, document numbers, etc. 2. Functions for validating document numbers, looking up/creating person and entity records, and cleaning name fields. 3. Serializers for person data and search results. 4. SQL commands for initializing the personal_document_type lookup table and sample data.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 7

from django.

db import models, transaction


import django
from typing import Tuple, Optional
import datetime
from funes.models.entity import Entity
from rest_framework import serializers

def dni_to_ruc(dni:str) -> int:


suma = 0
for a,b in zip([int(i) for i in list('10' + dni)], [5,0,3,2,7,6,5,4,3,2]):
suma += a*b

final_digit = 11 - (suma % 11)


if final_digit == 11:
final_digit = '1'
elif final_digit == 10:
final_digit = '0'
else:
final_digit = str(final_digit)
return int('10' + dni + final_digit)

def check_if_ruc_is_valid(ruc:str) -> Tuple[bool, str]:


is_valid, explanation = True, ''
is_personal = ruc[:2] == '10'
is_company = ruc[:2] == '20'
is_special = ruc[:2] in ['15', '17']
if is_special:
is_valid = True
elif is_company:
is_valid = True
elif is_personal:
is_valid = dni_to_ruc(ruc[2:10]) == ruc
if not is_valid:
explanation = "RUC parece invalido para ese DNI"
else:
is_valid, explanation = False, 'RUC no comienza con 10, 20, 15 o 17'
return is_valid, explanation

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'),)

DOC_TYPES_MAPPER = {i.name:i for i in PersonalDocumentType.objects.all()}


NAMES_FIELDS = ['names', 'paternal_lastname', 'maternal_lastname', 'fullname']

@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

bypass placeholder document for trusted sources such as SUNAT


"""
document_type, document_number = document_type.strip(), document_number.strip()
doc_type = cls.DOC_TYPES_MAPPER[document_type]
q = cls.objects.filter(personal_document_type = doc_type, personal_document = document_number)
prev_count = q.count()
if prev_count > 0:
person = q.select_related('entity')[0]
changed = False
for i in ['names', 'paternal_lastname', 'maternal_lastname', 'fullname', 'birth_date']:
if eval(i) is not None and getattr(person, i) is None:
setattr(person,i,eval(i))
changed = True
if changed:
person.save()

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

return person, entity

@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

return person, entity, found


@classmethod
def check_if_names_are_close(cls, current_fullname:str, new_fullname:str) -> bool:
names = set(current_fullname.split(" "))
new_names = set(new_fullname.split(" "))
# NOTE
# Si es 0, son lo mismo, la diferencia no quito ni una sola palabra
# Si es -2, 2 palabras en comun
return len( new_names.difference(names)) - len(new_names) < -1

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

insert into personal_document_type(name, short_name)


values('Otro Nacional', 'Otro documento nacional de fuentes que no especifican bien el tipo'),
('Otro Extranjero', 'Otro documento extranjero de fuentes que no especifican bien el tipo')

CREATE TABLE entity(


id serial primary key
);

CREATE TABLE person(


id serial primary key,
entity_id integer references entity(id),
personal_document_type_id integer references personal_document_type(id),
personal_document text not null,

names text,
paternal_lastname text,
maternal_lastname text,
fullname text,

birth_date date
);

CREATE UNIQUE INDEX idx_person_document ON person(personal_document_type_id,


personal_document);
"""

You might also like