Files
backend/api/reports/views_table.py

169 lines
6.6 KiB
Python

from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.pagination import PageNumberPagination
from django.db.models import Value, CharField, Q, Exists, OuterRef, Subquery
from django.db.models.functions import Cast
from datetime import datetime, timedelta
from api.customs.models import Pedimento, Cove, EDocument, Partida
class CustomPagination(PageNumberPagination):
page_size = 50
page_size_query_param = 'page_size'
max_page_size = 1000
@api_view(['GET'])
@permission_classes([IsAuthenticated])
def table_summary(request):
"""
Endpoint que devuelve un resumen tabulado de pedimentos y sus documentos asociados.
"""
org_id = request.query_params.get('organizacion_id')
if not org_id:
return Response({"error": "organizacion_id es requerido"}, status=400)
# Obtener filtros de query params
tipo_documento = request.query_params.get('tipo_documento')
rfc = request.query_params.get('contribuyente__rfc')
fecha_pago_gte = request.query_params.get('fecha_pago__gte')
fecha_pago_lte = request.query_params.get('fecha_pago__lte')
patente = request.query_params.get('patente')
aduana = request.query_params.get('aduana')
pedimento = request.query_params.get('pedimento')
pedimento_app = request.query_params.get('pedimento_app')
regimen = request.query_params.get('regimen')
tipo_operacion = request.query_params.get('tipo_operacion')
# Si no se proporcionan fechas, establecer un rango por defecto de los últimos 30 días
if not fecha_pago_gte and not fecha_pago_lte:
fecha_pago_lte = datetime.now().date()
fecha_pago_gte = fecha_pago_lte - timedelta(days=30)
# Construir filtros base para pedimentos
pedimentos_filters = Q(organizacion_id=org_id)
# Añadir filtros de fecha siempre para limitar el conjunto de datos
pedimentos_filters &= Q(fecha_pago__gte=fecha_pago_gte)
pedimentos_filters &= Q(fecha_pago__lte=fecha_pago_lte)
if rfc:
pedimentos_filters &= Q(contribuyente__rfc=rfc)
if patente:
pedimentos_filters &= Q(patente=patente)
if aduana:
pedimentos_filters &= Q(aduana=aduana)
if pedimento:
pedimentos_filters &= Q(pedimento=pedimento)
if pedimento_app:
pedimentos_filters &= Q(pedimento_app=pedimento_app)
if regimen:
pedimentos_filters &= Q(regimen=regimen)
if tipo_operacion:
pedimentos_filters &= Q(tipo_operacion_id=tipo_operacion)
# Query base desde pedimentos con todas las subconsultas necesarias
resultado = Pedimento.objects.filter(pedimentos_filters).values(
'aduana',
'patente',
'regimen',
'pedimento',
'pedimento_app',
'clave_pedimento',
'tipo_operacion_id',
'contribuyente_id'
)
# Generar queries según el tipo de documento solicitado
queries = []
if not tipo_documento or tipo_documento == 'ACUSE COVE':
coves_acuse = resultado.annotate(
identificador=Cast(Subquery(
Cove.objects.filter(pedimento_id=OuterRef('id')).values('numero_cove')[:1]
), CharField()),
documento=Value('ACUSE COVE', CharField()),
estado=Cast(Subquery(
Cove.objects.filter(pedimento_id=OuterRef('id')).values('acuse_cove_descargado')[:1]
), CharField())
).filter(identificador__isnull=False)
queries.append(coves_acuse)
if not tipo_documento or tipo_documento == 'COVE':
coves = resultado.annotate(
identificador=Cast(Subquery(
Cove.objects.filter(pedimento_id=OuterRef('id')).values('numero_cove')[:1]
), CharField()),
documento=Value('COVE', CharField()),
estado=Cast(Subquery(
Cove.objects.filter(pedimento_id=OuterRef('id')).values('cove_descargado')[:1]
), CharField())
).filter(identificador__isnull=False)
queries.append(coves)
if not tipo_documento or tipo_documento == 'ACUSE EDOC':
edocs_acuse = resultado.annotate(
identificador=Cast(Subquery(
EDocument.objects.filter(pedimento_id=OuterRef('id')).values('numero_edocument')[:1]
), CharField()),
documento=Value('ACUSE EDOC', CharField()),
estado=Cast(Subquery(
EDocument.objects.filter(pedimento_id=OuterRef('id')).values('acuse_descargado')[:1]
), CharField())
).filter(identificador__isnull=False)
queries.append(edocs_acuse)
if not tipo_documento or tipo_documento == 'EDOC':
edocs = resultado.annotate(
identificador=Cast(Subquery(
EDocument.objects.filter(pedimento_id=OuterRef('id')).values('numero_edocument')[:1]
), CharField()),
documento=Value('EDOC', CharField()),
estado=Cast(Subquery(
EDocument.objects.filter(pedimento_id=OuterRef('id')).values('edocument_descargado')[:1]
), CharField())
).filter(identificador__isnull=False)
queries.append(edocs)
if not tipo_documento or tipo_documento == 'PARTIDA':
partidas = resultado.annotate(
identificador=Cast(Subquery(
Partida.objects.filter(pedimento_id=OuterRef('id')).values('numero_partida')[:1]
), CharField()),
documento=Value('PARTIDA', CharField()),
estado=Cast(Subquery(
Partida.objects.filter(pedimento_id=OuterRef('id')).values('descargado')[:1]
), CharField())
).filter(identificador__isnull=False)
queries.append(partidas)
# Unir los resultados usando UNION ALL para mejor rendimiento
if not queries:
return Response([])
resultado_final = queries[0]
for query in queries[1:]:
resultado_final = resultado_final.union(query, all=True)
# Aplicar paginación
paginator = CustomPagination()
page = paginator.paginate_queryset(
resultado_final.order_by('pedimento', 'documento'),
request
)
return paginator.get_paginated_response({
"results": page,
"filtros_aplicados": {
"organizacion_id": org_id,
"tipo_documento": tipo_documento,
"contribuyente__rfc": rfc,
"fecha_pago__gte": fecha_pago_gte,
"fecha_pago__lte": fecha_pago_lte,
"patente": patente,
"aduana": aduana,
"pedimento": pedimento,
"pedimento_app": pedimento_app,
"regimen": regimen,
"tipo_operacion": tipo_operacion
}
})