Ejemplo n.º 1
0
def add_or_update_enrollment_attr(user_id, course_id, attributes):
    """Set enrollment attributes for the enrollment of given user in the
    course provided.

    Args:
        course_id (str): The Course to set enrollment attributes for.
        user_id (str): The User to set enrollment attributes for.
        attributes (list): Attributes to be set.

    Example:
        >>>add_or_update_enrollment_attr(
            "Bob",
            "course-v1-edX-DemoX-1T2015",
            [
                {
                    "namespace": "credit",
                    "name": "provider_id",
                    "value": "hogwarts",
                },
            ]
        )
    """
    course_key = CourseKey.from_string(course_id)
    user = _get_user(user_id)
    enrollment = CourseEnrollment.get_enrollment(user, course_key)
    if not _invalid_attribute(attributes) and enrollment is not None:
        CourseEnrollmentAttribute.add_enrollment_attr(enrollment, attributes)
Ejemplo n.º 2
0
def add_or_update_enrollment_attr(user_id, course_id, attributes):
    """Set enrollment attributes for the enrollment of given user in the
    course provided.

    Args:
        course_id (str): The Course to set enrollment attributes for.
        user_id (str): The User to set enrollment attributes for.
        attributes (list): Attributes to be set.

    Example:
        >>>add_or_update_enrollment_attr(
            "Bob",
            "course-v1-edX-DemoX-1T2015",
            [
                {
                    "namespace": "credit",
                    "name": "provider_id",
                    "value": "hogwarts",
                },
            ]
        )
    """
    course_key = CourseKey.from_string(course_id)
    user = _get_user(user_id)
    enrollment = CourseEnrollment.get_enrollment(user, course_key)
    if not _invalid_attribute(attributes) and enrollment is not None:
        CourseEnrollmentAttribute.add_enrollment_attr(enrollment, attributes)
Ejemplo n.º 3
0
    def update_enrollment_mode(self, course_key, user, mode,
                               course_enrollment):
        """
        update the enrollment mode based on the learner existing state.
        """
        # if student already had a enrollment and its mode is same as the provided one
        if course_enrollment.mode == mode:
            logger.info(
                "Student [%s] is already enrolled in Course [%s] in mode [%s].",
                user.username, course_key, course_enrollment.mode)
            # set the enrollment to active if its not already active.
            if not course_enrollment.is_active:
                course_enrollment.update_enrollment(is_active=True)
        else:
            # if student enrollment exists update it to new mode.
            with transaction.atomic():
                course_enrollment.update_enrollment(mode=mode,
                                                    is_active=True,
                                                    skip_refund=True)
                course_enrollment.save()

                if mode == 'credit':
                    enrollment_attrs = [{
                        'namespace': 'credit',
                        'name': 'provider_id',
                        'value': course_key.org
                    }]
                    CourseEnrollmentAttribute.add_enrollment_attr(
                        enrollment=course_enrollment,
                        data_list=enrollment_attrs)
Ejemplo n.º 4
0
 def post(self, request, username_or_email):
     """Allows support staff to alter a user's enrollment."""
     try:
         user = User.objects.get(
             Q(username=username_or_email) | Q(email=username_or_email))
         course_id = request.data['course_id']
         course_key = CourseKey.from_string(course_id)
         old_mode = request.data['old_mode']
         new_mode = request.data['new_mode']
         reason = request.data['reason']
         enrollment = CourseEnrollment.objects.get(user=user,
                                                   course_id=course_key)
         if enrollment.mode != old_mode:
             return HttpResponseBadRequest(
                 u'User {username} is not enrolled with mode {old_mode}.'.
                 format(username=user.username, old_mode=old_mode))
     except KeyError as err:
         return HttpResponseBadRequest(u'The field {} is required.'.format(
             text_type(err)))
     except InvalidKeyError:
         return HttpResponseBadRequest(u'Could not parse course key.')
     except (CourseEnrollment.DoesNotExist, User.DoesNotExist):
         return HttpResponseBadRequest(
             u'Could not find enrollment for user {username} in course {course}.'
             .format(username=username_or_email,
                     course=six.text_type(course_key)))
     try:
         # Wrapped in a transaction so that we can be sure the
         # ManualEnrollmentAudit record is always created correctly.
         with transaction.atomic():
             update_enrollment(user.username,
                               course_id,
                               mode=new_mode,
                               include_expired=True)
             manual_enrollment = ManualEnrollmentAudit.create_manual_enrollment_audit(
                 request.user,
                 enrollment.user.email,
                 ENROLLED_TO_ENROLLED,
                 reason=reason,
                 enrollment=enrollment)
             if new_mode == CourseMode.CREDIT_MODE:
                 provider_ids = get_credit_provider_attribute_values(
                     course_key, 'id')
                 credit_provider_attr = {
                     'namespace': 'credit',
                     'name': 'provider_id',
                     'value': provider_ids[0],
                 }
                 CourseEnrollmentAttribute.add_enrollment_attr(
                     enrollment=enrollment,
                     data_list=[credit_provider_attr])
             return JsonResponse(
                 ManualEnrollmentSerializer(
                     instance=manual_enrollment).data)
     except CourseModeNotFoundError as err:
         return HttpResponseBadRequest(text_type(err))
