""" PX Sources REST API views and viewsets """ from rest_framework import status, viewsets from rest_framework.decorators import action from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response from apps.core.services import AuditService from .models import PXSource from .serializers import ( PXSourceChoiceSerializer, PXSourceDetailSerializer, PXSourceListSerializer, PXSourceSerializer, ) from .permissions import IsAdminUser, IsSourceUserOrAdmin, IsSourceUserOwnData class PXSourceViewSet(viewsets.ModelViewSet): """ ViewSet for PX Sources with full CRUD operations. Permissions: - PX Admins: Full access to all sources - Hospital Admins: Can view and manage sources - Source Users: Read-only access to their own source - Other users: No access """ queryset = PXSource.objects.all() permission_classes = [IsAuthenticated, IsAdminUser] filterset_fields = ["is_active"] search_fields = ["name_en", "name_ar", "description"] ordering_fields = ["name_en", "created_at"] ordering = ["name_en"] def get_serializer_class(self): """Use different serializers based on action""" if self.action == "list": return PXSourceListSerializer elif self.action == "retrieve": return PXSourceDetailSerializer elif self.action == "choices": return PXSourceChoiceSerializer return PXSourceSerializer def get_queryset(self): """Filter sources based on user role""" queryset = super().get_queryset() user = self.request.user # PX Admins see all sources if user.is_px_admin(): return queryset # Hospital Admins see all sources if user.is_hospital_admin(): return queryset # Source users see only their source (handled by IsSourceUserOrAdmin) if hasattr(user, "source_user_profile"): source_user = user.source_user_profile if source_user.is_active: return queryset.filter(id=source_user.source.id) # Default: active sources only return queryset.filter(is_active=True) def perform_create(self, serializer): """Log source creation""" source = serializer.save() AuditService.log_from_request( event_type="px_source_created", description=f"PX Source created: {source.name_en}", request=self.request, content_object=source, ) def perform_update(self, serializer): """Log source update""" source = serializer.save() AuditService.log_from_request( event_type="px_source_updated", description=f"PX Source updated: {source.name_en}", request=self.request, content_object=source, ) def perform_destroy(self, instance): """Log source deletion""" source_name = instance.name_en instance.delete() AuditService.log_from_request( event_type="px_source_deleted", description=f"PX Source deleted: {source_name}", request=self.request ) @action(detail=False, methods=["get"]) def choices(self, request): """ Get source choices for dropdowns. """ queryset = PXSource.get_active_sources() serializer = PXSourceChoiceSerializer(queryset, many=True, context={"request": request}) return Response(serializer.data) @action(detail=True, methods=["post"]) def activate(self, request, pk=None): """Activate a source""" source = self.get_object() source.activate() AuditService.log_from_request( event_type="px_source_activated", description=f"PX Source activated: {source.name_en}", request=self.request, content_object=source, ) return Response({"message": "Source activated successfully", "is_active": True}) @action(detail=True, methods=["post"]) def deactivate(self, request, pk=None): """Deactivate a source""" source = self.get_object() source.deactivate() AuditService.log_from_request( event_type="px_source_deactivated", description=f"PX Source deactivated: {source.name_en}", request=self.request, content_object=source, ) return Response({"message": "Source deactivated successfully", "is_active": False}) @action(detail=True, methods=["get"]) def usage(self, request, pk=None): """Get usage statistics for a source""" source = self.get_object() usage_records = source.usage_records.all().select_related("content_type", "hospital", "user") # Group by content type usage_by_type = {} for record in usage_records: content_type = record.content_type.model if content_type not in usage_by_type: usage_by_type[content_type] = 0 usage_by_type[content_type] += 1 return Response( { "source_id": str(source.id), "source_name": source.name_en, "total_usage": usage_records.count(), "usage_by_type": usage_by_type, "recent_usage": [ { "content_type": r.content_type.model, "object_id": str(r.object_id), "hospital": r.hospital.name if r.hospital else None, "user": r.user.get_full_name() if r.user else None, "created_at": r.created_at, } for r in usage_records[:10] ], } )