diff --git a/FusionIIIT/applications/examination/api/views.py b/FusionIIIT/applications/examination/api/views.py index 36c9ea863..4c05c683d 100644 --- a/FusionIIIT/applications/examination/api/views.py +++ b/FusionIIIT/applications/examination/api/views.py @@ -227,6 +227,19 @@ def parse_academic_year(academic_year, semester_type): session = academic_year # Use the complete academic year string as session. return working_year, session +def course_instructor_year(academic_year, semester_type): + """ + Year used by CourseInstructor rows for a given academic year + semester type. + CourseInstructor stores Odd/Summer under the start year and Even under the end + year (see CourseInstructor.academic_year). This differs from parse_academic_year, + which keys Summer on the end year to match Student_grades — so use this helper + (not working_year) whenever filtering CourseInstructor by year. + """ + if semester_type == "Summer Semester": + return int(academic_year.split("-")[0].strip()) + working_year, _ = parse_academic_year(academic_year, semester_type) + return working_year + def is_valid_grade(grade: str, course_code: str) -> bool: """ Returns True if the grade is valid for the given course code. @@ -1729,7 +1742,8 @@ def post(self, request): working_year, _ = parse_academic_year(academic_year=academic_year, semester_type=semester_type) - if user_holds_role(request.user, "acadadmin"): + acting_as_acadadmin = role == "acadadmin" and user_holds_role(request.user, "acadadmin") + if acting_as_acadadmin: course_ids = ( course_registration.objects .filter(session=academic_year, semester_type=semester_type) @@ -1740,7 +1754,7 @@ def post(self, request): else: unique_course_ids = ( CourseInstructor.objects - .filter(instructor_id_id=request.user.username, year=working_year, semester_type=semester_type) + .filter(instructor_id_id=request.user.username, year=course_instructor_year(academic_year, semester_type), semester_type=semester_type) .values("course_id_id") .distinct() .annotate(course_id_int=Cast("course_id_id", IntegerField())) @@ -1966,10 +1980,11 @@ def post(self, request): ) # 8) INSTRUCTOR‐OWNERSHIP CHECK (acadadmin may submit for any course) - if not user_holds_role(request.user, "acadadmin") and not CourseInstructor.objects.filter( + acting_as_acadadmin = role == "acadadmin" and user_holds_role(request.user, "acadadmin") + if not acting_as_acadadmin and not CourseInstructor.objects.filter( course_id_id=course_id, instructor_id_id=request.user.username, - year=working_year + year=course_instructor_year(academic_year, semester_type) ).exists(): return Response( {"error": "Access denied: you are not assigned as instructor for this course."}, @@ -2125,7 +2140,7 @@ def post(self, request): unique_course_ids = ( CourseInstructor.objects - .filter(instructor_id_id=instructor_id, year=working_year, semester_type=semester_type) + .filter(instructor_id_id=instructor_id, year=course_instructor_year(academic_year, semester_type), semester_type=semester_type) .values("course_id_id") .distinct() .annotate(course_id_int=Cast("course_id_id", IntegerField())) @@ -2219,13 +2234,13 @@ def post(self, request): if user_holds_role(request.user, "acadadmin"): ci = CourseInstructor.objects.filter( course_id_id=course_id, - year=working_year, + year=course_instructor_year(academic_year, semester_type), semester_type=semester_type, ) else: ci = CourseInstructor.objects.filter( course_id_id=course_id, - year=working_year, + year=course_instructor_year(academic_year, semester_type), semester_type=semester_type, instructor_id_id=request.user.username ) @@ -3539,7 +3554,7 @@ def post(self, request): instructors_map = {} instructors = CourseInstructor.objects.filter( course_id__in=course_ids, - year=working_year, + year=course_instructor_year(academic_year, semester_type), semester_type=semester_type ).select_related()