Files
backend/api/organization/views.py

118 lines
4.5 KiB
Python

from django.db.models import Sum
from rest_framework import viewsets, status
from rest_framework.permissions import IsAuthenticated
from rest_framework.decorators import api_view, permission_classes, action
from rest_framework.response import Response
from api.record.models import Document
from core.permissions import (
IsSameOrganization,
IsSameOrganizationDeveloper,
IsSameOrganizationAndAdmin,
IsSuperUser,
get_org_context,
is_internal_service_request,
user_has_permission,
)
from .serializers import OrganizacionSerializer, UsoAlmacenamientoSerializer
from .models import Organizacion, UsoAlmacenamiento
from api.customs.models import Pedimento
from api.logger.mixins import LoggingMixin
from mixins.filtrado_organizacion import OrganizacionFiltradaMixin
# Create your views here.
class ViewSetOrganizacion(LoggingMixin, viewsets.ModelViewSet, OrganizacionFiltradaMixin):
"""
ViewSet for Organizacion model.
"""
permission_classes = [IsAuthenticated & (IsSameOrganization | IsSameOrganizationAndAdmin | IsSameOrganizationDeveloper | IsSuperUser)]
queryset = Organizacion.objects.all()
serializer_class = OrganizacionSerializer
filterset_fields = ['nombre']
my_tags = ['Organizaciones']
def get_queryset(self):
user = self.request.user
if not user.is_authenticated:
return Organizacion.objects.none()
if is_internal_service_request(self.request):
return Organizacion.objects.all()
org = get_org_context(user)
if not org:
return Organizacion.objects.none()
# Superuser ve solo su org activa, no todas
return Organizacion.objects.filter(id=org.id)
class UsoAlmacenamientoViewSet(LoggingMixin, viewsets.ReadOnlyModelViewSet):
"""
Vista para consultar el uso de almacenamiento
Solo lectura (GET) ya que la actualización se hace automáticamente
"""
queryset = UsoAlmacenamiento.objects.all()
serializer_class = UsoAlmacenamientoSerializer
permission_classes = [IsAuthenticated & (IsSameOrganization | IsSameOrganizationAndAdmin | IsSameOrganizationDeveloper | IsSuperUser)]
my_tags = ['Uso de Almacenamiento']
def get_queryset(self):
if not self.request.user.is_authenticated:
return UsoAlmacenamiento.objects.none()
if is_internal_service_request(self.request):
return UsoAlmacenamiento.objects.all()
org = get_org_context(self.request.user)
if not org:
return UsoAlmacenamiento.objects.none()
if self.request.user.is_importador:
raise PermissionDenied("Los importadores no tienen acceso al uso de almacenamiento.")
return UsoAlmacenamiento.objects.filter(organizacion=org)
@action(detail=False, methods=['get'])
def mi_organizacion(self, request):
"""Obtiene el uso de almacenamiento de la organización del usuario actual"""
organizacion = get_org_context(request.user)
# Obtener o crear el registro de uso
uso, created = UsoAlmacenamiento.objects.get_or_create(
organizacion=organizacion,
defaults={'espacio_utilizado': 0}
)
# Calcular el total sumando todos los documentos (en bytes)
total_utilizado = Document.objects.filter(
organizacion=organizacion
).aggregate(total=Sum('size'))['total'] or 0
# Sincronizar con el registro de uso (por si hay discrepancias)
if uso.espacio_utilizado != total_utilizado:
uso.espacio_utilizado = total_utilizado
uso.save()
# Calcular métricas adicionales
max_almacenamiento_bytes = organizacion.licencia.almacenamiento * 1024 ** 3
porcentaje = (total_utilizado / max_almacenamiento_bytes * 100) if max_almacenamiento_bytes > 0 else 0
data = {
'organizacion': organizacion.nombre,
'limite_almacenamiento_gb': organizacion.licencia.almacenamiento,
'espacio_utilizado_bytes': total_utilizado,
'espacio_utilizado_gb': total_utilizado / (1024 ** 3),
'espacio_disponible_bytes': max(max_almacenamiento_bytes - total_utilizado, 0),
'porcentaje_utilizado': round(porcentaje, 2),
'total_documentos': Document.objects.filter(organizacion=organizacion).count(),
'total_pedimentos': Pedimento.objects.filter(organizacion=organizacion).count(),
'total_usuarios': organizacion.users.count()
}
return Response(data)