141 lines
6.0 KiB
Python
141 lines
6.0 KiB
Python
from rest_framework.pagination import PageNumberPagination
|
|
from api.customs.models import Pedimento, TipoOperacion, Regimen
|
|
from django.shortcuts import render
|
|
from rest_framework import viewsets
|
|
from rest_framework.permissions import IsAuthenticated
|
|
from rest_framework.decorators import action
|
|
from rest_framework.response import Response
|
|
from django.http import FileResponse, Http404
|
|
import os
|
|
|
|
from .models import DataStage
|
|
from .serializer import DataStageSerializer
|
|
|
|
from api.logger.mixins import LoggingMixin
|
|
from mixins.filtrado_organizacion import OrganizacionFiltradaMixin
|
|
from core.permissions import (
|
|
IsSameOrganization,
|
|
IsSameOrganizationDeveloper,
|
|
IsSameOrganizationAndAdmin,
|
|
IsSuperUser
|
|
)
|
|
# Create your views here.
|
|
class DataStagePagination(PageNumberPagination):
|
|
page_size = 20 # Valor por defecto
|
|
page_size_query_param = 'page_size'
|
|
max_page_size = 1000
|
|
|
|
class DataStageViewSet(LoggingMixin, viewsets.ModelViewSet, OrganizacionFiltradaMixin):
|
|
|
|
|
|
"""
|
|
ViewSet for managing DataStage instances.
|
|
Provides CRUD operations for DataStage.
|
|
"""
|
|
|
|
|
|
serializer_class = DataStageSerializer
|
|
permission_classes = [IsAuthenticated & (IsSameOrganization | IsSameOrganizationAndAdmin | IsSameOrganizationDeveloper | IsSuperUser)]
|
|
model = DataStage
|
|
my_tags = ['DataStage']
|
|
pagination_class = DataStagePagination
|
|
|
|
def get_queryset(self):
|
|
if self.request.user.is_superuser:
|
|
return DataStage.objects.all().order_by('-created_at')
|
|
|
|
if self.request.user.groups.filter(name='developer').exists() or self.request.user.groups.filter(name='admin').exists() or self.request.user.groups.filter(name='Agente Aduanal').exists():
|
|
return DataStage.objects.filter(organizacion=self.request.user.organizacion).order_by('-created_at')
|
|
|
|
return self.get_queryset_filtrado_por_organizacion().order_by('-created_at')
|
|
|
|
def perform_create(self, serializer):
|
|
"""
|
|
Permite que la organización sea opcional en el request, pero si no se envía, se asigna la del usuario autenticado.
|
|
"""
|
|
if not self.request.user.is_authenticated or not hasattr(self.request.user, 'organizacion'):
|
|
raise ValueError("Usuario no autenticado o sin organización")
|
|
|
|
data = serializer.validated_data
|
|
organizacion = data.get('organizacion')
|
|
|
|
if self.request.user.is_superuser:
|
|
# Permitir que el superusuario cree sin organización o la especifique
|
|
serializer.save()
|
|
return
|
|
|
|
if (self.request.user.groups.filter(name='developer').exists() or self.request.user.groups.filter(name='admin').exists() or self.request.user.groups.filter(name='user').exists()) and self.request.user.groups.filter(name='Agente Aduanal').exists():
|
|
if not organizacion:
|
|
serializer.save(organizacion=self.request.user.organizacion)
|
|
else:
|
|
serializer.save()
|
|
return
|
|
|
|
raise ValueError("No cuentas con los permisos necesarios para crear un DataStage")
|
|
|
|
def perform_update(self, serializer):
|
|
"""
|
|
Override to ensure organization is set on update.
|
|
"""
|
|
if not self.request.user.is_authenticated or not hasattr(self.request.user, 'organizacion'):
|
|
raise ValueError("Usuario no autenticado o sin organización")
|
|
|
|
if self.request.user.is_superuser:
|
|
# Allow superuser to update without organization
|
|
serializer.save()
|
|
return
|
|
|
|
if (self.request.user.groups.filter(name='developer').exists() or self.request.user.groups.filter(name='admin').exists() or self.request.user.groups.filter(name='user').exists()) and self.request.user.groups.filter(name='Agente Aduanal').exists():
|
|
serializer.save(organizacion=self.request.user.organizacion)
|
|
return
|
|
|
|
raise ValueError("No cuentas con los permisos necesarios para actualizar un DataStage")
|
|
|
|
@action(detail=True, methods=['get'], url_path='download-datastage', url_name='download-datastage')
|
|
def download_datastage(self, request, pk=None):
|
|
"""
|
|
Endpoint para descargar el archivo asociado a un DataStage.
|
|
"""
|
|
try:
|
|
datastage = self.get_object()
|
|
if not datastage.archivo:
|
|
raise Http404("No hay archivo asociado a este DataStage.")
|
|
file_path = datastage.archivo.path
|
|
if not os.path.exists(file_path):
|
|
raise Http404("El archivo no existe en el servidor.")
|
|
response = FileResponse(open(file_path, 'rb'), as_attachment=True, filename=os.path.basename(file_path))
|
|
return response
|
|
except Exception as e:
|
|
return Response({'detail': str(e)}, status=404)
|
|
|
|
@action(detail=True, methods=['post'], url_path='procesar')
|
|
def procesar(self, request, pk=None):
|
|
"""
|
|
Endpoint para procesar el DataStage de forma asíncrona usando Celery.
|
|
"""
|
|
from api.datastage.tasks import procesar_datastage_task
|
|
datastage = self.get_object()
|
|
user_organizacion = getattr(self.request.user, 'organizacion', None)
|
|
user_organizacion_id = user_organizacion.id if user_organizacion else None
|
|
task = procesar_datastage_task.delay(datastage.id, user_organizacion_id)
|
|
return Response({
|
|
'task_id': task.id,
|
|
'detail': 'Procesamiento iniciado. Puede consultar el estado con el task_id.'
|
|
})
|
|
|
|
@action(detail=False, methods=['get'], url_path='task-status')
|
|
def task_status(self, request):
|
|
"""
|
|
Consulta el estado de una tarea de Celery por task_id.
|
|
"""
|
|
from celery.result import AsyncResult
|
|
task_id = request.query_params.get('task_id')
|
|
if not task_id:
|
|
return Response({'detail': 'Falta el parámetro task_id.'}, status=400)
|
|
result = AsyncResult(task_id)
|
|
return Response({
|
|
'task_id': task_id,
|
|
'status': result.status,
|
|
'result': result.result if result.successful() else None
|
|
})
|