Ejemplo n.º 5
0
    def update_enrollments(self,
                           identifier,
                           enrollment_args,
                           options,
                           error_users,
                           success_users,
                           enrollment_attrs=None):
        """ Update enrollments for a specific user identifier (email or username). """
        users = options[identifier].split(",")

        credit_provider_attr = {}
        if options['to_mode'] == 'credit':
            provider_ids = get_credit_provider_attribute_values(
                enrollment_args.get('course_id'), 'id')
            credit_provider_attr = {
                'namespace': 'credit',
                'name': 'provider_id',
                'value': provider_ids[0],
            }

        for identified_user in users:
            logger.info(identified_user)

            try:
                user_args = {identifier: identified_user}

                enrollment_args['user'] = User.objects.get(**user_args)
                enrollments = CourseEnrollment.objects.filter(
                    **enrollment_args)

                enrollment_attrs = []
                with transaction.atomic():
                    for enrollment in enrollments:
                        enrollment.update_enrollment(mode=options['to_mode'])
                        enrollment.save()
                        if options['to_mode'] == 'credit':
                            enrollment_attrs.append(credit_provider_attr)
                            CourseEnrollmentAttribute.add_enrollment_attr(
                                enrollment=enrollment,
                                data_list=enrollment_attrs)

                    if options['noop']:
                        raise RollbackException('Forced rollback.')

            except RollbackException:
                success_users.append(identified_user)
                continue
            except Exception as exception:  # pylint: disable=broad-except
                error_users.append((identified_user, exception))
                continue

            success_users.append(identified_user)
            logger.info('Updated user [%s] to mode [%s]', identified_user,
                        options['to_mode'])
Ejemplo n.º 6
0
    def update_enrollments(self, identifier, enrollment_args, options, error_users, success_users, enrollment_attrs=None):
        """ Update enrollments for a specific user identifier (email or username). """
        users = options[identifier].split(",")

        credit_provider_attr = {}
        if options['to_mode'] == 'credit':
            provider_ids = get_credit_provider_attribute_values(
                enrollment_args.get('course_id'), 'id'
            )
            credit_provider_attr = {
                'namespace': 'credit',
                'name': 'provider_id',
                'value': provider_ids[0],
            }

        for identified_user in users:
            logger.info(identified_user)

            try:
                user_args = {
                    identifier: identified_user
                }

                enrollment_args['user'] = User.objects.get(**user_args)
                enrollments = CourseEnrollment.objects.filter(**enrollment_args)

                enrollment_attrs = []
                with transaction.atomic():
                    for enrollment in enrollments:
                        enrollment.update_enrollment(mode=options['to_mode'])
                        enrollment.save()
                        if options['to_mode'] == 'credit':
                            enrollment_attrs.append(credit_provider_attr)
                            CourseEnrollmentAttribute.add_enrollment_attr(
                                enrollment=enrollment, data_list=enrollment_attrs
                            )

                    if options['noop']:
                        raise RollbackException('Forced rollback.')

            except RollbackException:
                success_users.append(identified_user)
                continue
            except Exception as exception:  # pylint: disable=broad-except
                error_users.append((identified_user, exception))
                continue

            success_users.append(identified_user)
            logger.info('Updated user [%s] to mode [%s]', identified_user, options['to_mode'])
