示例#1
0
    def test_disabled_university_id_redirect(self):
        disabled_course = CourseFactory.create(enable_university_id=False)
        CourseEnrollment.get_or_create_enrollment(self.user,
                                                  disabled_course.id)
        set_course_cohort_settings(disabled_course.id, is_cohorted=True)

        student_form_url = reverse('edraak_university:id',
                                   args=[unicode(disabled_course.id)])
        course_root_url = reverse('course_root',
                                  args=[unicode(disabled_course.id)])

        res = self.client.get(student_form_url)
        self.assertRedirects(res, course_root_url)
示例#2
0
    def get(self, request, course_id):
        """
        display this view
        """
        course_id = CourseKey.from_string(course_id)
        course = modulestore().get_course(course_id)
        if course is None:
            raise Http404

        course_enrollment = CourseEnrollment.get_or_create_enrollment(
            request.user, course_id)
        course_enrollment.update_enrollment(mode="verified")
        course_enrollment.emit_event(
            EVENT_NAME_USER_ENTERED_MIDCOURSE_REVERIFY_VIEW)
        context = {
            "user_full_name": request.user.profile.name,
            "error": False,
            "course_id": course_id.to_deprecated_string(),
            "course_name": course.display_name_with_default,
            "course_org": course.display_org_with_default,
            "course_num": course.display_number_with_default,
            "reverify": True,
        }

        return render_to_response(
            "verify_student/midcourse_photo_reverification.html", context)
示例#3
0
    def post(self, request, course_id):
        """
        submits the reverification to SoftwareSecure
        """
        try:
            now = datetime.datetime.now(UTC)
            course_id = CourseKey.from_string(course_id)
            window = MidcourseReverificationWindow.get_window(course_id, now)
            if window is None:
                raise WindowExpiredException
            attempt = SoftwareSecurePhotoVerification(user=request.user, window=window)
            b64_face_image = request.POST["face_image"].split(",")[1]

            attempt.upload_face_image(b64_face_image.decode("base64"))
            attempt.fetch_photo_id_image()
            attempt.mark_ready()

            attempt.save()
            attempt.submit()
            course_enrollment = CourseEnrollment.get_or_create_enrollment(request.user, course_id)
            course_enrollment.update_enrollment(mode="verified")
            course_enrollment.emit_event(EVENT_NAME_USER_SUBMITTED_MIDCOURSE_REVERIFY)
            return HttpResponseRedirect(reverse("verify_student_midcourse_reverification_confirmation"))

        except WindowExpiredException:
            log.exception(
                "User {} attempted to re-verify, but the window expired before the attempt".format(request.user.id)
            )
            return HttpResponseRedirect(reverse("verify_student_reverification_window_expired"))

        except Exception:
            log.exception("Could not submit verification attempt for user {}".format(request.user.id))
            context = {"user_full_name": request.user.profile.name, "error": True}
            return render_to_response("verify_student/midcourse_photo_reverification.html", context)
示例#4
0
 def save(self, *args, **kwargs):
     course_enrollment = super(CourseEnrollmentForm, self).save(commit=False)
     user = self.cleaned_data['user']
     course_overview = self.cleaned_data['course']
     enrollment = CourseEnrollment.get_or_create_enrollment(user, course_overview.id)
     course_enrollment.id = enrollment.id
     course_enrollment.created = enrollment.created
     return course_enrollment
示例#5
0
    def add_to_order(cls, order, course_id, cost, mode, currency='usd'):
        """
        Add a CertificateItem to an order

        Returns the CertificateItem object after saving

        `order` - an order that this item should be added to, generally the cart order
        `course_id` - the course that we would like to purchase as a CertificateItem
        `cost` - the amount the user will be paying for this CertificateItem
        `mode` - the course mode that this certificate is going to be issued for

        This item also creates a new enrollment if none exists for this user and this course.

        Example Usage:
            cart = Order.get_cart_for_user(user)
            CertificateItem.add_to_order(cart, 'edX/Test101/2013_Fall', 30, 'verified')

        """
        super(CertificateItem, cls).add_to_order(order,
                                                 course_id,
                                                 cost,
                                                 currency=currency)

        course_enrollment = CourseEnrollment.get_or_create_enrollment(
            order.user, course_id)

        # do some validation on the enrollment mode
        valid_modes = CourseMode.modes_for_course_dict(course_id)
        if mode in valid_modes:
            mode_info = valid_modes[mode]
        else:
            raise InvalidCartItem(
                _("Mode {mode} does not exist for {course_id}").format(
                    mode=mode, course_id=course_id))
        item, _created = cls.objects.get_or_create(
            order=order,
            user=order.user,
            course_id=course_id,
            course_enrollment=course_enrollment,
            mode=mode,
        )
        item.status = order.status
        item.qty = 1
        item.unit_cost = cost
        course_name = modulestore().get_course(course_id).display_name
        # Translators: In this particular case, mode_name refers to a
        # particular mode (i.e. Honor Code Certificate, Verified Certificate, etc)
        # by which a user could enroll in the given course.
        item.line_desc = _("{mode_name} for course {course}").format(
            mode_name=mode_info.name, course=course_name)
        item.currency = currency
        order.currency = currency
        order.save()
        item.save()
        return item
    def test_midcourse_reverify_dash(self):
        url = reverse('verify_student_midcourse_reverify_dash')
        response = self.client.get(url)
        # not enrolled in any courses
        self.assertEquals(response.status_code, 200)

        enrollment = CourseEnrollment.get_or_create_enrollment(self.user, self.course_key)
        enrollment.update_enrollment(mode="verified", is_active=True)
        MidcourseReverificationWindowFactory(course_id=self.course_key)
        response = self.client.get(url)
        # enrolled in a verified course, and the window is open
        self.assertEquals(response.status_code, 200)
示例#7
0
    def test_midcourse_reverify_dash(self):
        url = reverse('verify_student_midcourse_reverify_dash')
        response = self.client.get(url)
        # not enrolled in any courses
        self.assertEquals(response.status_code, 200)

        enrollment = CourseEnrollment.get_or_create_enrollment(self.user, self.course_id)
        enrollment.update_enrollment(mode="verified", is_active=True)
        MidcourseReverificationWindowFactory(course_id=self.course_id)
        response = self.client.get(url)
        # enrolled in a verified course, and the window is open
        self.assertEquals(response.status_code, 200)
    def create_course_reference_data(course):
        """
        Populates DB with test data
        """
        course_key = course.id
        user = UserFactory()
        group = GroupFactory()
        CourseGroupRelationship(course_id=course_key, group=group).save()
        StudentGradebook(
            user=user,
            course_id=course_key,
            grade=0.9,
            proforma_grade=0.91,
            progress_summary='test',
            grade_summary='test',
            grading_policy='test',
        ).save()
        CourseEnrollment.get_or_create_enrollment(user, course_key)
        CourseAccessRole(user=user,
                         course_id=course_key,
                         org='test',
                         role='TA').save()
        handouts_usage_key = course_key.make_usage_key('course_info',
                                                       'handouts')
        StudentModule(student=user,
                      course_id=course_key,
                      module_state_key=handouts_usage_key).save()
        CourseAggregatedMetaData(id=course_key,
                                 total_assessments=10,
                                 total_modules=20).save()

        structure_json = '{"test": true}'
        course_structure, created = CourseStructure.objects.get_or_create(
            course_id=course_key, defaults={'structure_json': structure_json})
        if not created:
            course_structure.structure_json = structure_json
            course_structure.save()

        CourseOverview.get_from_id(course_key)
