From ea71b27c367c4c1e9a3c60ad6c8f40c4a8ccc228 Mon Sep 17 00:00:00 2001 From: Awais Jibran Date: Tue, 29 Sep 2020 21:49:09 +0500 Subject: [PATCH 1/4] Update bulk unenroll management command. --- .../management/commands/bulk_unenroll.py | 40 ++++++++++++++----- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/common/djangoapps/student/management/commands/bulk_unenroll.py b/common/djangoapps/student/management/commands/bulk_unenroll.py index 70aa59687c..60f90a23ad 100644 --- a/common/djangoapps/student/management/commands/bulk_unenroll.py +++ b/common/djangoapps/student/management/commands/bulk_unenroll.py @@ -22,20 +22,32 @@ class Command(BaseCommand): It expect that the data will be provided in a csv file format with first row being the header and columns will be either one of the following: - username,course-id + | username | course_id | OR - course-id + | course_id | + + Example: + $ ... bulk_unenroll --csv_path=foo.csv + $ ... bulk_unenroll --csv_path=foo.csv --commit """ + commit = False def add_arguments(self, parser): - parser.add_argument('-p', '--csv_path', - metavar='csv_path', - dest='csv_path', - required=False, - help='Path to CSV file.') + parser.add_argument( + '-p', '--csv_path', + metavar='csv_path', + dest='csv_path', + required=True, + help='Path to CSV file.') + parser.add_argument( + '--commit', + action='store_true', + help='Save the changes, without this flag only a dry run will be performed and nothing will be changed') def handle(self, *args, **options): csv_path = options['csv_path'] + import pdb;pdb.set_trace() + self.commit = options['commit'] if csv_path: with open(csv_path, 'rb') as csv_file: @@ -67,7 +79,13 @@ class Command(BaseCommand): if username: enrollments = enrollments.filter(user__username=username) - for enrollment in enrollments: - enrollment.update_enrollment(is_active=False, skip_refund=True) - logger.info("User [{}] have been successfully unenrolled from the course: {}" - .format(enrollment.user.username, course_key)) + logger.info("Processing [{}] with [{}] enrollments.".format(course_id, enrollments.count())) + + if self.commit: + for enrollment in enrollments: + enrollment.update_enrollment(is_active=False, skip_refund=True) + logger.info( + "User [{}] have been successfully unenrolled from the course: {}".format( + enrollment.user.username, course_key + ) + ) From 01832220e2ec1184b4181310ad9937f7bac07897 Mon Sep 17 00:00:00 2001 From: Awais Jibran Date: Tue, 29 Sep 2020 21:57:46 +0500 Subject: [PATCH 2/4] Update tests --- .../management/tests/test_bulk_unenroll.py | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/common/djangoapps/student/management/tests/test_bulk_unenroll.py b/common/djangoapps/student/management/tests/test_bulk_unenroll.py index d8f02ee3c4..d953d69155 100644 --- a/common/djangoapps/student/management/tests/test_bulk_unenroll.py +++ b/common/djangoapps/student/management/tests/test_bulk_unenroll.py @@ -58,7 +58,7 @@ class BulkUnenrollTests(SharedModuleStoreTestCase): csv = self._write_test_csv(csv, lines=["amy,test_course\n"]) with LogCapture(LOGGER_NAME) as log: - call_command("bulk_unenroll", "--csv_path={}".format(csv.name)) + call_command("bulk_unenroll", "--csv_path={} --commit".format(csv.name)) expected_message = 'Invalid course id {}, skipping un-enrollement.'.\ format('test_course') @@ -76,10 +76,26 @@ class BulkUnenrollTests(SharedModuleStoreTestCase): with NamedTemporaryFile() as csv: csv = self._write_test_csv(csv, lines=lines) - call_command("bulk_unenroll", "--csv_path={}".format(csv.name)) + call_command("bulk_unenroll", "--csv_path={} --commit".format(csv.name)) for enrollment in CourseEnrollment.objects.all(): self.assertEqual(enrollment.is_active, False) + def test_bulk_un_enroll_without_commit(self): + """ + Verify the ability to dry-run the command. + """ + lines = [ + enrollment.user.username + "," + + str(enrollment.course.id) + "\n" + for enrollment in self.enrollments + ] + with NamedTemporaryFile() as csv: + csv = self._write_test_csv(csv, lines=lines) + + call_command("bulk_unenroll", "--csv_path={}".format(csv.name)) + for enrollment in CourseEnrollment.objects.all(): + self.assertEqual(enrollment.is_active, True) + def test_bulk_unenroll_from_config_model(self): """Verify users are unenrolled using the command.""" lines = "user_id,username,email,course_id\n" @@ -90,7 +106,7 @@ class BulkUnenrollTests(SharedModuleStoreTestCase): csv_file = SimpleUploadedFile(name='test.csv', content=lines.encode('utf-8'), content_type='text/csv') BulkUnenrollConfiguration.objects.create(enabled=True, csv_file=csv_file) - call_command("bulk_unenroll") + call_command("bulk_unenroll --commit") for enrollment in CourseEnrollment.objects.all(): self.assertEqual(enrollment.is_active, False) @@ -102,7 +118,7 @@ class BulkUnenrollTests(SharedModuleStoreTestCase): BulkUnenrollConfiguration.objects.create(enabled=True, csv_file=csv_file) with LogCapture(LOGGER_NAME) as log: - call_command("bulk_unenroll") + call_command("bulk_unenroll --commit") log.check( ( LOGGER_NAME, From ee4aca6504a9ed699403cc92e06a7c4820ead080 Mon Sep 17 00:00:00 2001 From: Awais Jibran Date: Tue, 29 Sep 2020 22:22:15 +0500 Subject: [PATCH 3/4] Update tests --- common/djangoapps/student/management/commands/bulk_unenroll.py | 1 - 1 file changed, 1 deletion(-) diff --git a/common/djangoapps/student/management/commands/bulk_unenroll.py b/common/djangoapps/student/management/commands/bulk_unenroll.py index 60f90a23ad..e09d3bb437 100644 --- a/common/djangoapps/student/management/commands/bulk_unenroll.py +++ b/common/djangoapps/student/management/commands/bulk_unenroll.py @@ -46,7 +46,6 @@ class Command(BaseCommand): def handle(self, *args, **options): csv_path = options['csv_path'] - import pdb;pdb.set_trace() self.commit = options['commit'] if csv_path: From 7d8d943167ce02f01e475ed0151bd73209df9256 Mon Sep 17 00:00:00 2001 From: Awais Jibran Date: Wed, 30 Sep 2020 13:51:56 +0500 Subject: [PATCH 4/4] Update tests --- .../student/management/commands/bulk_unenroll.py | 2 +- .../management/tests/test_bulk_unenroll.py | 16 +++++++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/common/djangoapps/student/management/commands/bulk_unenroll.py b/common/djangoapps/student/management/commands/bulk_unenroll.py index e09d3bb437..4faffa9aac 100644 --- a/common/djangoapps/student/management/commands/bulk_unenroll.py +++ b/common/djangoapps/student/management/commands/bulk_unenroll.py @@ -37,7 +37,7 @@ class Command(BaseCommand): '-p', '--csv_path', metavar='csv_path', dest='csv_path', - required=True, + required=False, help='Path to CSV file.') parser.add_argument( '--commit', diff --git a/common/djangoapps/student/management/tests/test_bulk_unenroll.py b/common/djangoapps/student/management/tests/test_bulk_unenroll.py index d953d69155..664eddbfe5 100644 --- a/common/djangoapps/student/management/tests/test_bulk_unenroll.py +++ b/common/djangoapps/student/management/tests/test_bulk_unenroll.py @@ -58,7 +58,7 @@ class BulkUnenrollTests(SharedModuleStoreTestCase): csv = self._write_test_csv(csv, lines=["amy,test_course\n"]) with LogCapture(LOGGER_NAME) as log: - call_command("bulk_unenroll", "--csv_path={} --commit".format(csv.name)) + call_command("bulk_unenroll", "--csv_path={}".format(csv.name), "--commit") expected_message = 'Invalid course id {}, skipping un-enrollement.'.\ format('test_course') @@ -76,7 +76,7 @@ class BulkUnenrollTests(SharedModuleStoreTestCase): with NamedTemporaryFile() as csv: csv = self._write_test_csv(csv, lines=lines) - call_command("bulk_unenroll", "--csv_path={} --commit".format(csv.name)) + call_command("bulk_unenroll", "--csv_path={}".format(csv.name), "--commit") for enrollment in CourseEnrollment.objects.all(): self.assertEqual(enrollment.is_active, False) @@ -106,7 +106,7 @@ class BulkUnenrollTests(SharedModuleStoreTestCase): csv_file = SimpleUploadedFile(name='test.csv', content=lines.encode('utf-8'), content_type='text/csv') BulkUnenrollConfiguration.objects.create(enabled=True, csv_file=csv_file) - call_command("bulk_unenroll --commit") + call_command("bulk_unenroll", "--commit") for enrollment in CourseEnrollment.objects.all(): self.assertEqual(enrollment.is_active, False) @@ -117,14 +117,20 @@ class BulkUnenrollTests(SharedModuleStoreTestCase): csv_file = SimpleUploadedFile(name='test.csv', content=lines.encode('utf-8'), content_type='text/csv') BulkUnenrollConfiguration.objects.create(enabled=True, csv_file=csv_file) + course_id = self.enrollments[0].course.id with LogCapture(LOGGER_NAME) as log: - call_command("bulk_unenroll --commit") + call_command("bulk_unenroll", "--commit") log.check( + ( + LOGGER_NAME, + 'INFO', + 'Processing [{}] with [1] enrollments.'.format(course_id), + ), ( LOGGER_NAME, 'INFO', 'User [{}] have been successfully unenrolled from the course: {}'.format( self.enrollments[0].username, self.enrollments[0].course.id ) - ) + ), )