from celery import shared_task from django.core.files.base import ContentFile from django.utils import timezone from api.reports.models import ReportDocument from api.customs.models import Pedimento, Cove, EDocument, Partida from django.db.models import Q import csv import os from django.conf import settings @shared_task def generate_report_document(report_id): try: report = ReportDocument.objects.get(id=report_id) report.status = 'processing' report.save(update_fields=['status']) filters = report.filters or {} # Construir Q para filtros complejos pedimentos_filters = Q() if filters.get('organizacion_id'): pedimentos_filters &= Q(organizacion_id=filters['organizacion_id']) if filters.get('fecha_pago__gte'): pedimentos_filters &= Q(fecha_pago__gte=filters['fecha_pago__gte']) if filters.get('fecha_pago__lte'): pedimentos_filters &= Q(fecha_pago__lte=filters['fecha_pago__lte']) if filters.get('contribuyente__rfc'): pedimentos_filters &= Q(contribuyente__rfc=filters['contribuyente__rfc']) if filters.get('patente'): pedimentos_filters &= Q(patente=filters['patente']) if filters.get('aduana'): pedimentos_filters &= Q(aduana=filters['aduana']) if filters.get('pedimento'): pedimentos_filters &= Q(pedimento=filters['pedimento']) if filters.get('pedimento_app'): pedimentos_filters &= Q(pedimento_app=filters['pedimento_app']) if filters.get('regimen'): pedimentos_filters &= Q(regimen=filters['regimen']) if filters.get('tipo_operacion'): pedimentos_filters &= Q(tipo_operacion_id=filters['tipo_operacion']) # Consulta asíncrona de los modelos pedimentos = Pedimento.objects.filter(pedimentos_filters) filename = filters.get('filename') if filename: filename = f"{filename}.csv" if not filename.endswith('.csv') else filename else: filename = f"report_{report.id}_{timezone.now().strftime('%Y%m%d%H%M%S')}.csv" file_path = os.path.join(settings.MEDIA_ROOT, 'reports', filename) os.makedirs(os.path.dirname(file_path), exist_ok=True) with open(file_path, 'w', newline='', encoding='utf-8') as f: writer = csv.writer(f) headers = [ 'aduana', 'patente', 'regimen', 'pedimento', 'pedimento_app', 'clave_pedimento', 'tipo_operacion_id', 'contribuyente_id', 'tipo_documento', 'numero_documento', 'estado', 'acuse_estado' ] writer.writerow(headers) for ped in pedimentos: for cove in Cove.objects.filter(pedimento=ped): writer.writerow([ ped.aduana, ped.patente, ped.regimen, ped.pedimento, ped.pedimento_app, ped.clave_pedimento, ped.tipo_operacion_id, ped.contribuyente_id, 'COVE', cove.numero_cove, cove.cove_descargado, cove.acuse_cove_descargado ]) for edoc in EDocument.objects.filter(pedimento=ped): writer.writerow([ ped.aduana, ped.patente, ped.regimen, ped.pedimento, ped.pedimento_app, ped.clave_pedimento, ped.tipo_operacion_id, ped.contribuyente_id, 'EDOC', edoc.numero_edocument, edoc.edocument_descargado, edoc.acuse_descargado ]) for partida in Partida.objects.filter(pedimento=ped): writer.writerow([ ped.aduana, ped.patente, ped.regimen, ped.pedimento, ped.pedimento_app, ped.clave_pedimento, ped.tipo_operacion_id, ped.contribuyente_id, 'PARTIDA', partida.numero_partida, partida.descargado, '' ]) # Guardar el archivo en el modelo with open(file_path, 'rb') as f: report.file.save(filename, ContentFile(f.read()), save=True) report.status = 'ready' report.finished_at = timezone.now() report.save(update_fields=['status', 'file', 'finished_at']) except Exception as e: report.status = 'error' report.error_message = str(e) report.finished_at = timezone.now() report.save(update_fields=['status', 'error_message', 'finished_at'])