示例#9
0
    def add_to_order(cls, order, course_id, cost, mode, currency='usd'):
        """
        Add a CertificateItem to an order

        Returns the CertificateItem object after saving

        `order` - an order that this item should be added to, generally the cart order
        `course_id` - the course that we would like to purchase as a CertificateItem
        `cost` - the amount the user will be paying for this CertificateItem
        `mode` - the course mode that this certificate is going to be issued for

        This item also creates a new enrollment if none exists for this user and this course.

        Example Usage:
            cart = Order.get_cart_for_user(user)
            CertificateItem.add_to_order(cart, 'edX/Test101/2013_Fall', 30, 'verified')

        """
        super(CertificateItem, cls).add_to_order(order, course_id, cost, currency=currency)

        course_enrollment = CourseEnrollment.get_or_create_enrollment(order.user, course_id)

        # do some validation on the enrollment mode
        valid_modes = CourseMode.modes_for_course_dict(course_id)
        if mode in valid_modes:
            mode_info = valid_modes[mode]
        else:
            raise InvalidCartItem(_("Mode {mode} does not exist for {course_id}").format(mode=mode, course_id=course_id))
        item, _created = cls.objects.get_or_create(
            order=order,
            user=order.user,
            course_id=course_id,
            course_enrollment=course_enrollment,
            mode=mode,
        )
        item.status = order.status
        item.qty = 1
        item.unit_cost = cost
        course_name = modulestore().get_course(course_id).display_name
        # Translators: In this particular case, mode_name refers to a
        # particular mode (i.e. Honor Code Certificate, Verified Certificate, etc)
        # by which a user could enroll in the given course.
        item.line_desc = _("{mode_name} for course {course}").format(
            mode_name=mode_info.name,
            course=course_name
        )
        item.currency = currency
        order.currency = currency
        order.save()
        item.save()
        return item
示例#10
0
    def test_show_receipt_success_with_upgrade(self):

        reg_item = PaidCourseRegistration.add_to_order(self.cart,
                                                       self.course_id)
        cert_item = CertificateItem.add_to_order(self.cart,
                                                 self.verified_course_id,
                                                 self.cost, 'honor')
        self.cart.purchase(first='FirstNameTesting123',
                           street1='StreetTesting123')

        self.login_user()

        # When we come from the upgrade flow, we'll have a session variable showing that
        s = self.client.session
        s['attempting_upgrade'] = True
        s.save()

        self.mock_tracker.emit.reset_mock()  # pylint: disable=maybe-no-member
        resp = self.client.get(
            reverse('shoppingcart.views.show_receipt', args=[self.cart.id]))

        # Once they've upgraded, they're no longer *attempting* to upgrade
        attempting_upgrade = self.client.session.get('attempting_upgrade',
                                                     False)
        self.assertFalse(attempting_upgrade)

        self.assertEqual(resp.status_code, 200)
        self.assertIn('FirstNameTesting123', resp.content)
        self.assertIn('80.00', resp.content)

        ((template, context), _) = render_mock.call_args

        # When we come from the upgrade flow, we get these context variables

        self.assertEqual(template, 'shoppingcart/receipt.html')
        self.assertEqual(context['order'], self.cart)
        self.assertIn(reg_item, context['order_items'])
        self.assertIn(cert_item, context['order_items'])
        self.assertFalse(context['any_refunds'])

        course_enrollment = CourseEnrollment.get_or_create_enrollment(
            self.user, self.course_id)
        course_enrollment.emit_event('edx.course.enrollment.upgrade.succeeded')
        self.mock_tracker.emit.assert_any_call(  # pylint: disable=maybe-no-member
            'edx.course.enrollment.upgrade.succeeded',
            {
                'user_id': course_enrollment.user.id,
                'course_id': course_enrollment.course_id,
                'mode': course_enrollment.mode
            }
        )
示例#11
0
    def test_get_or_create_integrity_error(self):
        """Verify that get_or_create_enrollment handles IntegrityError."""

        CourseEnrollmentFactory.create(user=self.user,
                                       course_id=self.course.id)

        with patch.object(CourseEnrollment.objects,
                          "get_or_create") as mock_get_or_create:
            mock_get_or_create.side_effect = IntegrityError
            enrollment = CourseEnrollment.get_or_create_enrollment(
                self.user, self.course.id)

        self.assertEqual(enrollment.user, self.user)
        self.assertEqual(enrollment.course.id, self.course.id)
    def test_get_or_create_integrity_error(self):
        """Verify that get_or_create_enrollment handles IntegrityError."""

        CourseEnrollmentFactory.create(user=self.user, course_id=self.course.id)

        with patch.object(CourseEnrollment.objects, "get_or_create") as mock_get_or_create:
            mock_get_or_create.side_effect = IntegrityError
            enrollment = CourseEnrollment.get_or_create_enrollment(
                self.user,
                self.course.id
            )

        self.assertEqual(enrollment.user, self.user)
        self.assertEqual(enrollment.course.id, self.course.id)
示例#13
0
def fetch_reverify_banner_info(request, course_key):
    """
    Fetches needed context variable to display reverification banner in courseware
    """
    reverifications = defaultdict(list)
    user = request.user
    if not user.id:
        return reverifications
    enrollment = CourseEnrollment.get_or_create_enrollment(request.user, course_key)
    course = modulestore().get_course(course_key)
    info = single_course_reverification_info(user, course, enrollment)
    if info:
        reverifications[info.status].append(info)
    return reverifications
示例#14
0
 def clean(self):
     """
     clean form
     """
     user, course_id = self.cleaned_data.get('user'), self.cleaned_data.get('course_id')
     if user and course_id:
         self.cleaned_data['enrollment'] = enrollment = CourseEnrollment.get_or_create_enrollment(user, course_id)
         if enrollment.refundable():
             raise forms.ValidationError(_("Course {course_id} not past the refund window.").format(course_id=course_id))
         try:
             self.cleaned_data['cert'] = enrollment.certificateitem_set.filter(mode='verified', status='purchased')[0]
         except IndexError:
             raise forms.ValidationError(_("No order found for {user} in course {course_id}").format(user=user, course_id=course_id))
     return self.cleaned_data
示例#15
0
def fetch_reverify_banner_info(request, course_key):
    """
    Fetches needed context variable to display reverification banner in courseware
    """
    reverifications = defaultdict(list)
    user = request.user
    if not user.id:
        return reverifications
    enrollment = CourseEnrollment.get_or_create_enrollment(request.user, course_key)
    course = modulestore().get_course(course_key)
    info = single_course_reverification_info(user, course, enrollment)
    if info:
        reverifications[info.status].append(info)
    return reverifications