Ejemplo n.º 7
0
    def test_multiple_refunds_dashbaord_page_error(self):
        """ Order with mutiple refunds will not throw 500 error when dashboard page will access."""
        now = datetime.now(pytz.UTC).replace(microsecond=0)
        order_date = now + timedelta(days=1)
        expected_content = '{{"date_placed": "{date}"}}'.format(date=order_date.strftime(ECOMMERCE_DATE_FORMAT))

        httpretty.register_uri(
            httpretty.GET,
            '{url}/orders/{order}/'.format(url=TEST_API_URL, order=self.ORDER_NUMBER),
            status=200, body=expected_content,
            adding_headers={'Content-Type': JSON}
        )

        # creating multiple attributes for same order.
        for attribute_count in range(2):  # pylint: disable=unused-variable
            self.enrollment.attributes.add(CourseEnrollmentAttribute(
                enrollment=self.enrollment,
                namespace='order',
                name='order_number',
                value=self.ORDER_NUMBER
            ))

        self.client.login(username=self.user.username, password=self.USER_PASSWORD)
        resp = self.client.post(reverse('student.views.dashboard', args=[]))
        self.assertEqual(resp.status_code, 200)
Ejemplo n.º 8
0
    def test_refund_cutoff_date(self, order_date_delta, course_start_delta, expected_date_delta, days):
        """
        Assert that the later date is used with the configurable refund period in calculating the returned cutoff date.
        """
        now = datetime.now(pytz.UTC).replace(microsecond=0)
        order_date = now + order_date_delta
        course_start = now + course_start_delta
        expected_date = now + expected_date_delta
        refund_period = timedelta(days=days)
        expected_content = '{{"date_placed": "{date}"}}'.format(date=order_date.strftime(ECOMMERCE_DATE_FORMAT))

        httpretty.register_uri(
            httpretty.GET,
            '{url}/orders/{order}/'.format(url=TEST_API_URL, order=self.ORDER_NUMBER),
            status=200, body=expected_content,
            adding_headers={'Content-Type': JSON}
        )

        self.enrollment.course_overview.start = course_start
        self.enrollment.attributes.add(CourseEnrollmentAttribute(
            enrollment=self.enrollment,
            namespace='order',
            name='order_number',
            value=self.ORDER_NUMBER
        ))

        with patch('student.models.EnrollmentRefundConfiguration.current') as config:
            instance = config.return_value
            instance.refund_window = refund_period
            self.assertEqual(
                self.enrollment.refund_cutoff_date(),
                expected_date + refund_period
            )
Ejemplo n.º 9
0
def get_enrollment_attributes(user_id, course_id):
    """Retrieve enrollment attributes for given user for provided course.

    Args:
        user_id: The User to get enrollment attributes for
        course_id (str): The Course to get enrollment attributes for.

    Example:
        >>>get_enrollment_attributes("Bob", "course-v1-edX-DemoX-1T2015")
        [
            {
                "namespace": "credit",
                "name": "provider_id",
                "value": "hogwarts",
            },
        ]

    Returns: list
    """
    course_key = CourseKey.from_string(course_id)
    user = _get_user(user_id)
    enrollment = CourseEnrollment.get_enrollment(user, course_key)
    return CourseEnrollmentAttribute.get_enrollment_attributes(enrollment)
