From 64cf932b9c8e312bef35f19f735bff5a65986f32 Mon Sep 17 00:00:00 2001 From: Akanshu-2u Date: Fri, 2 Jan 2026 12:39:57 +0000 Subject: [PATCH 1/2] fix: handle missing CourseOverview during manual enrollment retirement --- common/djangoapps/student/models/course_enrollment.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/common/djangoapps/student/models/course_enrollment.py b/common/djangoapps/student/models/course_enrollment.py index 0673495f0ec3..606f202f1c41 100644 --- a/common/djangoapps/student/models/course_enrollment.py +++ b/common/djangoapps/student/models/course_enrollment.py @@ -1581,7 +1581,14 @@ def retire_manual_enrollments(cls, user, retired_email): return False for manual_enrollment_audit in manual_enrollment_audits: - manual_enrollment_audit.history.update(reason="", enrolled_email=retired_email) + try: + manual_enrollment_audit.history.update(reason="", enrolled_email=retired_email) + except CourseOverview.DoesNotExist: + # Course overview no longer exists, skip historical update but continue retirement + log.warning( + f"CourseOverview missing for enrollment during retirement, skipping historical update " + f"for audit {manual_enrollment_audit.id}" + ) manual_enrollment_audits.update(reason="", enrolled_email=retired_email) return True From 3e37fc3c30b2469d8c3c9cf6062f73f056ad281f Mon Sep 17 00:00:00 2001 From: Akanshu-2u Date: Fri, 2 Jan 2026 18:41:19 +0000 Subject: [PATCH 2/2] fix: added tests and removed comment --- .../student/models/course_enrollment.py | 1 - .../djangoapps/student/tests/test_models.py | 24 +++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/common/djangoapps/student/models/course_enrollment.py b/common/djangoapps/student/models/course_enrollment.py index 606f202f1c41..6318e53d4145 100644 --- a/common/djangoapps/student/models/course_enrollment.py +++ b/common/djangoapps/student/models/course_enrollment.py @@ -1584,7 +1584,6 @@ def retire_manual_enrollments(cls, user, retired_email): try: manual_enrollment_audit.history.update(reason="", enrolled_email=retired_email) except CourseOverview.DoesNotExist: - # Course overview no longer exists, skip historical update but continue retirement log.warning( f"CourseOverview missing for enrollment during retirement, skipping historical update " f"for audit {manual_enrollment_audit.id}" diff --git a/common/djangoapps/student/tests/test_models.py b/common/djangoapps/student/tests/test_models.py index 02df1a6714c6..161885d728d9 100644 --- a/common/djangoapps/student/tests/test_models.py +++ b/common/djangoapps/student/tests/test_models.py @@ -723,6 +723,30 @@ def test_retirement(self): assert not ManualEnrollmentAudit.objects.filter(enrollment=enrollment).exclude(enrolled_email='xxx') assert not ManualEnrollmentAudit.objects.filter(enrollment=enrollment).exclude(reason='') + def test_retirement_with_missing_course_overview(self): + """ + Tests that retirement succeeds gracefully when CourseOverview is missing, + skipping historical updates but still updating current records. + """ + enrollment = CourseEnrollment.enroll(self.user, self.course.id) + ManualEnrollmentAudit.create_manual_enrollment_audit( + self.instructor, self.user.email, ALLOWEDTOENROLL_TO_ENROLLED, + 'test enrollment with missing overview', enrollment + ) + + # Delete the CourseOverview to simulate the missing overview scenario + CourseOverview.objects.filter(id=self.course.id).delete() + + # Retirement should complete successfully without raising CourseOverview.DoesNotExist + ManualEnrollmentAudit.retire_manual_enrollments(user=self.user, retired_email="retired@test.com") + + # Verify the main audit records were still updated despite missing CourseOverview + assert ManualEnrollmentAudit.objects.filter(enrollment=enrollment).exists() + assert not ManualEnrollmentAudit.objects.filter(enrollment=enrollment).exclude( + enrolled_email='retired@test.com' + ) + assert not ManualEnrollmentAudit.objects.filter(enrollment=enrollment).exclude(reason='') + class TestAccountRecovery(TestCase): """