示例#16
0
def show_receipt(request, ordernum):
    """
    Displays a receipt for a particular order.
    404 if order is not yet purchased or request.user != order.user
    """
    try:
        order = Order.objects.get(id=ordernum)
    except Order.DoesNotExist:
        raise Http404('Order not found!')

    if order.user != request.user or order.status != 'purchased':
        raise Http404('Order not found!')

    order_items = OrderItem.objects.filter(order=order).select_subclasses()
    any_refunds = any(i.status == "refunded" for i in order_items)
    receipt_template = 'shoppingcart/receipt.html'
    __, instructions = order.generate_receipt_instructions()

    # only show billed to information on receipt if we have any
    # note, SaferPay does not capture Bill To information
    show_billed_to_info = order.bill_to_cardtype or order.bill_to_ccnum or \
                          order.bill_to_first or order.bill_to_last or \
                          order.bill_to_street1 or order.bill_to_street2 or \
                          order.bill_to_city or order.bill_to_state or order.bill_to_postalcode or \
                          order.bill_to_country

    # we want to have the ability to override the default receipt page when
    # there is only one item in the order
    context = {
        'order': order,
        'order_items': order_items,
        'any_refunds': any_refunds,
        'instructions': instructions,
        'show_billed_to_info': show_billed_to_info,
    }

    if order_items.count() == 1:
        receipt_template = order_items[0].single_item_receipt_template
        context.update(order_items[0].single_item_receipt_context)

    # Only orders where order_items.count() == 1 might be attempting to upgrade
    attempting_upgrade = request.session.get('attempting_upgrade', False)
    if attempting_upgrade:
        course_enrollment = CourseEnrollment.get_or_create_enrollment(request.user, order_items[0].course_id)
        course_enrollment.emit_event(EVENT_NAME_USER_UPGRADED)
        request.session['attempting_upgrade'] = False

    return render_to_response(receipt_template, context)
示例#17
0
    def test_show_receipt_success_with_upgrade(self):

        reg_item = PaidCourseRegistration.add_to_order(self.cart, self.course_id)
        cert_item = CertificateItem.add_to_order(self.cart, self.verified_course_id, self.cost, 'honor')
        self.cart.purchase(first='FirstNameTesting123', street1='StreetTesting123')

        self.login_user()

        # When we come from the upgrade flow, we'll have a session variable showing that
        s = self.client.session
        s['attempting_upgrade'] = True
        s.save()

        self.mock_server_track.reset_mock()
        resp = self.client.get(reverse('shoppingcart.views.show_receipt', args=[self.cart.id]))

        # Once they've upgraded, they're no longer *attempting* to upgrade
        attempting_upgrade = self.client.session.get('attempting_upgrade', False)
        self.assertFalse(attempting_upgrade)
        
        self.assertEqual(resp.status_code, 200)
        self.assertIn('FirstNameTesting123', resp.content)
        self.assertIn('80.00', resp.content)


        ((template, context), _) = render_mock.call_args

        # When we come from the upgrade flow, we get these context variables


        self.assertEqual(template, 'shoppingcart/receipt.html')
        self.assertEqual(context['order'], self.cart)
        self.assertIn(reg_item, context['order_items'])
        self.assertIn(cert_item, context['order_items'])
        self.assertFalse(context['any_refunds'])

        course_enrollment = CourseEnrollment.get_or_create_enrollment(self.user, self.course_id)
        course_enrollment.emit_event('edx.course.enrollment.upgrade.succeeded')
        self.mock_server_track.assert_any_call(
            None,
            'edx.course.enrollment.upgrade.succeeded',
            {
                'user_id': course_enrollment.user.id,
                'course_id': course_enrollment.course_id,
                'mode': course_enrollment.mode
            }
        )
示例#18
0
    def post(self, request, course_id):
        """
        submits the reverification to SoftwareSecure
        """
        try:
            now = datetime.datetime.now(UTC)
            course_id = SlashSeparatedCourseKey.from_deprecated_string(
                course_id)
            window = MidcourseReverificationWindow.get_window(course_id, now)
            if window is None:
                raise WindowExpiredException
            attempt = SoftwareSecurePhotoVerification(user=request.user,
                                                      window=window)
            b64_face_image = request.POST['face_image'].split(",")[1]

            attempt.upload_face_image(b64_face_image.decode('base64'))
            attempt.fetch_photo_id_image()
            attempt.mark_ready()

            attempt.save()
            attempt.submit()
            course_enrollment = CourseEnrollment.get_or_create_enrollment(
                request.user, course_id)
            course_enrollment.update_enrollment(mode="verified")
            course_enrollment.emit_event(
                EVENT_NAME_USER_SUBMITTED_MIDCOURSE_REVERIFY)
            return HttpResponseRedirect(
                reverse(
                    'verify_student_midcourse_reverification_confirmation'))

        except WindowExpiredException:
            log.exception(
                "User {} attempted to re-verify, but the window expired before the attempt"
                .format(request.user.id))
            return HttpResponseRedirect(
                reverse('verify_student_reverification_window_expired'))

        except Exception:
            log.exception(
                "Could not submit verification attempt for user {}".format(
                    request.user.id))
            context = {
                "user_full_name": request.user.profile.name,
                "error": True,
            }
            return render_to_response(
                "verify_student/midcourse_photo_reverification.html", context)
示例#19
0
    def test_mode_change_after_refund_seat(self, course_modes, new_mode):
        """
        Test if a course seat is refunded student is enrolled into default course mode
        unless no default mode available.
        """
        course_id = CourseLocator('test_org', 'test_course_number', 'test_run')
        CourseMode.objects.all().delete()
        for course_mode in course_modes:
            CourseModeFactory.create(
                course_id=course_id,
                mode_slug=course_mode,
                mode_display_name=course_mode,
            )

        httpretty.register_uri(httpretty.POST,
                               settings.ECOMMERCE_API_URL + 'refunds/',
                               status=201,
                               body='[1]',
                               content_type='application/json')
        httpretty.register_uri(httpretty.PUT,
                               settings.ECOMMERCE_API_URL +
                               'refunds/1/process/',
                               status=200,
                               body=json.dumps({
                                   "id": 9,
                                   "created": "2017-12-21T18:23:49.468298Z",
                                   "modified": "2017-12-21T18:24:02.741426Z",
                                   "total_credit_excl_tax": "100.00",
                                   "currency": "USD",
                                   "status": "Complete",
                                   "order": 15,
                                   "user": 5
                               }),
                               content_type='application/json')
        enrollment = CourseEnrollment.enroll(self.user,
                                             course_id,
                                             mode=course_modes[0])

        refund_success = refund_seat(enrollment, True)

        enrollment = CourseEnrollment.get_or_create_enrollment(
            self.user, course_id)

        assert refund_success
        self.assertEqual(enrollment.mode, new_mode)
示例#20
0
    def test_mode_change_after_refund_seat(self, course_modes, new_mode):
        """
        Test if a course seat is refunded student is enrolled into default course mode
        unless no default mode available.
        """
        course_id = CourseLocator('test_org', 'test_course_number', 'test_run')
        CourseMode.objects.all().delete()
        for course_mode in course_modes:
            CourseModeFactory.create(
                course_id=course_id,
                mode_slug=course_mode,
                mode_display_name=course_mode,
            )

        httpretty.register_uri(
            httpretty.POST,
            settings.ECOMMERCE_API_URL + 'refunds/',
            status=201,
            body='[1]',
            content_type='application/json'
        )
        httpretty.register_uri(
            httpretty.PUT,
            settings.ECOMMERCE_API_URL + 'refunds/1/process/',
            status=200,
            body=json.dumps({
                "id": 9,
                "created": "2017-12-21T18:23:49.468298Z",
                "modified": "2017-12-21T18:24:02.741426Z",
                "total_credit_excl_tax": "100.00",
                "currency": "USD",
                "status": "Complete",
                "order": 15,
                "user": 5
            }),
            content_type='application/json'
        )
        enrollment = CourseEnrollment.enroll(self.user, course_id, mode=course_modes[0])

        refund_success = refund_seat(enrollment, True)

        enrollment = CourseEnrollment.get_or_create_enrollment(self.user, course_id)

        assert refund_success
        self.assertEqual(enrollment.mode, new_mode)