Ejemplo n.º 10
0
def get_enrollment_attributes(user_id, course_id):
    """Retrieve enrollment attributes for given user for provided course.

    Args:
        user_id: The User to get enrollment attributes for
        course_id (str): The Course to get enrollment attributes for.

    Example:
        >>>get_enrollment_attributes("Bob", "course-v1-edX-DemoX-1T2015")
        [
            {
                "namespace": "credit",
                "name": "provider_id",
                "value": "hogwarts",
            },
        ]

    Returns: list
    """
    course_key = CourseKey.from_string(course_id)
    user = _get_user(user_id)
    enrollment = CourseEnrollment.get_enrollment(user, course_key)
    return CourseEnrollmentAttribute.get_enrollment_attributes(enrollment)
    def handle(self, *args, **options):
        """ Main handler for the command."""
        file_path = options['csv_file_path']

        if not path.isfile(file_path):
            raise CommandError("File not found.")

        with open(file_path) as csv_file:
            course_key = None
            user = None
            file_reader = csv.DictReader(csv_file)
            headers = file_reader.fieldnames

            if not ('course_id' in headers and 'mode' in headers and 'user' in headers):
                raise CommandError('Invalid input CSV file.')

            for row in file_reader:
                try:
                    course_key = CourseKey.from_string(row['course_id'])
                except InvalidKeyError:
                    logger.warning('Invalid or non-existent course id [{}]'.format(row['course_id']))

                try:
                    user = User.objects.get(username=row['user'])
                except:
                    logger.warning('Invalid or non-existent user [{}]'.format(row['user']))
                if course_key and user:
                    try:
                        course_enrollment = CourseEnrollment.get_enrollment(user, course_key)
                        #  If student is not enrolled in course enroll the student in free mode
                        if not course_enrollment:
                            # try to create a enroll user in default course enrollment mode in case of
                            # professional it will break because of no default course mode.
                            try:
                                course_enrollment = CourseEnrollment.get_or_create_enrollment(user=user,
                                                                                              course_key=course_key)
                            except Exception:  # pylint: disable=broad-except
                                # In case if no free mode is available.
                                course_enrollment = None

                        if course_enrollment:
                            # if student already had a enrollment and its mode is same as the provided one
                            if course_enrollment.mode == row['mode']:
                                logger.info("Student [%s] is already enrolled in Course [%s] in mode [%s].", user.username,
                                            course_key, course_enrollment.mode)
                                # set the enrollment to active if its not already active.
                                if not course_enrollment.is_active:
                                    course_enrollment.update_enrollment(is_active=True)
                            else:
                                # if student enrollment exists update it to new mode.
                                with transaction.atomic():
                                    course_enrollment.update_enrollment(
                                        mode=row['mode'],
                                        is_active=True,
                                        skip_refund=True
                                    )
                                    course_enrollment.save()

                                    if row['mode'] == 'credit':
                                        enrollment_attrs = [{
                                            'namespace': 'credit',
                                            'name': 'provider_id',
                                            'value': course_key.org,
                                        }]
                                        CourseEnrollmentAttribute.add_enrollment_attr(enrollment=course_enrollment,
                                                                                      data_list=enrollment_attrs)
                        else:
                            # if student enrollment do not exists directly enroll in new mode.
                            CourseEnrollment.enroll(user=user, course_key=course_key, mode=row['mode'])

                    except Exception as e:
                        logger.info("Unable to update student [%s] course [%s] enrollment to mode [%s] "
                                    "because of Exception [%s]", row['user'], row['course_id'], row['mode'], repr(e))
    def handle(self, *args, **options):
        """ Main handler for the command."""
        file_path = options['csv_file_path']

        if not path.isfile(file_path):
            raise CommandError("File not found.")

        with open(file_path) as csv_file:
            course_key = None
            user = None
            file_reader = csv.DictReader(csv_file)
            headers = file_reader.fieldnames

            if not ('course_id' in headers and 'mode' in headers and 'user' in headers):
                raise CommandError('Invalid input CSV file.')

            for row in file_reader:
                try:
                    course_key = CourseKey.from_string(row['course_id'])
                except InvalidKeyError:
                    logger.warning('Invalid or non-existent course id [{}]'.format(row['course_id']))

                try:
                    user = User.objects.get(username=row['user'])
                except:
                    logger.warning('Invalid or non-existent user [{}]'.format(row['user']))
                if course_key and user:
                    try:
                        course_enrollment = CourseEnrollment.get_enrollment(user, course_key)
                        #  If student is not enrolled in course enroll the student in free mode
                        if not course_enrollment:
                            # try to create a enroll user in default course enrollment mode in case of
                            # professional it will break because of no default course mode.
                            try:
                                course_enrollment = CourseEnrollment.get_or_create_enrollment(user=user,
                                                                                              course_key=course_key)
                            except Exception:  # pylint: disable=broad-except
                                # In case if no free mode is available.
                                course_enrollment = None

                        if course_enrollment:
                            # if student already had a enrollment and its mode is same as the provided one
                            if course_enrollment.mode == row['mode']:
                                logger.info("Student [%s] is already enrolled in Course [%s] in mode [%s].", user.username,
                                            course_key, course_enrollment.mode)
                                # set the enrollment to active if its not already active.
                                if not course_enrollment.is_active:
                                    course_enrollment.update_enrollment(is_active=True)
                            else:
                                # if student enrollment exists update it to new mode.
                                with transaction.atomic():
                                    course_enrollment.update_enrollment(
                                        mode=row['mode'],
                                        is_active=True,
                                        skip_refund=True
                                    )
                                    course_enrollment.save()

                                    if row['mode'] == 'credit':
                                        enrollment_attrs = [{
                                            'namespace': 'credit',
                                            'name': 'provider_id',
                                            'value': course_key.org,
                                        }]
                                        CourseEnrollmentAttribute.add_enrollment_attr(enrollment=course_enrollment,
                                                                                      data_list=enrollment_attrs)
                        else:
                            # if student enrollment do not exists directly enroll in new mode.
                            CourseEnrollment.enroll(user=user, course_key=course_key, mode=row['mode'])

                    except Exception as e:
                        logger.info("Unable to update student [%s] course [%s] enrollment to mode [%s] "
                                    "because of Exception [%s]", row['user'], row['course_id'], row['mode'], repr(e))