from rest_framework import viewsets, permissions, status, filters from rest_framework.decorators import action from rest_framework.response import Response from django.db.models import Q from .models import FeaturedService from .serializers import ( FeaturedServiceSerializer, FeaturedServiceCreateSerializer, FeaturedServiceUpdateSerializer, FeaturedServiceReviewSerializer, FeaturedServiceListSerializer ) class FeaturedServiceViewSet(viewsets.ModelViewSet): """ViewSet for FeaturedService model.""" permission_classes = [permissions.IsAuthenticatedOrReadOnly] filter_backends = [filters.SearchFilter, filters.OrderingFilter, filters.DjangoFilterBackend] search_fields = ['name', 'description'] filterset_fields = ['category', 'region', 'publish_status'] ordering_fields = ['created_at', 'updated_at', 'published_at'] ordering = ['-created_at'] def get_queryset(self): queryset = FeaturedService.objects.select_related('submitter', 'region', 'moderator_reviewer') # Only show published services to non-authenticated users if not self.request.user.is_authenticated: return queryset.filter(publish_status='published') # Show all for admins if self.request.user.is_admin(): return queryset # Show own services + published services for regular users return queryset.filter( Q(submitter=self.request.user) | Q(publish_status='published') ).distinct() def get_serializer_class(self): if self.action == 'create': return FeaturedServiceCreateSerializer elif self.action in ['update', 'partial_update']: return FeaturedServiceUpdateSerializer elif self.action == 'list': return FeaturedServiceListSerializer elif self.action in ['approve', 'reject', 'submit']: return FeaturedServiceReviewSerializer return FeaturedServiceSerializer def perform_create(self, serializer): serializer.save(submitter=self.request.user) def perform_update(self, serializer): # Only allow updating own services or by admin if (not self.request.user.is_admin() and str(serializer.instance.submitter.id) != str(self.request.user.id)): from rest_framework.exceptions import PermissionDenied raise PermissionDenied("You can only update your own services") serializer.save() def perform_destroy(self, instance): # Only allow deleting own services or by admin if (not self.request.user.is_admin() and str(instance.submitter.id) != str(self.request.user.id)): from rest_framework.exceptions import PermissionDenied raise PermissionDenied("You can only delete your own services") instance.delete() @action(detail=True, methods=['post']) def submit(self, request, pk=None): """Submit service for review.""" service = self.get_object() if service.submitter != request.user: return Response( {'detail': 'You can only submit your own services'}, status=status.HTTP_403_FORBIDDEN ) service.submit_for_review() return Response({'message': 'Service submitted for review'}) @action(detail=True, methods=['post']) def approve(self, request, pk=None): """Approve service (moderator only).""" service = self.get_object() serializer = self.get_serializer(data=request.data) if not serializer.is_valid(): return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) if not request.user.is_moderator(): return Response( {'detail': 'Only moderators can approve services'}, status=status.HTTP_403_FORBIDDEN ) # Check if moderator has permission for this region from apps.moderation.models import ModeratorPermission has_permission = ModeratorPermission.objects.filter( moderator=request.user, region=service.region, status='active' ).exists() if not has_permission: return Response( {'detail': 'You do not have permission to approve services in this region'}, status=status.HTTP_403_FORBIDDEN ) service.approve_moderator( reviewer=request.user, reason=serializer.validated_data.get('reason', '') ) return Response({'message': 'Service approved'}) @action(detail=True, methods=['post']) def reject(self, request, pk=None): """Reject service (moderator only).""" service = self.get_object() serializer = self.get_serializer(data=request.data) if not serializer.is_valid(): return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) if not request.user.is_moderator(): return Response( {'detail': 'Only moderators can reject services'}, status=status.HTTP_403_FORBIDDEN ) # Check if moderator has permission for this region from apps.moderation.models import ModeratorPermission has_permission = ModeratorPermission.objects.filter( moderator=request.user, region=service.region, status='active' ).exists() if not has_permission: return Response( {'detail': 'You do not have permission to reject services in this region'}, status=status.HTTP_403_FORBIDDEN ) service.reject_moderator( reviewer=request.user, reason=serializer.validated_data.get('reason', 'Required reason') ) return Response({'message': 'Service rejected'}) @action(detail=True, methods=['get']) def comments(self, request, pk=None): """Get comments for a service.""" service = self.get_object() from apps.interactions.serializers import CommentSerializer from apps.interactions.models import Comment comments = Comment.objects.filter( target_type='service', target_id=service.id, ai_status='approved' ) serializer = CommentSerializer(comments, many=True) return Response(serializer.data) @action(detail=True, methods=['post']) def like(self, request, pk=None): """Like or unlike a service.""" service = self.get_object() from apps.interactions.models import Like like, created = Like.objects.get_or_create( user=request.user, target_type='service', target_id=service.id ) if not created: like.delete() return Response({'message': 'Unliked', 'liked': False}) return Response({'message': 'Liked', 'liked': True}) @action(detail=True, methods=['post']) def rate(self, request, pk=None): """Rate a service.""" service = self.get_object() from apps.interactions.serializers import RatingCreateSerializer serializer = RatingCreateSerializer(data=request.data) if serializer.is_valid(): serializer.save(target_type='service', target_id=service.id) return Response({'message': 'Rating saved'}) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) @action(detail=True, methods=['get']) def stats(self, request, pk=None): """Get service statistics.""" service = self.get_object() from apps.interactions.models import Like, Comment, Rating likes_count = Like.objects.filter( target_type='service', target_id=service.id ).count() comments_count = Comment.objects.filter( target_type='service', target_id=service.id, ai_status='approved' ).count() ratings = Rating.objects.filter( target_type='service', target_id=service.id ) avg_rating = ratings.aggregate(avg=models.Avg('score'))['avg'] or 0 return Response({ 'likes_count': likes_count, 'comments_count': comments_count, 'avg_rating': round(avg_rating, 1), 'ratings_count': ratings.count(), })