示例#21
0
    def test_show_receipt_success_with_upgrade(self):

        reg_item = PaidCourseRegistration.add_to_order(self.cart, self.course_id)
        cert_item = CertificateItem.add_to_order(self.cart, self.verified_course_id, self.cost, "honor")
        self.cart.purchase(first="FirstNameTesting123", street1="StreetTesting123")

        self.login_user()

        # When we come from the upgrade flow, we'll have a session variable showing that
        s = self.client.session
        s["attempting_upgrade"] = True
        s.save()

        self.mock_tracker.emit.reset_mock()  # pylint: disable=maybe-no-member
        resp = self.client.get(reverse("shoppingcart.views.show_receipt", args=[self.cart.id]))

        # Once they've upgraded, they're no longer *attempting* to upgrade
        attempting_upgrade = self.client.session.get("attempting_upgrade", False)
        self.assertFalse(attempting_upgrade)

        self.assertEqual(resp.status_code, 200)
        self.assertIn("FirstNameTesting123", resp.content)
        self.assertIn("80.00", resp.content)

        ((template, context), _) = render_mock.call_args

        # When we come from the upgrade flow, we get these context variables

        self.assertEqual(template, "shoppingcart/receipt.html")
        self.assertEqual(context["order"], self.cart)
        self.assertIn(reg_item, context["order_items"])
        self.assertIn(cert_item, context["order_items"])
        self.assertFalse(context["any_refunds"])

        course_enrollment = CourseEnrollment.get_or_create_enrollment(self.user, self.course_id)
        course_enrollment.emit_event("edx.course.enrollment.upgrade.succeeded")
        self.mock_tracker.emit.assert_any_call(  # pylint: disable=maybe-no-member
            "edx.course.enrollment.upgrade.succeeded",
            {
                "user_id": course_enrollment.user.id,
                "course_id": course_enrollment.course_id,
                "mode": course_enrollment.mode,
            },
        )
    def get_course_enrollment(self, course_key, user):
        """
        If student is not enrolled in course enroll the student in free mode
        """

        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

        return course_enrollment
示例#23
0
    def get(self, request, course_id):
        """
        display this view
        """
        course = course_from_id(course_id)
        course_enrollment = CourseEnrollment.get_or_create_enrollment(request.user, course_id)
        course_enrollment.update_enrollment(mode="verified")
        course_enrollment.emit_event(EVENT_NAME_USER_ENTERED_MIDCOURSE_REVERIFY_VIEW)
        context = {
            "user_full_name": request.user.profile.name,
            "error": False,
            "course_id": course_id,
            "course_name": course.display_name_with_default,
            "course_org": course.display_org_with_default,
            "course_num": course.display_number_with_default,
            "reverify": True,
        }

        return render_to_response("verify_student/midcourse_photo_reverification.html", context)
示例#24
0
 def clean(self):
     """
     clean form
     """
     user, course_id = self.cleaned_data.get('user'), self.cleaned_data.get('course_id')
     if user and course_id:
         self.cleaned_data['enrollment'] = enrollment = CourseEnrollment.get_or_create_enrollment(user, course_id)
         if enrollment.refundable():
             msg = _("Course {course_id} not past the refund window.").format(course_id=course_id)
             raise forms.ValidationError(msg)
         try:
             self.cleaned_data['cert'] = enrollment.certificateitem_set.filter(
                 mode='verified',
                 status='purchased'
             )[0]
         except IndexError:
             msg = _("No order found for {user} in course {course_id}").format(user=user, course_id=course_id)
             raise forms.ValidationError(msg)
     return self.cleaned_data
示例#25
0
 def test_admin_model_form_update(self):
     """
     Test CourseEnrollmentAdminForm update.
     """
     enrollment = CourseEnrollment.get_or_create_enrollment(
         self.user, self.course.id)
     count = CourseEnrollment.objects.count()
     form = CourseEnrollmentForm(
         {
             'user': self.user.id,
             'course': six.text_type(self.course.id),
             'is_active': False,
             'mode': 'audit'
         },
         instance=enrollment)
     self.assertTrue(form.is_valid())
     course_enrollment = form.save()
     self.assertEqual(count, CourseEnrollment.objects.count())
     self.assertFalse(course_enrollment.is_active)
     self.assertEqual(enrollment.id, course_enrollment.id)
示例#26
0
def show_receipt(request, ordernum):
    """
    Displays a receipt for a particular order.
    404 if order is not yet purchased or request.user != order.user
    """

    try:
        order = Order.objects.get(id=ordernum)
    except Order.DoesNotExist:
        raise Http404('Order not found!')

    if order.user != request.user or order.status != 'purchased':
        raise Http404('Order not found!')

    order_items = OrderItem.objects.filter(order=order).select_subclasses()
    any_refunds = any(i.status == "refunded" for i in order_items)
    receipt_template = 'shoppingcart/receipt.html'
    __, instructions = order.generate_receipt_instructions()
    # we want to have the ability to override the default receipt page when
    # there is only one item in the order
    context = {
        'order': order,
        'order_items': order_items,
        'any_refunds': any_refunds,
        'instructions': instructions,
    }

    if order_items.count() == 1:
        receipt_template = order_items[0].single_item_receipt_template
        context.update(order_items[0].single_item_receipt_context)

    # Only orders where order_items.count() == 1 might be attempting to upgrade
    attempting_upgrade = request.session.get('attempting_upgrade', False)
    if attempting_upgrade:
        course_enrollment = CourseEnrollment.get_or_create_enrollment(
            request.user, order_items[0].course_id)
        course_enrollment.emit_event(EVENT_NAME_USER_UPGRADED)
        request.session['attempting_upgrade'] = False

    return render_to_response(receipt_template, context)
示例#27
0
    def test_activation(self):
        user = User.objects.create(username="******", email="*****@*****.**")
        course_id = "edX/Test101/2013"
        self.assertFalse(CourseEnrollment.is_enrolled(user, course_id))

        # Creating an enrollment doesn't actually enroll a student
        # (calling CourseEnrollment.enroll() would have)
        enrollment = CourseEnrollment.get_or_create_enrollment(user, course_id)
        self.assertFalse(CourseEnrollment.is_enrolled(user, course_id))
        self.assert_no_events_were_emitted()

        # Until you explicitly activate it
        enrollment.activate()
        self.assertTrue(CourseEnrollment.is_enrolled(user, course_id))
        self.assert_enrollment_event_was_emitted(user, course_id)

        # Activating something that's already active does nothing
        enrollment.activate()
        self.assertTrue(CourseEnrollment.is_enrolled(user, course_id))
        self.assert_no_events_were_emitted()

        # Now deactive
        enrollment.deactivate()
        self.assertFalse(CourseEnrollment.is_enrolled(user, course_id))
        self.assert_unenrollment_event_was_emitted(user, course_id)

        # Deactivating something that's already inactive does nothing
        enrollment.deactivate()
        self.assertFalse(CourseEnrollment.is_enrolled(user, course_id))
        self.assert_no_events_were_emitted()

        # A deactivated enrollment should be activated if enroll() is called
        # for that user/course_id combination
        CourseEnrollment.enroll(user, course_id)
        self.assertTrue(CourseEnrollment.is_enrolled(user, course_id))
        self.assert_enrollment_event_was_emitted(user, course_id)
