85 lines
3.3 KiB
Python
85 lines
3.3 KiB
Python
from django.shortcuts import get_object_or_404
|
|
from drf_spectacular.utils import OpenApiResponse, extend_schema
|
|
from rest_framework import viewsets
|
|
from rest_framework.exceptions import PermissionDenied
|
|
from rest_framework.generics import ListAPIView
|
|
from rest_framework.permissions import IsAuthenticated
|
|
|
|
from apps.announcements.models import Announcement
|
|
from apps.courses.api.permissions import IsCourseOwner, IsTeacher
|
|
from apps.courses.models import Course, CourseStatus
|
|
from apps.enrollments.api.permissions import IsStudent
|
|
from apps.enrollments.models import Enrollment
|
|
|
|
from .serializers import AnnouncementSerializer, AnnouncementWriteSerializer
|
|
|
|
|
|
@extend_schema(tags=["announcements"])
|
|
class InstructorAnnouncementViewSet(viewsets.ModelViewSet):
|
|
"""Instructor CRUD over announcements on their own courses."""
|
|
|
|
permission_classes = [IsAuthenticated, IsTeacher, IsCourseOwner]
|
|
queryset = Announcement.objects.all().select_related("course", "posted_by")
|
|
filterset_fields = ["course"]
|
|
ordering = ["-created_at"]
|
|
|
|
def get_queryset(self):
|
|
return super().get_queryset().filter(course__instructor=self.request.user)
|
|
|
|
def get_serializer_class(self):
|
|
if self.action in {"create", "update", "partial_update"}:
|
|
return AnnouncementWriteSerializer
|
|
return AnnouncementSerializer
|
|
|
|
def perform_create(self, serializer):
|
|
course = serializer.validated_data["course"]
|
|
if course.instructor_id != self.request.user.id:
|
|
raise PermissionDenied("You don't own this course.")
|
|
announcement = serializer.save(posted_by=self.request.user)
|
|
# Record activity event for the instructor's home feed
|
|
from apps.enrollments.models import ActivityKind
|
|
from apps.enrollments.services.events import record_event
|
|
|
|
record_event(
|
|
course=course,
|
|
actor=self.request.user,
|
|
kind=ActivityKind.ANNOUNCEMENT_POSTED.value,
|
|
payload={
|
|
"announcement_id": announcement.pk,
|
|
"preview": (announcement.body or "")[:120],
|
|
},
|
|
)
|
|
|
|
|
|
class MyCourseAnnouncementsView(ListAPIView):
|
|
"""Student-facing list: announcements for a specific course the student is enrolled in."""
|
|
|
|
permission_classes = [IsAuthenticated, IsStudent]
|
|
serializer_class = AnnouncementSerializer
|
|
pagination_class = None
|
|
|
|
@extend_schema(
|
|
tags=["announcements"],
|
|
summary="My course announcements",
|
|
description="Lists all announcements posted by the instructor on a course the student is enrolled in.",
|
|
responses={
|
|
200: AnnouncementSerializer(many=True),
|
|
403: OpenApiResponse(description="Not enrolled."),
|
|
404: OpenApiResponse(description="Course not found or not published."),
|
|
},
|
|
)
|
|
def get(self, request, *args, **kwargs):
|
|
return super().get(request, *args, **kwargs)
|
|
|
|
def get_queryset(self):
|
|
slug = self.kwargs["slug"]
|
|
course = get_object_or_404(Course, slug=slug, status=CourseStatus.PUBLISHED)
|
|
if not Enrollment.objects.filter(student=self.request.user, course=course).exists():
|
|
raise PermissionDenied("You are not enrolled in this course.")
|
|
return (
|
|
Announcement.objects
|
|
.filter(course=course)
|
|
.select_related("posted_by")
|
|
.order_by("-created_at")
|
|
)
|