Skip to content

Commit 84e3acf

Browse files
feat: delete CourseRun/CatalogCourse when deleting a course
1 parent c569920 commit 84e3acf

2 files changed

Lines changed: 53 additions & 1 deletion

File tree

openedx/core/djangoapps/content/course_overviews/signals.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,16 @@ def _listen_for_course_delete(sender, course_key, **kwargs): # pylint: disable=
104104
sender=None,
105105
courserun_key=courserun_key,
106106
)
107+
# Delete the openedx_catalog CourseRun to keep it in sync:
108+
try:
109+
course_run_obj = catalog_api.get_course_run(course_key)
110+
except CourseRun.DoesNotExist:
111+
pass
112+
else:
113+
catalog_course = course_run_obj.catalog_course
114+
catalog_api.delete_course_run(course_key)
115+
if catalog_course.runs.count() == 0:
116+
catalog_api.delete_catalog_course(catalog_course)
107117

108118

109119
@receiver(post_save, sender=CourseOverview)

openedx/core/djangoapps/content/course_overviews/tests/test_sync_with_openedx_catalog.py

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22
Test that changes to courses get synced into the new openedx_catalog models.
33
"""
44

5+
import pytest
6+
57
from openedx_catalog import api as catalog_api
8+
from openedx_catalog.models_api import CatalogCourse, CourseRun
69

710
from cms.djangoapps.contentstore.views.course import rerun_course
811
from xmodule.modulestore import ModuleStoreEnum
@@ -20,7 +23,7 @@ class CourseOverviewSyncTestCase(ImmediateOnCommitMixin, ModuleStoreTestCase):
2023
"""
2124

2225
MODULESTORE = TEST_DATA_ONLY_SPLIT_MODULESTORE_DRAFT_PREFERRED
23-
ENABLED_SIGNALS = ["course_published"]
26+
ENABLED_SIGNALS = ["course_deleted", "course_published"]
2427

2528
def test_courserun_creation(self) -> None:
2629
"""
@@ -144,3 +147,42 @@ def test_courserun_of_many_sync(self) -> None:
144147
# Changing the language of the second run doesn't affect the lanugage of the overall catalog course (since the
145148
# first run is still in English)
146149
assert new_run.catalog_course.language_short == "en"
150+
151+
def test_courserun_deletion(self) -> None:
152+
"""
153+
Tests that when a course run is deleted, the corresponding CourseRun is
154+
deleted, and when it's the last run, the CatalogCourse is deleted too.
155+
"""
156+
# Create a course with two runs:
157+
course = CourseFactory.create(display_name="Intro to Testing", emit_signals=True)
158+
course_id1 = course.location.context_key
159+
run1 = catalog_api.get_course_run(course_id1)
160+
# re-run the course:
161+
course_id2 = rerun_course(
162+
self.user,
163+
source_course_key=course_id1,
164+
org=course_id1.org,
165+
number=course_id1.course,
166+
run="run2",
167+
fields={"display_name": "ItT run2"},
168+
background=False,
169+
)
170+
run2 = catalog_api.get_course_run(course_id2)
171+
catalog_course = run1.catalog_course
172+
assert catalog_course == run2.catalog_course # Same for run1 and run2
173+
174+
self.store.delete_course(course_id1, ModuleStoreEnum.UserID.test)
175+
with pytest.raises(CourseRun.DoesNotExist):
176+
run1.refresh_from_db()
177+
178+
# run2 should still exist:
179+
run2.refresh_from_db()
180+
assert run2.catalog_course.display_name == "Intro to Testing" # The catalog course still exists and works
181+
182+
# delete run 2:
183+
self.store.delete_course(course_id2, ModuleStoreEnum.UserID.test)
184+
with pytest.raises(CourseRun.DoesNotExist):
185+
run2.refresh_from_db()
186+
# With no runs left, the CatalogCourse also gets auto-deleted:
187+
with pytest.raises(CatalogCourse.DoesNotExist):
188+
catalog_course.refresh_from_db()

0 commit comments

Comments
 (0)