示例#28
0
    def test_activation(self):
        user = User.objects.create(username="******", email="*****@*****.**")
        course_id = SlashSeparatedCourseKey("edX", "Test101", "2013")
        self.assertFalse(CourseEnrollment.is_enrolled(user, course_id))

        # Creating an enrollment doesn't actually enroll a student
        # (calling CourseEnrollment.enroll() would have)
        enrollment = CourseEnrollment.get_or_create_enrollment(user, course_id)
        self.assertFalse(CourseEnrollment.is_enrolled(user, course_id))
        self.assert_no_events_were_emitted()

        # Until you explicitly activate it
        enrollment.activate()
        self.assertTrue(CourseEnrollment.is_enrolled(user, course_id))
        self.assert_enrollment_event_was_emitted(user, course_id)

        # Activating something that's already active does nothing
        enrollment.activate()
        self.assertTrue(CourseEnrollment.is_enrolled(user, course_id))
        self.assert_no_events_were_emitted()

        # Now deactive
        enrollment.deactivate()
        self.assertFalse(CourseEnrollment.is_enrolled(user, course_id))
        self.assert_unenrollment_event_was_emitted(user, course_id)

        # Deactivating something that's already inactive does nothing
        enrollment.deactivate()
        self.assertFalse(CourseEnrollment.is_enrolled(user, course_id))
        self.assert_no_events_were_emitted()

        # A deactivated enrollment should be activated if enroll() is called
        # for that user/course_id combination
        CourseEnrollment.enroll(user, course_id)
        self.assertTrue(CourseEnrollment.is_enrolled(user, course_id))
        self.assert_enrollment_event_was_emitted(user, course_id)
示例#29
0
def results_callback(request):
    """
    Software Secure will call this callback to tell us whether a user is
    verified to be who they said they are.
    """
    body = request.body

    try:
        body_dict = json.loads(body)
    except ValueError:
        log.exception(
            "Invalid JSON received from Software Secure:\n\n{}\n".format(body))
        return HttpResponseBadRequest(
            "Invalid JSON. Received:\n\n{}".format(body))

    if not isinstance(body_dict, dict):
        log.error(
            "Reply from Software Secure is not a dict:\n\n{}\n".format(body))
        return HttpResponseBadRequest(
            "JSON should be dict. Received:\n\n{}".format(body))

    headers = {
        "Authorization": request.META.get("HTTP_AUTHORIZATION", ""),
        "Date": request.META.get("HTTP_DATE", "")
    }

    sig_valid = ssencrypt.has_valid_signature(
        "POST", headers, body_dict,
        settings.VERIFY_STUDENT["SOFTWARE_SECURE"]["API_ACCESS_KEY"],
        settings.VERIFY_STUDENT["SOFTWARE_SECURE"]["API_SECRET_KEY"])

    _response, access_key_and_sig = headers["Authorization"].split(" ")
    access_key = access_key_and_sig.split(":")[0]

    # This is what we should be doing...
    #if not sig_valid:
    #    return HttpResponseBadRequest("Signature is invalid")

    # This is what we're doing until we can figure out why we disagree on sigs
    if access_key != settings.VERIFY_STUDENT["SOFTWARE_SECURE"][
            "API_ACCESS_KEY"]:
        return HttpResponseBadRequest("Access key invalid")

    receipt_id = body_dict.get("EdX-ID")
    result = body_dict.get("Result")
    reason = body_dict.get("Reason", "")
    error_code = body_dict.get("MessageType", "")

    try:
        attempt = SoftwareSecurePhotoVerification.objects.get(
            receipt_id=receipt_id)
    except SoftwareSecurePhotoVerification.DoesNotExist:
        log.error(
            "Software Secure posted back for receipt_id {}, but not found".
            format(receipt_id))
        return HttpResponseBadRequest("edX ID {} not found".format(receipt_id))

    if result == "PASS":
        log.debug("Approving verification for {}".format(receipt_id))
        attempt.approve()
    elif result == "FAIL":
        log.debug("Denying verification for {}".format(receipt_id))
        attempt.deny(json.dumps(reason), error_code=error_code)
    elif result == "SYSTEM FAIL":
        log.debug("System failure for {} -- resetting to must_retry".format(
            receipt_id))
        attempt.system_error(json.dumps(reason), error_code=error_code)
        log.error("Software Secure callback attempt for %s failed: %s",
                  receipt_id, reason)
    else:
        log.error("Software Secure returned unknown result {}".format(result))
        return HttpResponseBadRequest(
            "Result {} not understood. Known results: PASS, FAIL, SYSTEM FAIL".
            format(result))

    # If this is a reverification, log an event
    if attempt.window:
        course_id = attempt.window.course_id
        course_enrollment = CourseEnrollment.get_or_create_enrollment(
            attempt.user, course_id)
        course_enrollment.emit_event(
            EVENT_NAME_USER_REVERIFICATION_REVIEWED_BY_SOFTWARESECURE)

    return HttpResponse("OK!")
示例#30
0
def show_receipt(request, ordernum):
    """
    Displays a receipt for a particular order.
    404 if order is not yet purchased or request.user != order.user
    """

    try:
        order = Order.objects.get(id=ordernum)
    except Order.DoesNotExist:
        raise Http404('Order not found!')

    if order.user != request.user or order.status != 'purchased':
        raise Http404('Order not found!')

    order_items = OrderItem.objects.filter(order=order).select_subclasses()
    shoppingcart_items = []
    course_names_list = []
    for order_item in order_items:
        course_key = getattr(order_item, 'course_id')
        if course_key:
            course = get_course_by_id(course_key, depth=0)
            shoppingcart_items.append((order_item, course))
            course_names_list.append(course.display_name)

    appended_course_names = ", ".join(course_names_list)
    any_refunds = any(i.status == "refunded" for i in order_items)
    receipt_template = 'shoppingcart/receipt.html'
    __, instructions = order.generate_receipt_instructions()
    order_type = getattr(order, 'order_type')

    # Only orders where order_items.count() == 1 might be attempting to upgrade
    attempting_upgrade = request.session.get('attempting_upgrade', False)
    if attempting_upgrade:
        course_enrollment = CourseEnrollment.get_or_create_enrollment(
            request.user, order_items[0].course_id)
        course_enrollment.emit_event(EVENT_NAME_USER_UPGRADED)
        request.session['attempting_upgrade'] = False

    recipient_list = []
    registration_codes = None
    total_registration_codes = None
    recipient_list.append(getattr(order.user, 'email'))
    if order_type == OrderTypes.BUSINESS:
        registration_codes = CourseRegistrationCode.objects.filter(order=order)
        total_registration_codes = registration_codes.count()
        if order.company_contact_email:
            recipient_list.append(order.company_contact_email)
        if order.recipient_email:
            recipient_list.append(order.recipient_email)

    appended_recipient_emails = ", ".join(recipient_list)

    context = {
        'order': order,
        'shoppingcart_items': shoppingcart_items,
        'any_refunds': any_refunds,
        'instructions': instructions,
        'site_name': microsite.get_value('SITE_NAME', settings.SITE_NAME),
        'order_type': order_type,
        'appended_course_names': appended_course_names,
        'appended_recipient_emails': appended_recipient_emails,
        'currency_symbol': settings.PAID_COURSE_REGISTRATION_CURRENCY[1],
        'currency': settings.PAID_COURSE_REGISTRATION_CURRENCY[0],
        'total_registration_codes': total_registration_codes,
        'registration_codes': registration_codes,
        'order_purchase_date': order.purchase_time.strftime("%B %d, %Y"),
    }
    # we want to have the ability to override the default receipt page when
    # there is only one item in the order
    if order_items.count() == 1:
        receipt_template = order_items[0].single_item_receipt_template
        context.update(order_items[0].single_item_receipt_context)

    return render_to_response(receipt_template, context)
示例#31
0
def _show_receipt_html(request, order):
    """Render the receipt page as HTML.

    Arguments:
        request (HttpRequest): The request for the receipt.
        order (Order): The order model to display.

    Returns:
        HttpResponse

    """
    order_items = OrderItem.objects.filter(order=order).select_subclasses()
    shoppingcart_items = []
    course_names_list = []
    for order_item in order_items:
        course_key = getattr(order_item, 'course_id')
        if course_key:
            course = get_course_by_id(course_key, depth=0)
            shoppingcart_items.append((order_item, course))
            course_names_list.append(course.display_name)

    appended_course_names = ", ".join(course_names_list)
    any_refunds = any(i.status == "refunded" for i in order_items)
    receipt_template = 'shoppingcart/receipt.html'
    __, instructions = order.generate_receipt_instructions()
    order_type = getattr(order, 'order_type')

    # Only orders where order_items.count() == 1 might be attempting to upgrade
    attempting_upgrade = request.session.get('attempting_upgrade', False)
    if attempting_upgrade:
        course_enrollment = CourseEnrollment.get_or_create_enrollment(
            request.user, order_items[0].course_id)
        course_enrollment.emit_event(EVENT_NAME_USER_UPGRADED)
        request.session['attempting_upgrade'] = False

    recipient_list = []
    total_registration_codes = None
    reg_code_info_list = []
    recipient_list.append(getattr(order.user, 'email'))
    if order_type == OrderTypes.BUSINESS:
        if order.company_contact_email:
            recipient_list.append(order.company_contact_email)
        if order.recipient_email:
            recipient_list.append(order.recipient_email)

        for __, course in shoppingcart_items:
            course_registration_codes = CourseRegistrationCode.objects.filter(
                order=order, course_id=course.id)
            total_registration_codes = course_registration_codes.count()
            for course_registration_code in course_registration_codes:
                reg_code_info_list.append({
                    'course_name':
                    course.display_name,
                    'redemption_url':
                    reverse('register_code_redemption',
                            args=[course_registration_code.code]),
                    'code':
                    course_registration_code.code,
                    'is_redeemed':
                    RegistrationCodeRedemption.objects.filter(
                        registration_code=course_registration_code).exists(),
                })

    appended_recipient_emails = ", ".join(recipient_list)

    context = {
        'order': order,
        'shoppingcart_items': shoppingcart_items,
        'any_refunds': any_refunds,
        'instructions': instructions,
        'site_name': microsite.get_value('SITE_NAME', settings.SITE_NAME),
        'order_type': order_type,
        'appended_course_names': appended_course_names,
        'appended_recipient_emails': appended_recipient_emails,
        'currency_symbol': settings.PAID_COURSE_REGISTRATION_CURRENCY[1],
        'currency': settings.PAID_COURSE_REGISTRATION_CURRENCY[0],
        'total_registration_codes': total_registration_codes,
        'reg_code_info_list': reg_code_info_list,
        'order_purchase_date': order.purchase_time.strftime("%B %d, %Y"),
    }
    # we want to have the ability to override the default receipt page when
    # there is only one item in the order
    if order_items.count() == 1:
        receipt_template = order_items[0].single_item_receipt_template
        context.update(order_items[0].single_item_receipt_context)

    return render_to_response(receipt_template, context)
    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))
示例#33
0
def results_callback(request):
    """
    Software Secure will call this callback to tell us whether a user is
    verified to be who they said they are.
    """
    body = request.body

    try:
        body_dict = json.loads(body)
    except ValueError:
        log.exception("Invalid JSON received from Software Secure:\n\n{}\n".format(body))
        return HttpResponseBadRequest("Invalid JSON. Received:\n\n{}".format(body))

    if not isinstance(body_dict, dict):
        log.error("Reply from Software Secure is not a dict:\n\n{}\n".format(body))
        return HttpResponseBadRequest("JSON should be dict. Received:\n\n{}".format(body))

    headers = {
        "Authorization": request.META.get("HTTP_AUTHORIZATION", ""),
        "Date": request.META.get("HTTP_DATE", "")
    }

    sig_valid = ssencrypt.has_valid_signature(
        "POST",
        headers,
        body_dict,
        settings.VERIFY_STUDENT["SOFTWARE_SECURE"]["API_ACCESS_KEY"],
        settings.VERIFY_STUDENT["SOFTWARE_SECURE"]["API_SECRET_KEY"]
    )

    _response, access_key_and_sig = headers["Authorization"].split(" ")
    access_key = access_key_and_sig.split(":")[0]

    # This is what we should be doing...
    #if not sig_valid:
    #    return HttpResponseBadRequest("Signature is invalid")

    # This is what we're doing until we can figure out why we disagree on sigs
    if access_key != settings.VERIFY_STUDENT["SOFTWARE_SECURE"]["API_ACCESS_KEY"]:
        return HttpResponseBadRequest("Access key invalid")

    receipt_id = body_dict.get("EdX-ID")
    result = body_dict.get("Result")
    reason = body_dict.get("Reason", "")
    error_code = body_dict.get("MessageType", "")

    try:
        attempt = SoftwareSecurePhotoVerification.objects.get(receipt_id=receipt_id)
    except SoftwareSecurePhotoVerification.DoesNotExist:
        log.error("Software Secure posted back for receipt_id {}, but not found".format(receipt_id))
        return HttpResponseBadRequest("edX ID {} not found".format(receipt_id))

    if result == "PASS":
        log.debug("Approving verification for {}".format(receipt_id))
        attempt.approve()
    elif result == "FAIL":
        log.debug("Denying verification for {}".format(receipt_id))
        attempt.deny(json.dumps(reason), error_code=error_code)
    elif result == "SYSTEM FAIL":
        log.debug("System failure for {} -- resetting to must_retry".format(receipt_id))
        attempt.system_error(json.dumps(reason), error_code=error_code)
        log.error("Software Secure callback attempt for %s failed: %s", receipt_id, reason)
    else:
        log.error("Software Secure returned unknown result {}".format(result))
        return HttpResponseBadRequest(
            "Result {} not understood. Known results: PASS, FAIL, SYSTEM FAIL".format(result)
        )

    # If this is a reverification, log an event
    if attempt.window:
        course_id = attempt.window.course_id
        course_enrollment = CourseEnrollment.get_or_create_enrollment(attempt.user, course_id)
        course_enrollment.emit_event(EVENT_NAME_USER_REVERIFICATION_REVIEWED_BY_SOFTWARESECURE)

    return HttpResponse("OK!")
示例#34
0
def _show_receipt_html(request, order):
    """Render the receipt page as HTML.

    Arguments:
        request (HttpRequest): The request for the receipt.
        order (Order): The order model to display.

    Returns:
        HttpResponse

    """
    order_items = OrderItem.objects.filter(order=order).select_subclasses()
    shoppingcart_items = []
    course_names_list = []
    for order_item in order_items:
        course_key = getattr(order_item, 'course_id')
        if course_key:
            course = get_course_by_id(course_key, depth=0)
            shoppingcart_items.append((order_item, course))
            course_names_list.append(course.display_name)

    appended_course_names = ", ".join(course_names_list)
    any_refunds = any(i.status == "refunded" for i in order_items)
    receipt_template = 'shoppingcart/receipt.html'
    __, instructions = order.generate_receipt_instructions()
    order_type = getattr(order, 'order_type')

    # Only orders where order_items.count() == 1 might be attempting to upgrade
    attempting_upgrade = request.session.get('attempting_upgrade', False)
    if attempting_upgrade:
        course_enrollment = CourseEnrollment.get_or_create_enrollment(request.user, order_items[0].course_id)
        course_enrollment.emit_event(EVENT_NAME_USER_UPGRADED)
        request.session['attempting_upgrade'] = False

    recipient_list = []
    total_registration_codes = None
    reg_code_info_list = []
    recipient_list.append(getattr(order.user, 'email'))
    if order_type == OrderTypes.BUSINESS:
        if order.company_contact_email:
            recipient_list.append(order.company_contact_email)
        if order.recipient_email:
            recipient_list.append(order.recipient_email)

        for __, course in shoppingcart_items:
            course_registration_codes = CourseRegistrationCode.objects.filter(order=order, course_id=course.id)
            total_registration_codes = course_registration_codes.count()
            for course_registration_code in course_registration_codes:
                reg_code_info_list.append({
                    'course_name': course.display_name,
                    'redemption_url': reverse('register_code_redemption', args=[course_registration_code.code]),
                    'code': course_registration_code.code,
                    'is_redeemed': RegistrationCodeRedemption.objects.filter(
                        registration_code=course_registration_code).exists(),
                })

    appended_recipient_emails = ", ".join(recipient_list)

    context = {
        'order': order,
        'shoppingcart_items': shoppingcart_items,
        'any_refunds': any_refunds,
        'instructions': instructions,
        'site_name': microsite.get_value('SITE_NAME', settings.SITE_NAME),
        'order_type': order_type,
        'appended_course_names': appended_course_names,
        'appended_recipient_emails': appended_recipient_emails,
        'currency_symbol': settings.PAID_COURSE_REGISTRATION_CURRENCY[1],
        'currency': settings.PAID_COURSE_REGISTRATION_CURRENCY[0],
        'total_registration_codes': total_registration_codes,
        'reg_code_info_list': reg_code_info_list,
        'order_purchase_date': order.purchase_time.strftime("%B %d, %Y"),
    }
    # We want to have the ability to override the default receipt page when
    # there is only one item in the order.
    if order_items.count() == 1:
        receipt_template = order_items[0].single_item_receipt_template
        context.update(order_items[0].single_item_receipt_context)

        # Ideally, the shoppingcart app would own the receipt view. However,
        # as a result of changes made to the payment and verification flows as
        # part of an A/B test, the verify_student app owns it instead. This is
        # left over, and will be made more general in the future.
        if receipt_template == 'shoppingcart/verified_cert_receipt.html':
            url = reverse(
                'verify_student_payment_confirmation',
                kwargs={'course_id': unicode(order_items[0].course_id)}
            )

            # Add a query string param for the order ID
            # This allows the view to query for the receipt information later.
            url += '?payment-order-num={order_num}'.format(
                order_num=order_items[0].order.id
            )
            return HttpResponseRedirect(url)

    return render_to_response(receipt_template, context)
示例#35
0
def _show_receipt_html(request, order):
    """Render the receipt page as HTML.

    Arguments:
        request (HttpRequest): The request for the receipt.
        order (Order): The order model to display.

    Returns:
        HttpResponse

    """
    order_items = OrderItem.objects.filter(order=order).select_subclasses()
    shoppingcart_items = []
    course_names_list = []
    for order_item in order_items:
        course_key = getattr(order_item, 'course_id')
        if course_key:
            course = get_course_by_id(course_key, depth=0)
            shoppingcart_items.append((order_item, course))
            course_names_list.append(course.display_name)

    appended_course_names = ", ".join(course_names_list)
    any_refunds = any(i.status == "refunded" for i in order_items)
    receipt_template = 'shoppingcart/receipt.html'
    __, instructions = order.generate_receipt_instructions()
    order_type = getattr(order, 'order_type')

    # Only orders where order_items.count() == 1 might be attempting to upgrade
    attempting_upgrade = request.session.get('attempting_upgrade', False)
    if attempting_upgrade:
        course_enrollment = CourseEnrollment.get_or_create_enrollment(request.user, order_items[0].course_id)
        course_enrollment.emit_event(EVENT_NAME_USER_UPGRADED)
        request.session['attempting_upgrade'] = False

    recipient_list = []
    total_registration_codes = None
    reg_code_info_list = []
    recipient_list.append(getattr(order.user, 'email'))
    if order_type == OrderTypes.BUSINESS:
        if order.company_contact_email:
            recipient_list.append(order.company_contact_email)
        if order.recipient_email:
            recipient_list.append(order.recipient_email)

        for __, course in shoppingcart_items:
            course_registration_codes = CourseRegistrationCode.objects.filter(order=order, course_id=course.id)
            total_registration_codes = course_registration_codes.count()
            for course_registration_code in course_registration_codes:
                reg_code_info_list.append({
                    'course_name': course.display_name,
                    'redemption_url': reverse('register_code_redemption', args=[course_registration_code.code]),
                    'code': course_registration_code.code,
                    'is_redeemed': RegistrationCodeRedemption.objects.filter(
                        registration_code=course_registration_code).exists(),
                })

    appended_recipient_emails = ", ".join(recipient_list)

    context = {
        'order': order,
        'shoppingcart_items': shoppingcart_items,
        'any_refunds': any_refunds,
        'instructions': instructions,
        'site_name': microsite.get_value('SITE_NAME', settings.SITE_NAME),
        'order_type': order_type,
        'appended_course_names': appended_course_names,
        'appended_recipient_emails': appended_recipient_emails,
        'currency_symbol': settings.PAID_COURSE_REGISTRATION_CURRENCY[1],
        'currency': settings.PAID_COURSE_REGISTRATION_CURRENCY[0],
        'total_registration_codes': total_registration_codes,
        'reg_code_info_list': reg_code_info_list,
        'order_purchase_date': order.purchase_time.strftime("%B %d, %Y"),
    }
    # we want to have the ability to override the default receipt page when
    # there is only one item in the order
    if order_items.count() == 1:
        receipt_template = order_items[0].single_item_receipt_template
        context.update(order_items[0].single_item_receipt_context)

    return render_to_response(receipt_template, context)
