From 1105d706f55a6450e74c9d672292ea6d986cd9ba Mon Sep 17 00:00:00 2001 From: mohsentaba Date: Sun, 31 May 2026 13:01:56 +0330 Subject: [PATCH] multiple lesson completion handled --- apps/course/views/lesson.py | 93 ++++++++++++++++++++++++++----------- 1 file changed, 66 insertions(+), 27 deletions(-) diff --git a/apps/course/views/lesson.py b/apps/course/views/lesson.py index 0a2a068..13d29fa 100644 --- a/apps/course/views/lesson.py +++ b/apps/course/views/lesson.py @@ -129,54 +129,93 @@ class LessonCompletionToggleAPIView(GenericAPIView): authentication_classes = [TokenAuthentication] @swagger_auto_schema( - operation_description="Toggle lesson completion status (Check/Uncheck)", + operation_description="Toggle lesson completion status (for single ID) or mark multiple lessons as completed (for list of IDs)", tags=["Imam-Javad - Course"], request_body=openapi.Schema( type=openapi.TYPE_OBJECT, required=['lesson_id'], properties={ - 'lesson_id': openapi.Schema(type=openapi.TYPE_INTEGER, description='ID of the lesson to toggle'), + 'lesson_id': openapi.Schema( + type=openapi.TYPE_INTEGER, + description='ID of the lesson to toggle (integer), or list of IDs to mark completed (array of integers)' + ), }, ), responses={ 201: 'Lesson marked as COMPLETED.', - 200: 'Lesson marked as INCOMPLETE (Unchecked).', - 400: 'Lesson ID is required.', + 200: 'Lesson marked as INCOMPLETE (Unchecked) or Bulk operation completed.', + 400: 'Lesson ID is required or invalid.', 404: 'Lesson not found.', } ) def post(self, request): student = request.user - lesson_id = request.data.get('lesson_id') + lesson_id_data = request.data.get('lesson_id') - if not lesson_id: + if not lesson_id_data: return Response({'error': 'Lesson ID is required.'}, status=status.HTTP_400_BAD_REQUEST) - try: - course_lesson = CourseLesson.objects.get(id=lesson_id) - except CourseLesson.DoesNotExist: - return Response({'error': 'Lesson not found.'}, status=status.HTTP_404_NOT_FOUND) - - # TOGGLE LOGIC - # Try to find an existing completion record - completion = LessonCompletion.objects.filter(student=student, course_lesson=course_lesson).first() - - if completion: - # Scenario: The user clicked by mistake or wants to un-check - # Action: Delete the record - completion.delete() + # List Case: + if isinstance(lesson_id_data, list): + try: + lesson_ids = [int(lid) for lid in lesson_id_data] + except (ValueError, TypeError): + return Response({'error': 'Invalid lesson ID in list.'}, status=status.HTTP_400_BAD_REQUEST) + + course_lessons = CourseLesson.objects.filter(id__in=lesson_ids) + found_ids = set(course_lessons.values_list('id', flat=True)) + + existing_completions = LessonCompletion.objects.filter( + student=student, + course_lesson_id__in=found_ids + ).values_list('course_lesson_id', flat=True) + existing_completed_set = set(existing_completions) + + completions_to_create = [] + for cl in course_lessons: + if cl.id not in existing_completed_set: + completions_to_create.append( + LessonCompletion(student=student, course_lesson=cl) + ) + + if completions_to_create: + LessonCompletion.objects.bulk_create(completions_to_create) + return Response( - {'message': 'Lesson marked as incomplete.', 'is_completed': False}, + { + 'message': f'Completed {len(completions_to_create)} new lessons.', + 'completed_ids': list(found_ids) + }, status=status.HTTP_200_OK ) + + # Single Integer Case: else: - # Scenario: The lesson is not finished yet - # Action: Create the record - LessonCompletion.objects.create(student=student, course_lesson=course_lesson) - return Response( - {'message': 'Lesson completed successfully.', 'is_completed': True}, - status=status.HTTP_201_CREATED - ) + try: + lesson_id = int(lesson_id_data) + except (ValueError, TypeError): + return Response({'error': 'Invalid lesson ID.'}, status=status.HTTP_400_BAD_REQUEST) + + try: + course_lesson = CourseLesson.objects.get(id=lesson_id) + except CourseLesson.DoesNotExist: + return Response({'error': 'Lesson not found.'}, status=status.HTTP_404_NOT_FOUND) + + # TOGGLE LOGIC + completion = LessonCompletion.objects.filter(student=student, course_lesson=course_lesson).first() + + if completion: + completion.delete() + return Response( + {'message': 'Lesson marked as incomplete.', 'is_completed': False}, + status=status.HTTP_200_OK + ) + else: + LessonCompletion.objects.create(student=student, course_lesson=course_lesson) + return Response( + {'message': 'Lesson completed successfully.', 'is_completed': True}, + status=status.HTTP_201_CREATED + ) from django.db.models import Prefetch class LessonListV2APIView(ListAPIView):