From 7d9b6a55ddcccc2449831f081247d697773a9aa6 Mon Sep 17 00:00:00 2001 From: Feanil Patel Date: Tue, 24 Dec 2013 14:32:38 -0500 Subject: [PATCH 1/3] Add a command to transfer students from one course to another. Move only active students and also update cert item for verified students. --- .../management/commands/transfer_students.py | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 common/djangoapps/student/management/commands/transfer_students.py diff --git a/common/djangoapps/student/management/commands/transfer_students.py b/common/djangoapps/student/management/commands/transfer_students.py new file mode 100644 index 0000000000..e986e7d192 --- /dev/null +++ b/common/djangoapps/student/management/commands/transfer_students.py @@ -0,0 +1,64 @@ +from optparse import make_option +from django.core.management.base import BaseCommand +from django.contrib.auth.models import User +from student.models import CourseEnrollment +from shoppingcart.models import CertificateItem + + +class Command(BaseCommand): + help = """ + This command takes two course ids as input and transfers + all students enrolled in one course into the other. This will + remove them from the first class and enroll them in the second + class in the same mode as the first one. eg. honor, verified, + audit. + + example: + # Transfer students from the old demoX class to a new one. + manage.py ... transfer_students -f edX/Open_DemoX/edx_demo_course -t edX/Open_DemoX/new_demoX + """ + + option_list = BaseCommand.option_list + ( + make_option('-f', '--from', + metavar='SOURCE_COURSE', + dest='source_course', + help='The course to transfer students from.'), + make_option('-t', '--to', + metavar='DEST_COURSE', + dest='dest_course', + help='The new course to enroll the student into.'), + ) + + def handle(self, *args, **options): + source = options['source_course'] + dest = options['dest_course'] + + source_students = User.objects.filter( + courseenrollment__course_id=source, + courseenrollment__is_active=True) + + for user in source_students: + print("Moving {}.".format(user.username)) + # Find the old enrollment. + enrollment = CourseEnrollment.objects.get(user=user, + course_id=source) + # Move the Student between the classes. + mode = enrollment.mode + CourseEnrollment.unenroll(user,source) + CourseEnrollment.enroll(user, dest, mode=mode) + + if mode == 'verified': + try: + certificate_item = CertificateItem.objects.get( + course_id=source, + course_enrollment=enrollment) + except CertificateItem.DoesNotExist: + print("No certificate for {}".format(user)) + continue + + new_enrollment = CourseEnrollment.objects.get(user=user, + course_id=dest) + + certificate_item.course_id = dest + certificate_item.course_enrollment = new_enrollment + certificate_item.save() From 1be33651b08ac4fc20cad3ea962c5ca3468c4b53 Mon Sep 17 00:00:00 2001 From: Feanil Patel Date: Fri, 10 Jan 2014 13:18:39 -0500 Subject: [PATCH 2/3] CertificateItems should be updated for all course students. Not just students that are currently active. Students may have enrolled with verified certs, paid, gotten a refund, and un-enrolled from the original course. This function should now capture that. --- .../student/management/commands/transfer_students.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/common/djangoapps/student/management/commands/transfer_students.py b/common/djangoapps/student/management/commands/transfer_students.py index e986e7d192..38585961aa 100644 --- a/common/djangoapps/student/management/commands/transfer_students.py +++ b/common/djangoapps/student/management/commands/transfer_students.py @@ -34,18 +34,21 @@ class Command(BaseCommand): dest = options['dest_course'] source_students = User.objects.filter( - courseenrollment__course_id=source, - courseenrollment__is_active=True) + courseenrollment__course_id=source) for user in source_students: print("Moving {}.".format(user.username)) # Find the old enrollment. enrollment = CourseEnrollment.objects.get(user=user, course_id=source) + # Move the Student between the classes. mode = enrollment.mode CourseEnrollment.unenroll(user,source) - CourseEnrollment.enroll(user, dest, mode=mode) + new_enrollment = CourseEnrollment.enroll(user, dest, mode=mode) + + if not enrollment.is_active: + CourseEnrollment.unenroll(user,dest) if mode == 'verified': try: @@ -56,9 +59,6 @@ class Command(BaseCommand): print("No certificate for {}".format(user)) continue - new_enrollment = CourseEnrollment.objects.get(user=user, - course_id=dest) - certificate_item.course_id = dest certificate_item.course_enrollment = new_enrollment certificate_item.save() From 16d6d23fbcd79e105113db63fdefec529d2c88c5 Mon Sep 17 00:00:00 2001 From: Feanil Patel Date: Fri, 10 Jan 2014 14:16:04 -0500 Subject: [PATCH 3/3] Save state before unenrolling student from old course. --- .../student/management/commands/transfer_students.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/common/djangoapps/student/management/commands/transfer_students.py b/common/djangoapps/student/management/commands/transfer_students.py index 38585961aa..0e7edc7cfb 100644 --- a/common/djangoapps/student/management/commands/transfer_students.py +++ b/common/djangoapps/student/management/commands/transfer_students.py @@ -44,11 +44,14 @@ class Command(BaseCommand): # Move the Student between the classes. mode = enrollment.mode + old_is_active = enrollment.is_active CourseEnrollment.unenroll(user,source) new_enrollment = CourseEnrollment.enroll(user, dest, mode=mode) - if not enrollment.is_active: - CourseEnrollment.unenroll(user,dest) + # Unenroll from the new coures if the user had unenrolled + # form the old course. + if not old_is_active: + new_enrollment.update_enrollment(is_active=False) if mode == 'verified': try: