T2026-05-030
This commit is contained in:
@@ -6,6 +6,8 @@ from api.customs.models import ProcesamientoPedimento, Pedimento, Cove, EDocumen
|
||||
from core.utils import xml_controller
|
||||
import requests
|
||||
from core.utils import xml_remesas_controller
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def obtener_pedimentos(organizacion_id):
|
||||
return Pedimento.objects.filter(organizacion_id=organizacion_id)
|
||||
@@ -35,23 +37,31 @@ def auditor_descargas(pedimento, servicio, related_name, variable, mensaje):
|
||||
pedimento_id = pedimento.id
|
||||
docs = getattr(pedimento, related_name).all()
|
||||
|
||||
print(f"pedimento: {pedimento}, servicio: {servicio}, related_name: {related_name}, variable: {variable}, mensaje: {mensaje}")
|
||||
logger.info(f"pedimento: {pedimento}, servicio: {servicio}, related_name: {related_name}, variable: {variable}, mensaje: {mensaje}")
|
||||
|
||||
# Si no hay documentos, marcar como completado
|
||||
if not docs.exists():
|
||||
proceso = modificar_estado_procesamiento(pedimento, servicio_id=servicio, nuevo_estado=3) # Estado "completado"
|
||||
print(f"✓ Pedimento {pedimento_id} no tiene {mensaje}s para procesar.")
|
||||
logger.info(f"✓ Pedimento {pedimento_id} no tiene {mensaje}s para procesar.")
|
||||
else:
|
||||
all_docs = all(getattr(doc, variable) for doc in docs)
|
||||
if all_docs:
|
||||
proceso = modificar_estado_procesamiento(pedimento, servicio_id=servicio, nuevo_estado=3) # Estado "completado"
|
||||
print(f"✓ Pedimento {pedimento_id} tiene todos sus {mensaje} descargados.")
|
||||
logger.info(f"✓ Pedimento {pedimento_id} tiene todos sus {mensaje} descargados.")
|
||||
else:
|
||||
proceso = modificar_estado_procesamiento(pedimento, servicio_id=servicio, nuevo_estado=4) # Estado "en progreso"
|
||||
print(f"✗ Pedimento {pedimento_id} NO tiene todos sus {mensaje} descargados.")
|
||||
logger.info(f"✗ Pedimento {pedimento_id} NO tiene todos sus {mensaje} descargados.")
|
||||
|
||||
if proceso:
|
||||
print(f"✓ Proceso de auditoría para pedimento {pedimento_id} completado.")
|
||||
logger.info(f"✓ Proceso de auditoría para pedimento {pedimento_id} completado.")
|
||||
else:
|
||||
print(f"✗ No se encontró proceso de auditoría para pedimento {pedimento_id}.")
|
||||
logger.info(f"✗ No se encontró proceso de auditoría para pedimento {pedimento_id}.")
|
||||
|
||||
## Auditar pedimentos
|
||||
|
||||
@@ -121,44 +131,66 @@ def auditar_procesamiento_remesa_por_pedimento(pedimento_id):
|
||||
|
||||
@shared_task
|
||||
def crear_partidas(organizacion_id):
|
||||
from api.customs.models import Partida
|
||||
|
||||
pedimentos = obtener_pedimentos(organizacion_id)
|
||||
total_pedimentos = pedimentos.count()
|
||||
pedimentos_procesados = 0
|
||||
total_partidas_agregadas = 0
|
||||
|
||||
print(f"Iniciando procesamiento de {total_pedimentos} pedimentos para organización {organizacion_id}")
|
||||
completados = []
|
||||
con_pendientes = []
|
||||
sin_datos = []
|
||||
errores = []
|
||||
|
||||
for pedimento in pedimentos:
|
||||
pedimentos_procesados += 1
|
||||
partidas_agregadas_pedimento = 0
|
||||
|
||||
# Validar que numero_partidas no sea None y sea mayor que 0
|
||||
if pedimento.numero_partidas is not None and pedimento.numero_partidas > 0:
|
||||
partidas_existentes = pedimento.partidas.count()
|
||||
if pedimento.numero_partidas > partidas_existentes:
|
||||
print(f"Procesando pedimento {pedimento.id} ({pedimentos_procesados}/{total_pedimentos}) - Partidas existentes: {partidas_existentes}, Requeridas: {pedimento.numero_partidas}")
|
||||
|
||||
for i in range(1, pedimento.numero_partidas + 1):
|
||||
from api.customs.models import Partida
|
||||
partida, created = Partida.objects.get_or_create(
|
||||
pedimento=pedimento,
|
||||
numero_partida=i,
|
||||
organizacion_id=organizacion_id
|
||||
)
|
||||
if created:
|
||||
partidas_agregadas_pedimento += 1
|
||||
total_partidas_agregadas += 1
|
||||
|
||||
print(f" → Partidas agregadas para pedimento {pedimento.id}: {partidas_agregadas_pedimento}")
|
||||
else:
|
||||
print(f"Pedimento {pedimento.id} ya tiene todas sus partidas ({partidas_existentes}/{pedimento.numero_partidas})")
|
||||
else:
|
||||
print(f"Pedimento {pedimento.id} omitido - numero_partidas: {pedimento.numero_partidas} (inválido)")
|
||||
try:
|
||||
if not pedimento.numero_partidas or pedimento.numero_partidas <= 0:
|
||||
sin_datos.append({
|
||||
'pedimento_id': str(pedimento.id),
|
||||
'pedimento': pedimento.pedimento,
|
||||
'razon': f'numero_partidas inválido ({pedimento.numero_partidas})',
|
||||
})
|
||||
continue
|
||||
|
||||
print(f"\n=== RESUMEN ===")
|
||||
print(f"Pedimentos procesados: {pedimentos_procesados}")
|
||||
print(f"Total de partidas agregadas: {total_partidas_agregadas}")
|
||||
print(f"Procesamiento completado para organización {organizacion_id}")
|
||||
for i in range(1, pedimento.numero_partidas + 1):
|
||||
Partida.objects.get_or_create(
|
||||
pedimento=pedimento,
|
||||
numero_partida=i,
|
||||
defaults={'organizacion_id': organizacion_id}
|
||||
)
|
||||
|
||||
partidas = list(pedimento.partidas.order_by('numero_partida'))
|
||||
no_descargadas = [p.numero_partida for p in partidas if not p.descargado]
|
||||
|
||||
if not no_descargadas:
|
||||
completados.append(str(pedimento.id))
|
||||
else:
|
||||
con_pendientes.append({
|
||||
'pedimento_id': str(pedimento.id),
|
||||
'pedimento': pedimento.pedimento,
|
||||
'total_partidas': len(partidas),
|
||||
'descargadas': len(partidas) - len(no_descargadas),
|
||||
'no_descargadas': no_descargadas,
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
errores.append({
|
||||
'pedimento_id': str(pedimento.id),
|
||||
'pedimento': pedimento.pedimento,
|
||||
'error': str(e),
|
||||
})
|
||||
logger.error(f"Error creando partidas para pedimento {pedimento.id}: {e}")
|
||||
|
||||
return {
|
||||
'organizacion_id': str(organizacion_id),
|
||||
'total_pedimentos': total_pedimentos,
|
||||
'completados': len(completados),
|
||||
'con_pendientes': len(con_pendientes),
|
||||
'sin_datos': len(sin_datos),
|
||||
'con_errores': len(errores),
|
||||
'detalle_pendientes': con_pendientes,
|
||||
'detalle_sin_datos': sin_datos,
|
||||
'detalle_errores': errores,
|
||||
}
|
||||
|
||||
@shared_task
|
||||
def crear_partidas_por_pedimento(pedimento_id):
|
||||
@@ -169,6 +201,7 @@ def crear_partidas_por_pedimento(pedimento_id):
|
||||
return
|
||||
|
||||
print(f"Procesando pedimento individual {pedimento_id}...")
|
||||
logger.info(f"Procesando pedimento individual {pedimento_id}...")
|
||||
partidas_agregadas = 0
|
||||
|
||||
# Validar que numero_partidas no sea None y sea mayor que 0
|
||||
@@ -176,6 +209,7 @@ def crear_partidas_por_pedimento(pedimento_id):
|
||||
partidas_existentes = pedimento.partidas.count()
|
||||
if pedimento.numero_partidas > partidas_existentes:
|
||||
print(f"Pedimento {pedimento_id} - Partidas existentes: {partidas_existentes}, Requeridas: {pedimento.numero_partidas}")
|
||||
logger.info(f"Pedimento {pedimento_id} - Partidas existentes: {partidas_existentes}, Requeridas: {pedimento.numero_partidas}")
|
||||
|
||||
for i in range(1, pedimento.numero_partidas + 1):
|
||||
from api.customs.models import Partida
|
||||
@@ -188,62 +222,165 @@ def crear_partidas_por_pedimento(pedimento_id):
|
||||
partidas_agregadas += 1
|
||||
|
||||
print(f"✓ Partidas agregadas para pedimento {pedimento_id}: {partidas_agregadas}")
|
||||
logger.info(f"✓ Partidas agregadas para pedimento {pedimento_id}: {partidas_agregadas}")
|
||||
else:
|
||||
print(f"Pedimento {pedimento_id} ya tiene todas sus partidas ({partidas_existentes}/{pedimento.numero_partidas})")
|
||||
logger.info(f"Pedimento {pedimento_id} ya tiene todas sus partidas ({partidas_existentes}/{pedimento.numero_partidas})")
|
||||
else:
|
||||
print(f"Error: Pedimento {pedimento_id} tiene numero_partidas inválido: {pedimento.numero_partidas}")
|
||||
logger.info(f"Error: Pedimento {pedimento_id} tiene numero_partidas inválido: {pedimento.numero_partidas}")
|
||||
|
||||
# Auditar coves
|
||||
def _auditar_organizacion(organizacion_id, servicio, related_name, variable, label):
|
||||
"""
|
||||
Itera todos los pedimentos de una organización auditando el campo `variable`
|
||||
en la relación `related_name`. Retorna un resumen estructurado por pedimento.
|
||||
"""
|
||||
pedimentos = obtener_pedimentos(organizacion_id)
|
||||
total_pedimentos = pedimentos.count()
|
||||
|
||||
completados = []
|
||||
pendientes = []
|
||||
errores = []
|
||||
|
||||
for pedimento in pedimentos:
|
||||
try:
|
||||
docs = list(getattr(pedimento, related_name).all())
|
||||
total = len(docs)
|
||||
faltantes = [
|
||||
getattr(doc, 'numero_cove', None) or getattr(doc, 'numero_edocument', None)
|
||||
for doc in docs if not getattr(doc, variable)
|
||||
]
|
||||
|
||||
if total == 0 or len(faltantes) == 0:
|
||||
nuevo_estado = 3
|
||||
completados.append(str(pedimento.id))
|
||||
else:
|
||||
nuevo_estado = 4
|
||||
pendientes.append({
|
||||
'pedimento_id': str(pedimento.id),
|
||||
'pedimento': pedimento.pedimento,
|
||||
f'faltantes_{label}': faltantes,
|
||||
'total': total,
|
||||
'descargados': total - len(faltantes),
|
||||
})
|
||||
|
||||
modificar_estado_procesamiento(pedimento, servicio_id=servicio, nuevo_estado=nuevo_estado)
|
||||
|
||||
except Exception as e:
|
||||
errores.append({
|
||||
'pedimento_id': str(pedimento.id),
|
||||
'pedimento': pedimento.pedimento,
|
||||
'error': str(e),
|
||||
})
|
||||
logger.error(f"Error auditando pedimento {pedimento.id} [{label}]: {e}")
|
||||
|
||||
return {
|
||||
'organizacion_id': str(organizacion_id),
|
||||
'auditoria': label,
|
||||
'total_pedimentos': total_pedimentos,
|
||||
'completados': len(completados),
|
||||
'con_pendientes': len(pendientes),
|
||||
'con_errores': len(errores),
|
||||
'detalle_pendientes': pendientes,
|
||||
'detalle_errores': errores,
|
||||
}
|
||||
|
||||
|
||||
@shared_task
|
||||
def auditar_coves(organizacion_id):
|
||||
for pedimento in obtener_pedimentos(organizacion_id):
|
||||
auditor_descargas(
|
||||
pedimento,
|
||||
servicio=8,
|
||||
related_name='coves',
|
||||
variable='cove_descargado',
|
||||
mensaje='COVE'
|
||||
)
|
||||
return _auditar_organizacion(
|
||||
organizacion_id,
|
||||
servicio=8,
|
||||
related_name='coves',
|
||||
variable='cove_descargado',
|
||||
label='cove',
|
||||
)
|
||||
|
||||
@shared_task
|
||||
def auditar_acuse_cove(organizacion_id):
|
||||
for pedimento in obtener_pedimentos(organizacion_id):
|
||||
auditor_descargas(
|
||||
pedimento,
|
||||
servicio=9,
|
||||
related_name='coves',
|
||||
variable='acuse_cove_descargado',
|
||||
mensaje='acuse de COVE'
|
||||
)
|
||||
return _auditar_organizacion(
|
||||
organizacion_id,
|
||||
servicio=9,
|
||||
related_name='coves',
|
||||
variable='acuse_cove_descargado',
|
||||
label='acuse_cove',
|
||||
)
|
||||
|
||||
# Revisa si el pedimento completo todos sus acuse coves
|
||||
|
||||
# Auditar edocuments
|
||||
@shared_task
|
||||
def auditar_edocuments(organizacion_id):
|
||||
for pedimento in obtener_pedimentos(organizacion_id):
|
||||
auditor_descargas(
|
||||
pedimento,
|
||||
servicio=7,
|
||||
related_name='documentos',
|
||||
variable='edocument_descargado',
|
||||
mensaje='EDocument'
|
||||
)
|
||||
|
||||
return _auditar_organizacion(
|
||||
organizacion_id,
|
||||
servicio=7,
|
||||
related_name='documentos',
|
||||
variable='edocument_descargado',
|
||||
label='edocument',
|
||||
)
|
||||
|
||||
@shared_task
|
||||
def auditar_acuse(organizacion_id):
|
||||
for pedimento in obtener_pedimentos(organizacion_id):
|
||||
auditor_descargas(
|
||||
pedimento,
|
||||
servicio=6,
|
||||
related_name='documentos',
|
||||
variable='acuse_descargado',
|
||||
mensaje='acuse'
|
||||
)
|
||||
return _auditar_organizacion(
|
||||
organizacion_id,
|
||||
servicio=6,
|
||||
related_name='documentos',
|
||||
variable='acuse_descargado',
|
||||
label='acuse',
|
||||
)
|
||||
|
||||
@shared_task
|
||||
def auditar_remesas(organizacion_id):
|
||||
"""
|
||||
Audita el estado de descarga de remesas para todos los pedimentos de una organización.
|
||||
A diferencia de coves/edocuments, las remesas no tienen campo booleano propio —
|
||||
se verifica la existencia de un documento de tipo 3 (Remesa) en el pedimento.
|
||||
"""
|
||||
pedimentos = obtener_pedimentos(organizacion_id)
|
||||
total_pedimentos = pedimentos.count()
|
||||
|
||||
completados = []
|
||||
pendientes = []
|
||||
errores = []
|
||||
|
||||
for pedimento in pedimentos:
|
||||
try:
|
||||
if not pedimento.remesas:
|
||||
# El pedimento no declara remesas — no aplica, marcar como completado
|
||||
modificar_estado_procesamiento(pedimento, servicio_id=5, nuevo_estado=3)
|
||||
completados.append(str(pedimento.id))
|
||||
elif pedimento.documents.filter(document_type=3).exists():
|
||||
# Documento de remesa ya descargado
|
||||
modificar_estado_procesamiento(pedimento, servicio_id=5, nuevo_estado=3)
|
||||
completados.append(str(pedimento.id))
|
||||
else:
|
||||
# Tiene remesas declaradas pero el documento aún no existe
|
||||
modificar_estado_procesamiento(pedimento, servicio_id=5, nuevo_estado=4)
|
||||
pendientes.append({
|
||||
'pedimento_id': str(pedimento.id),
|
||||
'pedimento': pedimento.pedimento,
|
||||
})
|
||||
except Exception as e:
|
||||
errores.append({
|
||||
'pedimento_id': str(pedimento.id),
|
||||
'pedimento': pedimento.pedimento,
|
||||
'error': str(e),
|
||||
})
|
||||
logger.error(f"Error auditando remesa de pedimento {pedimento.id}: {e}")
|
||||
|
||||
return {
|
||||
'organizacion_id': str(organizacion_id),
|
||||
'auditoria': 'remesa',
|
||||
'total_pedimentos': total_pedimentos,
|
||||
'completados': len(completados),
|
||||
'con_pendientes': len(pendientes),
|
||||
'con_errores': len(errores),
|
||||
'detalle_pendientes': pendientes,
|
||||
'detalle_errores': errores,
|
||||
}
|
||||
|
||||
@shared_task
|
||||
def auditar_cove_por_pedimento(pedimento_id):
|
||||
try:
|
||||
print(f"auditar_cove_por_pedimento >>>> {pedimento_id}")
|
||||
logger.info(f"auditar_cove_por_pedimento >>>> {pedimento_id}")
|
||||
from api.customs.models import Pedimento
|
||||
pedimento = Pedimento.objects.get(id=pedimento_id)
|
||||
auditor_descargas(
|
||||
|
||||
Reference in New Issue
Block a user