diff --git a/openedx/core/djangoapps/course_groups/models.py b/openedx/core/djangoapps/course_groups/models.py index ab710518cd..e3d40a8ba3 100644 --- a/openedx/core/djangoapps/course_groups/models.py +++ b/openedx/core/djangoapps/course_groups/models.py @@ -10,9 +10,11 @@ from django.core.exceptions import ValidationError from django.db import models, transaction from django.db.models.signals import pre_delete from django.dispatch import receiver -from opaque_keys.edx.django.models import CourseKeyField from util.db import outer_atomic +from opaque_keys.edx.django.models import CourseKeyField +from openedx.core.djangolib.model_mixins import DeletableByUserValue + log = logging.getLogger(__name__) @@ -183,7 +185,6 @@ class CourseCohortsSettings(models.Model): # Note that although a default value is specified here for always_cohort_inline_discussions (False), # in reality the default value at the time that cohorting is enabled for a course comes from # course_module.always_cohort_inline_discussions (via `migrate_cohort_settings`). - # pylint: disable=invalid-name # DEPRECATED-- DO NOT USE: Instead use `CourseDiscussionSettings.always_divide_inline_discussions` # via `get_course_discussion_settings` or `set_course_discussion_settings`. always_cohort_inline_discussions = models.BooleanField(default=False) @@ -237,8 +238,11 @@ class CourseCohort(models.Model): return course_cohort -class UnregisteredLearnerCohortAssignments(models.Model): - +class UnregisteredLearnerCohortAssignments(DeletableByUserValue, models.Model): + """ + Tracks the assignment of an unregistered learner to a course's cohort. + """ + #pylint: disable=model-missing-unicode class Meta(object): unique_together = (('course_id', 'email'), ) diff --git a/openedx/core/djangoapps/course_groups/tests/test_cohorts.py b/openedx/core/djangoapps/course_groups/tests/test_cohorts.py index 5eb8084ad3..ec57fe39e1 100644 --- a/openedx/core/djangoapps/course_groups/tests/test_cohorts.py +++ b/openedx/core/djangoapps/course_groups/tests/test_cohorts.py @@ -11,6 +11,7 @@ from django.contrib.auth.models import User from django.db import IntegrityError from django.http import Http404 from django.test import TestCase +from opaque_keys.edx.keys import CourseKey from opaque_keys.edx.locator import CourseLocator from six import text_type @@ -21,7 +22,10 @@ from xmodule.modulestore.tests.django_utils import TEST_DATA_MIXED_MODULESTORE, from xmodule.modulestore.tests.factories import ToyCourseFactory from .. import cohorts -from ..models import CourseCohort, CourseUserGroup, CourseUserGroupPartitionGroup +from ..models import ( + CourseCohort, CourseUserGroup, CourseUserGroupPartitionGroup, + UnregisteredLearnerCohortAssignments +) from ..tests.helpers import CohortFactory, CourseCohortFactory, config_course_cohorts, config_course_cohorts_legacy @@ -267,7 +271,7 @@ class TestCohorts(ModuleStoreTestCase): """ course = modulestore().get_course(self.toy_course_key) cohort = CohortFactory(course_id=course.id, name="TestCohort", users=[]) - cohort2 = CohortFactory(course_id=course.id, name="RandomCohort", users=[]) + CohortFactory(course_id=course.id, name="RandomCohort", users=[]) config_course_cohorts(course, is_cohorted=True) # Add email address to the cohort @@ -873,3 +877,47 @@ class TestCohortsAndPartitionGroups(ModuleStoreTestCase): CourseUserGroupPartitionGroup.objects.get( course_user_group_id=self.first_cohort.id ) + + +class TestUnregisteredLearnerCohortAssignments(TestCase): + """ + Tests the UnregisteredLearnerCohortAssignment.retire_user method. + """ + + def setUp(self): + super(TestUnregisteredLearnerCohortAssignments, self).setUp() + self.course_key = CourseKey.from_string('course-v1:edX+DemoX+Demo_Course') + self.cohort = CourseUserGroup.objects.create( + name="TestCohort", + course_id=self.course_key, + group_type=CourseUserGroup.COHORT + ) + self.cohort_assignment = UnregisteredLearnerCohortAssignments.objects.create( + course_user_group=self.cohort, + course_id=self.course_key, + email='learner@example.com' + ) + + def test_retired_user_has_deleted_record(self): + was_retired = UnregisteredLearnerCohortAssignments.delete_by_user_value( + value='learner@example.com', + field='email' + ) + + self.assertTrue(was_retired) + + search_retired_user_results = \ + UnregisteredLearnerCohortAssignments.objects.filter( + email=self.cohort_assignment.email + ) + self.assertFalse(search_retired_user_results) + + def test_retired_user_with_no_cohort_returns_false(self): + known_learner_email = self.cohort_assignment.email + was_retired = UnregisteredLearnerCohortAssignments.delete_by_user_value( + value='nonexistantlearner@example.com', + field='email' + ) + + self.assertFalse(was_retired) + self.assertEqual(self.cohort_assignment.email, known_learner_email)