agdar/core/api_views.py
2025-11-02 14:35:35 +03:00

240 lines
7.8 KiB
Python

"""
DRF API ViewSets for Core app.
"""
from rest_framework import viewsets, filters, status
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from django_filters.rest_framework import DjangoFilterBackend
from django.db.models import Q
from .models import Patient, Clinic, File, SubFile, Consent, Attachment, AuditLog
from .serializers import (
PatientListSerializer, PatientDetailSerializer, PatientCreateUpdateSerializer,
ClinicSerializer, FileSerializer, SubFileSerializer,
ConsentSerializer, AttachmentSerializer, AuditLogSerializer
)
class PatientViewSet(viewsets.ModelViewSet):
"""
API endpoint for Patient CRUD operations.
list: Get list of patients (with search and filters)
retrieve: Get patient details
create: Create new patient
update: Update patient
partial_update: Partially update patient
destroy: Soft delete patient
"""
permission_classes = [IsAuthenticated]
filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
filterset_fields = ['gender', 'is_active']
search_fields = ['mrn', 'first_name_en', 'last_name_en', 'first_name_ar', 'last_name_ar', 'phone']
ordering_fields = ['created_at', 'mrn', 'first_name_en']
ordering = ['-created_at']
def get_queryset(self):
"""Filter by tenant."""
return Patient.objects.filter(tenant=self.request.user.tenant)
def get_serializer_class(self):
"""Return appropriate serializer based on action."""
if self.action == 'list':
return PatientListSerializer
elif self.action in ['create', 'update', 'partial_update']:
return PatientCreateUpdateSerializer
return PatientDetailSerializer
def perform_create(self, serializer):
"""Set tenant on create."""
serializer.save(tenant=self.request.user.tenant)
def perform_destroy(self, instance):
"""Soft delete instead of hard delete."""
instance.is_active = False
instance.save()
@action(detail=True, methods=['get'])
def files(self, request, pk=None):
"""Get patient's files."""
patient = self.get_object()
files = File.objects.filter(patient=patient)
serializer = FileSerializer(files, many=True)
return Response(serializer.data)
@action(detail=True, methods=['get'])
def consents(self, request, pk=None):
"""Get patient's consents."""
patient = self.get_object()
consents = Consent.objects.filter(patient=patient)
serializer = ConsentSerializer(consents, many=True)
return Response(serializer.data)
@action(detail=True, methods=['get'])
def audit_trail(self, request, pk=None):
"""Get patient's audit trail."""
patient = self.get_object()
logs = AuditLog.objects.filter(
model_name='Patient',
object_id=str(patient.id)
).order_by('-timestamp')
serializer = AuditLogSerializer(logs, many=True)
return Response(serializer.data)
class ClinicViewSet(viewsets.ReadOnlyModelViewSet):
"""
API endpoint for Clinic (read-only).
list: Get list of clinics
retrieve: Get clinic details
"""
permission_classes = [IsAuthenticated]
serializer_class = ClinicSerializer
filter_backends = [DjangoFilterBackend, filters.SearchFilter]
filterset_fields = ['specialty', 'is_active']
search_fields = ['name_en', 'name_ar']
def get_queryset(self):
"""Filter by tenant."""
return Clinic.objects.filter(tenant=self.request.user.tenant, is_active=True)
class FileViewSet(viewsets.ReadOnlyModelViewSet):
"""
API endpoint for File (read-only).
list: Get list of files
retrieve: Get file details
"""
permission_classes = [IsAuthenticated]
serializer_class = FileSerializer
filter_backends = [DjangoFilterBackend, filters.SearchFilter]
filterset_fields = ['patient', 'is_active']
search_fields = ['file_number', 'patient__mrn']
def get_queryset(self):
"""Filter by tenant."""
return File.objects.filter(tenant=self.request.user.tenant)
@action(detail=True, methods=['get'])
def subfiles(self, request, pk=None):
"""Get file's subfiles."""
file = self.get_object()
subfiles = SubFile.objects.filter(file=file)
serializer = SubFileSerializer(subfiles, many=True)
return Response(serializer.data)
class SubFileViewSet(viewsets.ReadOnlyModelViewSet):
"""
API endpoint for SubFile (read-only).
list: Get list of subfiles
retrieve: Get subfile details
"""
permission_classes = [IsAuthenticated]
serializer_class = SubFileSerializer
filter_backends = [DjangoFilterBackend, filters.SearchFilter]
filterset_fields = ['file', 'clinic', 'is_active']
search_fields = ['subfile_number']
def get_queryset(self):
"""Filter by tenant."""
return SubFile.objects.filter(tenant=self.request.user.tenant)
class ConsentViewSet(viewsets.ModelViewSet):
"""
API endpoint for Consent CRUD operations.
list: Get list of consents
retrieve: Get consent details
create: Create new consent
update: Update consent
destroy: Delete consent
"""
permission_classes = [IsAuthenticated]
serializer_class = ConsentSerializer
filter_backends = [DjangoFilterBackend, filters.SearchFilter]
filterset_fields = ['patient', 'consent_type', 'is_valid']
search_fields = ['patient__mrn', 'patient__first_name_en']
def get_queryset(self):
"""Filter by tenant."""
return Consent.objects.filter(tenant=self.request.user.tenant)
def perform_create(self, serializer):
"""Set tenant and signed_by on create."""
serializer.save(
tenant=self.request.user.tenant,
signed_by=self.request.user
)
@action(detail=True, methods=['post'])
def verify(self, request, pk=None):
"""Verify consent signature."""
consent = self.get_object()
# Add signature verification logic here
return Response({
'verified': True,
'signed_by': consent.signed_by.get_full_name(),
'signed_at': consent.signed_at
})
class AttachmentViewSet(viewsets.ModelViewSet):
"""
API endpoint for Attachment CRUD operations.
list: Get list of attachments
retrieve: Get attachment details
create: Upload new attachment
destroy: Delete attachment
"""
permission_classes = [IsAuthenticated]
serializer_class = AttachmentSerializer
filter_backends = [DjangoFilterBackend, filters.SearchFilter]
filterset_fields = ['category']
search_fields = ['title', 'description']
def get_queryset(self):
"""Filter by tenant."""
return Attachment.objects.filter(tenant=self.request.user.tenant)
def perform_create(self, serializer):
"""Set tenant and uploaded_by on create."""
serializer.save(
tenant=self.request.user.tenant,
uploaded_by=self.request.user
)
class AuditLogViewSet(viewsets.ReadOnlyModelViewSet):
"""
API endpoint for AuditLog (read-only).
list: Get list of audit logs
retrieve: Get audit log details
"""
permission_classes = [IsAuthenticated]
serializer_class = AuditLogSerializer
filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
filterset_fields = ['user', 'action', 'model_name']
search_fields = ['object_repr', 'model_name']
ordering_fields = ['timestamp']
ordering = ['-timestamp']
def get_queryset(self):
"""Filter by tenant."""
return AuditLog.objects.filter(tenant=self.request.user.tenant)