feature/T2026-05-016 implementar cargas de tareas en background e implementar y corregir auditoria para datastages

This commit is contained in:
Dulce
2026-05-18 11:54:46 -06:00
parent 3a636c14ae
commit 8cc0b9f573
8 changed files with 317 additions and 63 deletions

View File

@@ -9,6 +9,8 @@ import zipfile
import re
from api.utils.storage_service import storage_service
logger = logging.getLogger(__name__)
@shared_task
def procesar_datastage_task(datastage_id, user_organizacion_id=None):
import traceback
@@ -167,15 +169,22 @@ def procesar_archivo_asc_task(datastage_id, user_organizacion_id, asc_name):
continue
if first:
field_names = [f for f in line_decoded.split('|')]
field_names = line_decoded.split('|')
# Eliminar columnas vacías del final (líneas terminan con |)
while field_names and field_names[-1] == '':
field_names.pop()
field_names_snake = [to_snake_case(f) for f in field_names]
first = False
continue
values = line_decoded.split('|')
while values and values[-1] == '':
values.pop()
if len(values) != len(field_names_snake):
logger.debug(
"%s línea %d: esperados %d campos, recibidos %d — se omite",
asc_name, line_count, len(field_names_snake), len(values)
)
continue
data = dict(zip(field_names_snake, values))
@@ -185,28 +194,36 @@ def procesar_archivo_asc_task(datastage_id, user_organizacion_id, asc_name):
if hasattr(Model, 'datastage_id'):
data['datastage_id'] = datastage.id
# Limpiar fechas vacías
# Parsear y normalizar todos los campos de fecha/datetime
for field in Model._meta.get_fields():
if hasattr(field, 'get_internal_type') and field.get_internal_type() in ["DateField", "DateTimeField"]:
if data.get(field.name) == "":
data[field.name] = None
# Convertir fecha_pago_real
if 'fecha_pago_real' in data and data['fecha_pago_real']:
fecha_val = data['fecha_pago_real']
if isinstance(fecha_val, str):
try:
dt = datetime.datetime.strptime(fecha_val, '%Y-%m-%d %H:%M:%S')
except ValueError:
if not hasattr(field, 'get_internal_type'):
continue
field_type = field.get_internal_type()
val = data.get(field.name)
if val == '' or val is None:
data[field.name] = None
continue
if field_type == 'DateTimeField' and isinstance(val, str):
dt = None
for fmt in ('%Y-%m-%d %H:%M:%S', '%Y-%m-%d'):
try:
dt = datetime.datetime.strptime(fecha_val, '%Y-%m-%d')
except Exception:
dt = None
dt = datetime.datetime.strptime(val, fmt)
break
except ValueError:
continue
if dt and timezone.is_naive(dt):
dt = timezone.make_aware(dt)
if dt:
data['fecha_pago_real'] = dt
data[field.name] = dt
# Filtrar data para solo incluir campos válidos del modelo
valid_fields = set()
for f in Model._meta.get_fields():
if hasattr(f, 'name'):
valid_fields.add(f.name)
if hasattr(f, 'attname'):
valid_fields.add(f.attname)
data = {k: v for k, v in data.items() if k in valid_fields}
try:
obj = Model(**data)
objects_to_create.append(obj)
@@ -284,8 +301,9 @@ def procesar_archivo_asc_task(datastage_id, user_organizacion_id, asc_name):
try:
Pedimento.objects.create(**pedimento_data)
except Exception as ped_exc:
pass
logger.warning("No se pudo crear Pedimento %s: %s", pedimento_app, ped_exc)
except Exception as e:
logger.error("%s línea %d: error creando objeto %s: %s", asc_name, line_count, model_name, e)
continue
# Bulk create