示例#36
0
def show_receipt(request, ordernum):
    """
    Displays a receipt for a particular order.
    404 if order is not yet purchased or request.user != order.user
    """

    try:
        order = Order.objects.get(id=ordernum)
    except Order.DoesNotExist:
        raise Http404('Order not found!')

    if order.user != request.user or order.status != 'purchased':
        raise Http404('Order not found!')

    order_items = OrderItem.objects.filter(order=order).select_subclasses()
    shoppingcart_items = []
    course_names_list = []
    for order_item in order_items:
        course_key = getattr(order_item, 'course_id')
        if course_key:
            course = get_course_by_id(course_key, depth=0)
            shoppingcart_items.append((order_item, course))
            course_names_list.append(course.display_name)

    appended_course_names = ", ".join(course_names_list)
    any_refunds = any(i.status == "refunded" for i in order_items)
    receipt_template = 'shoppingcart/receipt.html'
    __, instructions = order.generate_receipt_instructions()
    order_type = getattr(order, 'order_type')

    # Only orders where order_items.count() == 1 might be attempting to upgrade
    attempting_upgrade = request.session.get('attempting_upgrade', False)
    if attempting_upgrade:
        course_enrollment = CourseEnrollment.get_or_create_enrollment(request.user, order_items[0].course_id)
        course_enrollment.emit_event(EVENT_NAME_USER_UPGRADED)
        request.session['attempting_upgrade'] = False

    recipient_list = []
    registration_codes = None
    total_registration_codes = None
    recipient_list.append(getattr(order.user, 'email'))
    if order_type == OrderTypes.BUSINESS:
        registration_codes = CourseRegistrationCode.objects.filter(order=order)
        total_registration_codes = registration_codes.count()
        if order.company_contact_email:
            recipient_list.append(order.company_contact_email)
        if order.recipient_email:
            recipient_list.append(order.recipient_email)

    appended_recipient_emails = ", ".join(recipient_list)

    context = {
        'order': order,
        'shoppingcart_items': shoppingcart_items,
        'any_refunds': any_refunds,
        'instructions': instructions,
        'site_name': microsite.get_value('SITE_NAME', settings.SITE_NAME),
        'order_type': order_type,
        'appended_course_names': appended_course_names,
        'appended_recipient_emails': appended_recipient_emails,
        'total_registration_codes': total_registration_codes,
        'registration_codes': registration_codes,
        'order_purchase_date': order.purchase_time.strftime("%B %d, %Y"),
    }
    # we want to have the ability to override the default receipt page when
    # there is only one item in the order
    if order_items.count() == 1:
        receipt_template = order_items[0].single_item_receipt_template
        context.update(order_items[0].single_item_receipt_context)

    return render_to_response(receipt_template, context)
示例#37
0
def _show_receipt_html(request, order):
    """Render the receipt page as HTML.

    Arguments:
        request (HttpRequest): The request for the receipt.
        order (Order): The order model to display.

    Returns:
        HttpResponse

    """
    order_items = OrderItem.objects.filter(order=order).select_subclasses()
    shoppingcart_items = []
    course_names_list = []
    for order_item in order_items:
        course_key = getattr(order_item, 'course_id')
        if course_key:
            course = get_course_by_id(course_key, depth=0)
            shoppingcart_items.append((order_item, course))
            course_names_list.append(course.display_name)

    appended_course_names = ", ".join(course_names_list)
    any_refunds = any(i.status == "refunded" for i in order_items)
    receipt_template = 'shoppingcart/receipt.html'
    __, instructions = order.generate_receipt_instructions()
    order_type = getattr(order, 'order_type')

    # Only orders where order_items.count() == 1 might be attempting to upgrade
    attempting_upgrade = request.session.get('attempting_upgrade', False)
    if attempting_upgrade:
        course_enrollment = CourseEnrollment.get_or_create_enrollment(request.user, order_items[0].course_id)
        course_enrollment.emit_event(EVENT_NAME_USER_UPGRADED)
        request.session['attempting_upgrade'] = False

    recipient_list = []
    total_registration_codes = None
    reg_code_info_list = []
    recipient_list.append(getattr(order.user, 'email'))
    if order_type == OrderTypes.BUSINESS:
        if order.company_contact_email:
            recipient_list.append(order.company_contact_email)
        if order.recipient_email:
            recipient_list.append(order.recipient_email)

        for __, course in shoppingcart_items:
            course_registration_codes = CourseRegistrationCode.objects.filter(order=order, course_id=course.id)
            total_registration_codes = course_registration_codes.count()
            for course_registration_code in course_registration_codes:
                reg_code_info_list.append({
                    'course_name': course.display_name,
                    'redemption_url': reverse('register_code_redemption', args=[course_registration_code.code]),
                    'code': course_registration_code.code,
                    'is_redeemed': RegistrationCodeRedemption.objects.filter(
                        registration_code=course_registration_code).exists(),
                })

    appended_recipient_emails = ", ".join(recipient_list)

    context = {
        'order': order,
        'shoppingcart_items': shoppingcart_items,
        'any_refunds': any_refunds,
        'instructions': instructions,
        'site_name': microsite.get_value('SITE_NAME', settings.SITE_NAME),
        'order_type': order_type,
        'appended_course_names': appended_course_names,
        'appended_recipient_emails': appended_recipient_emails,
        'currency_symbol': settings.PAID_COURSE_REGISTRATION_CURRENCY[1],
        'currency': settings.PAID_COURSE_REGISTRATION_CURRENCY[0],
        'total_registration_codes': total_registration_codes,
        'reg_code_info_list': reg_code_info_list,
        'order_purchase_date': order.purchase_time.strftime("%B %d, %Y"),
    }
    # we want to have the ability to override the default receipt page when
    # there is only one item in the order
    if order_items.count() == 1:
        receipt_template = order_items[0].single_item_receipt_template
        context.update(order_items[0].single_item_receipt_context)

        # TODO (ECOM-188): Once the A/B test of separate verified / payment flow
        # completes, implement this in a more general way.  For now,
        # we simply redirect to the new receipt page (in verify_student).
        if settings.FEATURES.get('SEPARATE_VERIFICATION_FROM_PAYMENT') and request.session.get('separate-verified', False):
            if receipt_template == 'shoppingcart/verified_cert_receipt.html':
                url = reverse(
                    'verify_student_payment_confirmation',
                    kwargs={'course_id': unicode(order_items[0].course_id)}
                )

                # Add a query string param for the order ID
                # This allows the view to query for the receipt information later.
                url += '?payment-order-num={order_num}'.format(
                    order_num=order_items[0].id
                )
                return HttpResponseRedirect(url)

    return render_to_response(receipt_template, context)
    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))
示例#39
0
 def course_enrollment(self, create, extracted, **kwargs):
     CourseEnrollment.get_or_create_enrollment(
         course_key=self.course_key,
         user=self.user,
     )