Ejemplo n.º 1
0
    def test_confirmation_email_error(self):
        CourseMode.objects.create(
            course_id=self.course_key,
            mode_slug="verified",
            mode_display_name="Verified",
            min_price=self.cost
        )

        cart = Order.get_cart_for_user(self.user)
        CertificateItem.add_to_order(cart, self.course_key, self.cost, 'verified')

        # Simulate an error when sending the confirmation
        # email.  This should NOT raise an exception.
        # If it does, then the implicit view-level
        # transaction could cause a roll-back, effectively
        # reversing order fulfillment.
        with patch.object(mail.message.EmailMessage, 'send') as mock_send:
            mock_send.side_effect = Exception("Kaboom!")
            cart.purchase()

        # Verify that the purchase completed successfully
        self.assertEqual(cart.status, 'purchased')

        # Verify that the user is enrolled as "verified"
        mode, is_active = CourseEnrollment.enrollment_mode_for_user(self.user, self.course_key)
        self.assertTrue(is_active)
        self.assertEqual(mode, 'verified')
Ejemplo n.º 2
0
    def test_refund_cert_callback_before_expiration(self):
        # If the expiration date has not yet passed on a verified mode, the user can be refunded
        many_days = datetime.timedelta(days=60)

        course = CourseFactory.create()
        self.course_key = course.id
        course_mode = CourseMode(course_id=self.course_key,
                                 mode_slug="verified",
                                 mode_display_name="verified cert",
                                 min_price=self.cost,
                                 expiration_datetime=(datetime.datetime.now(pytz.utc) + many_days))
        course_mode.save()

        # need to prevent analytics errors from appearing in stderr
        with patch('sys.stderr', sys.stdout.write):
            CourseEnrollment.enroll(self.user, self.course_key, 'verified')
            cart = Order.get_cart_for_user(user=self.user)
            CertificateItem.add_to_order(cart, self.course_key, self.cost, 'verified')
            cart.purchase()
            CourseEnrollment.unenroll(self.user, self.course_key)

        target_certs = CertificateItem.objects.filter(course_id=self.course_key, user_id=self.user, status='refunded', mode='verified')
        self.assertTrue(target_certs[0])
        self.assertTrue(target_certs[0].refund_requested_time)
        self.assertEquals(target_certs[0].order.status, 'refunded')
        self._assert_refund_tracked()
Ejemplo n.º 3
0
    def test_single_item_template(self):
        cart = Order.get_cart_for_user(user=self.user)
        cert_item = CertificateItem.add_to_order(cart, self.course_key, self.cost, 'verified')
        self.assertEquals(cert_item.single_item_receipt_template, 'shoppingcart/receipt.html')

        cert_item = CertificateItem.add_to_order(cart, self.course_key, self.cost, 'honor')
        self.assertEquals(cert_item.single_item_receipt_template, 'shoppingcart/receipt.html')
Ejemplo n.º 4
0
    def test_refund_cert_callback_before_expiration_email(self):
        """ Test that refund emails are being sent correctly. """
        course = CourseFactory.create()
        course_key = course.id
        many_days = datetime.timedelta(days=60)

        course_mode = CourseMode(course_id=course_key,
                                 mode_slug="verified",
                                 mode_display_name="verified cert",
                                 min_price=self.cost,
                                 expiration_datetime=datetime.datetime.now(pytz.utc) + many_days)
        course_mode.save()

        CourseEnrollment.enroll(self.user, course_key, 'verified')
        cart = Order.get_cart_for_user(user=self.user)
        CertificateItem.add_to_order(cart, course_key, self.cost, 'verified')
        cart.purchase()

        mail.outbox = []
        with patch('shoppingcart.models.log.error') as mock_error_logger:
            CourseEnrollment.unenroll(self.user, course_key)
            self.assertFalse(mock_error_logger.called)
            self.assertEquals(len(mail.outbox), 1)
            self.assertEquals('[Refund] User-Requested Refund', mail.outbox[0].subject)
            self.assertEquals(settings.PAYMENT_SUPPORT_EMAIL, mail.outbox[0].from_email)
            self.assertIn('has requested a refund on Order', mail.outbox[0].body)
Ejemplo n.º 5
0
    def test_refund_cert_callback_before_expiration(self):
        # If the expiration date has not yet passed on a verified mode, the user can be refunded
        many_days = datetime.timedelta(days=60)

        course = CourseFactory.create(org="refund_before_expiration", number="test", display_name="one")
        course_key = course.id
        course_mode = CourseMode(
            course_id=course_key,
            mode_slug="verified",
            mode_display_name="verified cert",
            min_price=self.cost,
            expiration_datetime=(datetime.datetime.now(pytz.utc) + many_days),
        )
        course_mode.save()

        CourseEnrollment.enroll(self.user, course_key, "verified")
        cart = Order.get_cart_for_user(user=self.user)
        CertificateItem.add_to_order(cart, course_key, self.cost, "verified")
        cart.purchase()

        CourseEnrollment.unenroll(self.user, course_key)
        target_certs = CertificateItem.objects.filter(
            course_id=course_key, user_id=self.user, status="refunded", mode="verified"
        )
        self.assertTrue(target_certs[0])
        self.assertTrue(target_certs[0].refund_requested_time)
        self.assertEquals(target_certs[0].order.status, "refunded")
Ejemplo n.º 6
0
 def test_purchase_twice(self):
     cart = Order.get_cart_for_user(self.user)
     CertificateItem.add_to_order(cart, self.course_id, self.cost, 'honor')
     # purchase the cart more than once
     cart.purchase()
     cart.purchase()
     self.assertEquals(len(mail.outbox), 1)
Ejemplo n.º 7
0
def checkout_with_shoppingcart(request, user, course_key, course_mode, amount):
    """ Create an order and trigger checkout using shoppingcart."""
    cart = Order.get_cart_for_user(user)
    cart.clear()
    enrollment_mode = course_mode.slug
    CertificateItem.add_to_order(cart, course_key, amount, enrollment_mode)

    # Change the order's status so that we don't accidentally modify it later.
    # We need to do this to ensure that the parameters we send to the payment system
    # match what we store in the database.
    # (Ordinarily we would do this client-side when the user submits the form, but since
    # the JavaScript on this page does that immediately, we make the change here instead.
    # This avoids a second AJAX call and some additional complication of the JavaScript.)
    # If a user later re-enters the verification / payment flow, she will create a new order.
    cart.start_purchase()

    callback_url = request.build_absolute_uri(
        reverse("shoppingcart.views.postpay_callback")
    )

    payment_data = {
        'payment_processor_name': settings.CC_PROCESSOR_NAME,
        'payment_page_url': get_purchase_endpoint(),
        'payment_form_data': get_signed_purchase_params(
            cart,
            callback_url=callback_url,
            extra_data=[unicode(course_key), course_mode.slug]
        ),
    }
    return payment_data
Ejemplo n.º 8
0
 def test_cart_clear(self):
     cart = Order.get_cart_for_user(user=self.user)
     CertificateItem.add_to_order(cart, self.course_id, self.cost, 'verified')
     CertificateItem.add_to_order(cart, 'test/course1', self.cost, 'verified')
     self.assertEquals(cart.orderitem_set.count(), 2)
     cart.clear()
     self.assertEquals(cart.orderitem_set.count(), 0)
Ejemplo n.º 9
0
 def test_purchase_item_email_boto_failure(self, error_logger):
     cart = Order.get_cart_for_user(user=self.user)
     CertificateItem.add_to_order(cart, self.course_key, self.cost, 'honor')
     with patch.object(EmailMessage, 'send') as mock_send:
         mock_send.side_effect = BotoServerError("status", "reason")
         cart.purchase()
         self.assertTrue(error_logger.called)
Ejemplo n.º 10
0
    def test_start_purchase(self):
        # Start the purchase, which will mark the cart as "paying"
        cart = Order.get_cart_for_user(user=self.user)
        CertificateItem.add_to_order(cart, self.course_key, self.cost, 'honor', currency='usd')
        cart.start_purchase()
        self.assertEqual(cart.status, 'paying')
        for item in cart.orderitem_set.all():
            self.assertEqual(item.status, 'paying')

        # Starting the purchase should be idempotent
        cart.start_purchase()
        self.assertEqual(cart.status, 'paying')
        for item in cart.orderitem_set.all():
            self.assertEqual(item.status, 'paying')

        # If we retrieve the cart for the user, we should get a different order
        next_cart = Order.get_cart_for_user(user=self.user)
        self.assertNotEqual(cart, next_cart)
        self.assertEqual(next_cart.status, 'cart')

        # Complete the first purchase
        cart.purchase()
        self.assertEqual(cart.status, 'purchased')
        for item in cart.orderitem_set.all():
            self.assertEqual(item.status, 'purchased')

        # Starting the purchase again should be a no-op
        cart.start_purchase()
        self.assertEqual(cart.status, 'purchased')
        for item in cart.orderitem_set.all():
            self.assertEqual(item.status, 'purchased')
Ejemplo n.º 11
0
 def test_clear_cart(self):
     self.login_user()
     PaidCourseRegistration.add_to_order(self.cart, self.course_key)
     CertificateItem.add_to_order(self.cart, self.verified_course_key, self.cost, 'honor')
     self.assertEquals(self.cart.orderitem_set.count(), 2)
     resp = self.client.post(reverse('shoppingcart.views.clear_cart', args=[]))
     self.assertEqual(resp.status_code, 200)
     self.assertEquals(self.cart.orderitem_set.count(), 0)
Ejemplo n.º 12
0
    def test_retire_order_cart(self):
        """Test that an order in cart can successfully be retired"""
        cart = Order.get_cart_for_user(user=self.user)
        CertificateItem.add_to_order(cart, self.course_key, self.cost, 'honor', currency='usd')

        cart.retire()
        self.assertEqual(cart.status, 'defunct-cart')
        self.assertEqual(cart.orderitem_set.get().status, 'defunct-cart')
Ejemplo n.º 13
0
 def test_get_cart_for_user(self):
     # create a cart
     cart = Order.get_cart_for_user(user=self.user)
     # add something to it
     CertificateItem.add_to_order(cart, self.course_id, self.cost, 'verified')
     # should return the same cart
     cart2 = Order.get_cart_for_user(user=self.user)
     self.assertEquals(cart2.orderitem_set.count(), 1)
Ejemplo n.º 14
0
 def test_existing_enrollment(self):
     CourseEnrollment.enroll(self.user, self.course_id)
     cart = Order.get_cart_for_user(user=self.user)
     CertificateItem.add_to_order(cart, self.course_id, self.cost, 'verified')
     # verify that we are still enrolled
     self.assertTrue(CourseEnrollment.is_enrolled(self.user, self.course_id))
     cart.purchase()
     enrollment = CourseEnrollment.objects.get(user=self.user, course_id=self.course_id)
     self.assertEquals(enrollment.mode, u'verified')
Ejemplo n.º 15
0
 def test_cart_clear(self):
     cart = Order.get_cart_for_user(user=self.user)
     CertificateItem.add_to_order(cart, self.course_id, self.cost, 'honor')
     CertificateItem.add_to_order(cart, 'org/test/Test_Course_1', self.cost, 'honor')
     self.assertEquals(cart.orderitem_set.count(), 2)
     self.assertTrue(cart.has_items())
     cart.clear()
     self.assertEquals(cart.orderitem_set.count(), 0)
     self.assertFalse(cart.has_items())
Ejemplo n.º 16
0
 def test_user_cart_has_both_items(self):
     """
     This test exists b/c having both CertificateItem and PaidCourseRegistration in an order used to break
     PaidCourseRegistration.contained_in_order
     """
     cart = Order.get_cart_for_user(self.user)
     CertificateItem.add_to_order(cart, self.course_key, self.cost, 'honor')
     PaidCourseRegistration.add_to_order(self.cart, self.course_key)
     self.assertTrue(PaidCourseRegistration.contained_in_order(cart, self.course_key))
Ejemplo n.º 17
0
 def test_cart_clear(self):
     cart = Order.get_cart_for_user(user=self.user)
     CertificateItem.add_to_order(cart, self.course_key, self.cost, 'honor')
     CertificateItem.add_to_order(cart, SlashSeparatedCourseKey('org', 'test', 'Test_Course_1'), self.cost, 'honor')
     self.assertEquals(cart.orderitem_set.count(), 2)
     self.assertTrue(cart.has_items())
     cart.clear()
     self.assertEquals(cart.orderitem_set.count(), 0)
     self.assertFalse(cart.has_items())
Ejemplo n.º 18
0
 def _enroll(self, purchase=True):
     # pylint: disable=missing-docstring
     CourseEnrollment.enroll(self.student, self.course_id, self.course_mode.mode_slug)
     if purchase:
         self.order = Order.get_cart_for_user(self.student)
         CertificateItem.add_to_order(self.order, self.course_id, 1, self.course_mode.mode_slug)
         self.order.purchase()
     self.course_mode.expiration_datetime = datetime.datetime(1983, 4, 6, tzinfo=pytz.UTC)
     self.course_mode.save()
Ejemplo n.º 19
0
def create_order(request):
    """
    Submit PhotoVerification and create a new Order for this verified cert
    """
    if not SoftwareSecurePhotoVerification.user_has_valid_or_pending(request.user):
        attempt = SoftwareSecurePhotoVerification(user=request.user)
        b64_face_image = request.POST['face_image'].split(",")[1]
        b64_photo_id_image = request.POST['photo_id_image'].split(",")[1]

        attempt.upload_face_image(b64_face_image.decode('base64'))
        attempt.upload_photo_id_image(b64_photo_id_image.decode('base64'))
        attempt.mark_ready()

        attempt.save()

    course_id = request.POST['course_id']
    course_id = SlashSeparatedCourseKey.from_deprecated_string(course_id)
    donation_for_course = request.session.get('donation_for_course', {})
    current_donation = donation_for_course.get(course_id, decimal.Decimal(0))
    contribution = request.POST.get("contribution", donation_for_course.get(course_id, 0))
    try:
        amount = decimal.Decimal(contribution).quantize(decimal.Decimal('.01'), rounding=decimal.ROUND_DOWN)
    except decimal.InvalidOperation:
        return HttpResponseBadRequest(_("Selected price is not valid number."))

    if amount != current_donation:
        donation_for_course[course_id] = amount
        request.session['donation_for_course'] = donation_for_course

    # prefer professional mode over verified_mode
    current_mode = CourseMode.verified_mode_for_course(course_id)

    if current_mode.slug == 'professional':
        amount = current_mode.min_price

    # make sure this course has a verified mode
    if not current_mode:
        return HttpResponseBadRequest(_("This course doesn't support verified certificates"))

    if amount < current_mode.min_price:
        return HttpResponseBadRequest(_("No selected price or selected price is below minimum."))

    # I know, we should check this is valid. All kinds of stuff missing here
    cart = Order.get_cart_for_user(request.user)
    cart.clear()
    enrollment_mode = current_mode.slug
    CertificateItem.add_to_order(cart, course_id, amount, enrollment_mode)

    callback_url = request.build_absolute_uri(
        reverse("shoppingcart.views.postpay_callback")
    )
    params = get_signed_purchase_params(
        cart, callback_url=callback_url
    )

    return HttpResponse(json.dumps(params), content_type="text/json")
Ejemplo n.º 20
0
    def test_refund_cert_callback_no_expiration(self):
        # When there is no expiration date on a verified mode, the user can always get a refund
        CourseEnrollment.enroll(self.user, self.course_id, 'verified')
        cart = Order.get_cart_for_user(user=self.user)
        CertificateItem.add_to_order(cart, self.course_id, self.cost, 'verified')
        cart.purchase()

        CourseEnrollment.unenroll(self.user, self.course_id)
        target_certs = CertificateItem.objects.filter(course_id=self.course_id, user_id=self.user, status='refunded', mode='verified')
        self.assertTrue(target_certs[0])
Ejemplo n.º 21
0
 def test_purchase_item_failure(self):
     # once again, we're testing against the specific implementation of
     # CertificateItem
     cart = Order.get_cart_for_user(user=self.user)
     CertificateItem.add_to_order(cart, self.course_id, self.cost, 'verified')
     with patch('shoppingcart.models.CertificateItem.save', side_effect=DatabaseError):
         with self.assertRaises(DatabaseError):
             cart.purchase()
             # verify that we rolled back the entire transaction
             self.assertFalse(CourseEnrollment.is_enrolled(self.user, self.course_id))
Ejemplo n.º 22
0
 def _create_and_purchase_verified(self, student, course_id):
     """ Creates a verified mode for the course and purchases it for the student. """
     course_mode = CourseMode(
         course_id=course_id, mode_slug="verified", mode_display_name="verified cert", min_price=50
     )
     course_mode.save()
     # When there is no expiration date on a verified mode, the user can always get a refund
     cart = Order.get_cart_for_user(user=student)
     CertificateItem.add_to_order(cart, course_id, 50, "verified")
     cart.purchase()
Ejemplo n.º 23
0
 def test_total_cost(self):
     cart = Order.get_cart_for_user(user=self.user)
     # add items to the order
     course_costs = [(self.other_course_keys[0], 30),
                     (self.other_course_keys[1], 40),
                     (self.other_course_keys[2], 10),
                     (self.other_course_keys[3], 20)]
     for course, cost in course_costs:
         CertificateItem.add_to_order(cart, course, cost, 'honor')
     self.assertEquals(cart.orderitem_set.count(), len(course_costs))
     self.assertEquals(cart.total_cost, sum(cost for _course, cost in course_costs))
Ejemplo n.º 24
0
 def test_add_item_to_cart_currency_match(self):
     cart = Order.get_cart_for_user(user=self.user)
     CertificateItem.add_to_order(cart, self.course_id, self.cost, 'verified', currency='eur')
     # verify that a new item has been added
     self.assertEquals(cart.orderitem_set.count(), 1)
     # verify that the cart's currency was updated
     self.assertEquals(cart.currency, 'eur')
     with self.assertRaises(InvalidCartItem):
         CertificateItem.add_to_order(cart, self.course_id, self.cost, 'verified', currency='usd')
     # assert that this item did not get added to the cart
     self.assertEquals(cart.orderitem_set.count(), 1)
Ejemplo n.º 25
0
 def test_purchase(self):
     # This test is for testing the subclassing functionality of OrderItem, but in
     # order to do this, we end up testing the specific functionality of
     # CertificateItem, which is not quite good unit test form. Sorry.
     cart = Order.get_cart_for_user(user=self.user)
     self.assertFalse(CourseEnrollment.is_enrolled(self.user, self.course_id))
     CertificateItem.add_to_order(cart, self.course_id, self.cost, 'verified')
     # course enrollment object should be created but still inactive
     self.assertFalse(CourseEnrollment.is_enrolled(self.user, self.course_id))
     cart.purchase()
     self.assertTrue(CourseEnrollment.is_enrolled(self.user, self.course_id))
Ejemplo n.º 26
0
 def test_total_cost(self):
     cart = Order.get_cart_for_user(user=self.user)
     # add items to the order
     course_costs = [('test/course1', 30),
                     ('test/course2', 40),
                     ('test/course3', 10),
                     ('test/course4', 20)]
     for course, cost in course_costs:
         CertificateItem.add_to_order(cart, course, cost, 'verified')
     self.assertEquals(cart.orderitem_set.count(), len(course_costs))
     self.assertEquals(cart.total_cost, sum(cost for _course, cost in course_costs))
Ejemplo n.º 27
0
 def test_total_cost(self):
     cart = Order.get_cart_for_user(user=self.user)
     # add items to the order
     course_costs = [('org/test/Test_Course_1', 30),
                     ('org/test/Test_Course_2', 40),
                     ('org/test/Test_Course_3', 10),
                     ('org/test/Test_Course_4', 20)]
     for course, cost in course_costs:
         CertificateItem.add_to_order(cart, SlashSeparatedCourseKey.from_deprecated_string(course), cost, 'honor')
     self.assertEquals(cart.orderitem_set.count(), len(course_costs))
     self.assertEquals(cart.total_cost, sum(cost for _course, cost in course_costs))
Ejemplo n.º 28
0
    def rows(self):
        for course_id in course_ids_between(self.start_word, self.end_word):
            # If the first letter of the university is between start_word and end_word, then we include
            # it in the report.  These comparisons are unicode-safe.
            cur_course = get_course_by_id(course_id)
            university = cur_course.org
            # TODO add term (i.e. Fall 2013) to course?
            course = cur_course.number + " " + cur_course.display_name_with_default_escaped
            counts = CourseEnrollment.objects.enrollment_counts(course_id)
            total_enrolled = counts['total']
            audit_enrolled = counts['audit']
            honor_enrolled = counts['honor']

            if counts['verified'] == 0:
                verified_enrolled = 0
                gross_rev = Decimal(0.00)
                gross_rev_over_min = Decimal(0.00)
            else:
                verified_enrolled = counts['verified']
                gross_rev = CertificateItem.verified_certificates_monetary_field_sum(course_id, 'purchased', 'unit_cost')
                gross_rev_over_min = gross_rev - (CourseMode.min_course_price_for_verified_for_currency(course_id, 'usd') * verified_enrolled)

            num_verified_over_the_minimum = CertificateItem.verified_certificates_contributing_more_than_minimum(course_id)

            # should I be worried about is_active here?
            number_of_refunds = CertificateItem.verified_certificates_count(course_id, 'refunded')
            if number_of_refunds == 0:
                dollars_refunded = Decimal(0.00)
            else:
                dollars_refunded = CertificateItem.verified_certificates_monetary_field_sum(course_id, 'refunded', 'unit_cost')

            course_announce_date = ""
            course_reg_start_date = ""
            course_reg_close_date = ""
            registration_period = ""

            yield [
                university,
                course,
                course_announce_date,
                course_reg_start_date,
                course_reg_close_date,
                registration_period,
                total_enrolled,
                audit_enrolled,
                honor_enrolled,
                verified_enrolled,
                gross_rev,
                gross_rev_over_min,
                num_verified_over_the_minimum,
                number_of_refunds,
                dollars_refunded
            ]
Ejemplo n.º 29
0
 def test_purchase_item_failure(self):
     # once again, we're testing against the specific implementation of
     # CertificateItem
     cart = Order.get_cart_for_user(user=self.user)
     CertificateItem.add_to_order(cart, self.course_key, self.cost, "honor")
     with patch("shoppingcart.models.CertificateItem.save", side_effect=DatabaseError):
         with self.assertRaises(DatabaseError):
             cart.purchase()
             # verify that we rolled back the entire transaction
             self.assertFalse(CourseEnrollment.is_enrolled(self.user, self.course_key))
             # verify that e-mail wasn't sent
             self.assertEquals(len(mail.outbox), 0)
Ejemplo n.º 30
0
    def test_refund_cert_callback_no_expiration(self):
        # When there is no expiration date on a verified mode, the user can always get a refund
        CourseEnrollment.enroll(self.user, self.course_key, "verified")
        cart = Order.get_cart_for_user(user=self.user)
        CertificateItem.add_to_order(cart, self.course_key, self.cost, "verified")
        cart.purchase()

        CourseEnrollment.unenroll(self.user, self.course_key)
        target_certs = CertificateItem.objects.filter(
            course_id=self.course_key, user_id=self.user, status="refunded", mode="verified"
        )
        self.assertTrue(target_certs[0])
        self.assertTrue(target_certs[0].refund_requested_time)
        self.assertEquals(target_certs[0].order.status, "refunded")
Ejemplo n.º 31
0
    def test_retire_order_error(self, order_status, item_status, exception):
        """
        Test error cases for retiring an order:
        1) Order item has a different status than the order
        2) The order's status isn't in "cart" or "paying"
        """
        cart = Order.get_cart_for_user(user=self.user)
        item = CertificateItem.add_to_order(cart, self.course_key, self.cost, 'honor', currency='usd')

        cart.status = order_status
        cart.save()
        item.status = item_status
        item.save()

        with self.assertRaises(exception):
            cart.retire()
Ejemplo n.º 32
0
 def test_retire_order_already_retired(self, status):
     """
     Check that orders that have already been retired noop when the method
     is called on them again.
     """
     cart = Order.get_cart_for_user(user=self.user)
     item = CertificateItem.add_to_order(cart,
                                         self.course_key,
                                         self.cost,
                                         'honor',
                                         currency='usd')
     cart.status = item.status = status
     cart.save()
     item.save()
     cart.retire()
     self.assertEqual(cart.status, status)
     self.assertEqual(item.status, status)
Ejemplo n.º 33
0
    def setUp(self):
        self.user = UserFactory.create()
        self.cost = 40
        self.course = CourseFactory.create(org='MITx',
                                           number='999',
                                           display_name=u'Robot Super Course')
        self.course_key = self.course.id
        course_mode = CourseMode(course_id=self.course_key,
                                 mode_slug="honor",
                                 mode_display_name="honor cert",
                                 min_price=self.cost)
        course_mode.save()
        course_mode2 = CourseMode(course_id=self.course_key,
                                  mode_slug="verified",
                                  mode_display_name="verified cert",
                                  min_price=self.cost)
        course_mode2.save()
        self.annotation = PaidCourseRegistrationAnnotation(
            course_id=self.course_key, annotation=self.TEST_ANNOTATION)
        self.annotation.save()
        self.cart = Order.get_cart_for_user(self.user)
        self.reg = PaidCourseRegistration.add_to_order(self.cart,
                                                       self.course_key)
        self.cert_item = CertificateItem.add_to_order(self.cart,
                                                      self.course_key,
                                                      self.cost, 'verified')
        self.cart.purchase()
        self.now = datetime.datetime.now(pytz.UTC)

        paid_reg = PaidCourseRegistration.objects.get(
            course_id=self.course_key, user=self.user)
        paid_reg.fulfilled_time = self.now
        paid_reg.refund_requested_time = self.now
        paid_reg.save()

        cert = CertificateItem.objects.get(course_id=self.course_key,
                                           user=self.user)
        cert.fulfilled_time = self.now
        cert.refund_requested_time = self.now
        cert.save()

        self.CORRECT_CSV = dedent("""
            Purchase Time,Order ID,Status,Quantity,Unit Cost,Total Cost,Currency,Description,Comments
            {time_str},1,purchased,1,40,40,usd,Registration for Course: Robot Super Course,Ba\xc3\xbc\xe5\x8c\x85
            {time_str},1,purchased,1,40,40,usd,verified cert for course Robot Super Course,
            """.format(time_str=str(self.now)))
Ejemplo n.º 34
0
    def test_purchase(self):
        # This test is for testing the subclassing functionality of OrderItem, but in
        # order to do this, we end up testing the specific functionality of
        # CertificateItem, which is not quite good unit test form. Sorry.
        cart = Order.get_cart_for_user(user=self.user)
        self.assertFalse(
            CourseEnrollment.is_enrolled(self.user, self.course_key))
        item = CertificateItem.add_to_order(cart, self.course_key, self.cost,
                                            'honor')
        # course enrollment object should be created but still inactive
        self.assertFalse(
            CourseEnrollment.is_enrolled(self.user, self.course_key))
        # the analytics client pipes output to stderr when using the default client
        with patch('sys.stderr', sys.stdout.write):
            cart.purchase()
        self.assertTrue(
            CourseEnrollment.is_enrolled(self.user, self.course_key))

        # test e-mail sending
        self.assertEquals(len(mail.outbox), 1)
        self.assertEquals('Order Payment Confirmation', mail.outbox[0].subject)
        self.assertIn(settings.PAYMENT_SUPPORT_EMAIL, mail.outbox[0].body)
        self.assertIn(unicode(cart.total_cost), mail.outbox[0].body)
        self.assertIn(item.additional_instruction_text, mail.outbox[0].body)

        # Assert Google Analytics event fired for purchase.
        self.mock_tracker.track.assert_called_once_with(  # pylint: disable=maybe-no-member
            self.user.id,
            'Completed Order',
            {
                'orderId': 1,
                'currency': 'usd',
                'total': '40',
                'products': [
                    {
                        'sku': u'CertificateItem.honor',
                        'name': unicode(self.course_key),
                        'category': unicode(self.course_key.org),
                        'price': '40',
                        'id': 1,
                        'quantity': 1
                    }
                ]
            },
            context={'Google Analytics': {'clientId': None}}
        )
Ejemplo n.º 35
0
    def test_show_receipt_success_with_upgrade(self):

        reg_item = PaidCourseRegistration.add_to_order(self.cart, self.course_key)
        cert_item = CertificateItem.add_to_order(self.cart, self.verified_course_key, 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_key)
        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.to_deprecated_string(),
                'mode': course_enrollment.mode
            }
        )
Ejemplo n.º 36
0
    def test_show_receipt_success(self):
        reg_item = PaidCourseRegistration.add_to_order(self.cart, self.course_key)
        cert_item = CertificateItem.add_to_order(self.cart, self.verified_course_key, self.cost, 'honor')
        self.cart.purchase(first='FirstNameTesting123', street1='StreetTesting123')

        self.login_user()
        resp = self.client.get(reverse('shoppingcart.views.show_receipt', args=[self.cart.id]))
        self.assertEqual(resp.status_code, 200)
        self.assertIn('FirstNameTesting123', resp.content)
        self.assertIn('80.00', resp.content)

        ((template, context), _) = render_mock.call_args
        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'])
Ejemplo n.º 37
0
    def test_show_receipt_success_refund(self):
        reg_item = PaidCourseRegistration.add_to_order(self.cart, self.course_id)
        cert_item = CertificateItem.add_to_order(self.cart, 'test/course1', self.cost, 'verified')
        self.cart.purchase(first='FirstNameTesting123', street1='StreetTesting123')
        cert_item.status = "refunded"
        cert_item.save()
        self.assertEqual(self.cart.total_cost, 40)
        self.login_user()
        resp = self.client.get(reverse('shoppingcart.views.show_receipt', args=[self.cart.id]))
        self.assertEqual(resp.status_code, 200)
        self.assertIn('40.00', resp.content)

        ((template, context), _) = render_mock.call_args
        self.assertEqual(template, 'shoppingcart/receipt.html')
        self.assertEqual(context['order'], self.cart)
        self.assertIn(reg_item.orderitem_ptr, context['order_items'])
        self.assertIn(cert_item.orderitem_ptr, context['order_items'])
        self.assertTrue(context['any_refunds'])
Ejemplo n.º 38
0
    def test_delete_certificate_item(self, info_log):

        reg_item = self.add_course_to_user_cart()
        cert_item = CertificateItem.add_to_order(self.cart,
                                                 self.verified_course_key,
                                                 self.cost, 'honor')
        self.assertEquals(self.cart.orderitem_set.count(), 2)

        # Delete the discounted item, corresponding coupon redemption should be removed for that particular discounted item
        resp = self.client.post(
            reverse('shoppingcart.views.remove_item', args=[]),
            {'id': cert_item.id})

        self.assertEqual(resp.status_code, 200)
        self.assertEquals(self.cart.orderitem_set.count(), 1)
        info_log.assert_called_with(
            'order item {0} removed for user {1}'.format(
                cert_item.id, self.user))
Ejemplo n.º 39
0
    def test_show_cart(self):
        self.login_user()
        reg_item = PaidCourseRegistration.add_to_order(self.cart, self.course_key)
        cert_item = CertificateItem.add_to_order(self.cart, self.verified_course_key, self.cost, 'honor')
        resp = self.client.get(reverse('shoppingcart.views.show_cart', args=[]))
        self.assertEqual(resp.status_code, 200)

        ((purchase_form_arg_cart,), _) = form_mock.call_args
        purchase_form_arg_cart_items = purchase_form_arg_cart.orderitem_set.all().select_subclasses()
        self.assertIn(reg_item, purchase_form_arg_cart_items)
        self.assertIn(cert_item, purchase_form_arg_cart_items)
        self.assertEqual(len(purchase_form_arg_cart_items), 2)

        ((template, context), _) = render_mock.call_args
        self.assertEqual(template, 'shoppingcart/list.html')
        self.assertEqual(len(context['shoppingcart_items']), 2)
        self.assertEqual(context['amount'], 80)
        self.assertIn("80.00", context['form_html'])
Ejemplo n.º 40
0
    def test_purchase(self):
        # This test is for testing the subclassing functionality of OrderItem, but in
        # order to do this, we end up testing the specific functionality of
        # CertificateItem, which is not quite good unit test form. Sorry.
        cart = Order.get_cart_for_user(user=self.user)
        self.assertFalse(CourseEnrollment.is_enrolled(self.user, self.course_key))
        item = CertificateItem.add_to_order(cart, self.course_key, self.cost, 'honor')
        # course enrollment object should be created but still inactive
        self.assertFalse(CourseEnrollment.is_enrolled(self.user, self.course_key))
        cart.purchase()
        self.assertTrue(CourseEnrollment.is_enrolled(self.user, self.course_key))

        # test e-mail sending
        self.assertEquals(len(mail.outbox), 1)
        self.assertEquals('Order Payment Confirmation', mail.outbox[0].subject)
        self.assertIn(settings.PAYMENT_SUPPORT_EMAIL, mail.outbox[0].body)
        self.assertIn(unicode(cart.total_cost), mail.outbox[0].body)
        self.assertIn(item.additional_instruction_text, mail.outbox[0].body)
Ejemplo n.º 41
0
    def test_remove_item(self, exception_log):
        self.login_user()
        reg_item = PaidCourseRegistration.add_to_order(self.cart, self.course_key)
        cert_item = CertificateItem.add_to_order(self.cart, self.verified_course_key, self.cost, 'honor')
        self.assertEquals(self.cart.orderitem_set.count(), 2)
        resp = self.client.post(reverse('shoppingcart.views.remove_item', args=[]),
                                {'id': reg_item.id})
        self.assertEqual(resp.status_code, 200)
        self.assertEquals(self.cart.orderitem_set.count(), 1)
        self.assertNotIn(reg_item, self.cart.orderitem_set.all().select_subclasses())

        self.cart.purchase()
        resp2 = self.client.post(reverse('shoppingcart.views.remove_item', args=[]),
                                 {'id': cert_item.id})
        self.assertEqual(resp2.status_code, 200)
        exception_log.assert_called_with(
            'Cannot remove cart OrderItem id={0}. DoesNotExist or item is already purchased'.format(cert_item.id))

        resp3 = self.client.post(reverse('shoppingcart.views.remove_item', args=[]),
                                 {'id': -1})
        self.assertEqual(resp3.status_code, 200)
        exception_log.assert_called_with(
            'Cannot remove cart OrderItem id={0}. DoesNotExist or item is already purchased'.format(-1))
Ejemplo n.º 42
0
 def test_purchase_item_email_boto_failure(self, error_logger):
     cart = Order.get_cart_for_user(user=self.user)
     CertificateItem.add_to_order(cart, self.course_key, self.cost, 'honor')
     with patch('shoppingcart.models.send_mail', side_effect=BotoServerError("status", "reason")):
         cart.purchase()
         self.assertTrue(error_logger.called)
Ejemplo n.º 43
0
    def setUp(self, cutoff_date):
        super(ReportTypeTests, self).setUp()
        cutoff_date.return_value = datetime.datetime.now(
            pytz.UTC) + datetime.timedelta(days=1)
        # Need to make a *lot* of users for this one
        self.first_verified_user = UserFactory.create(profile__name="John Doe")
        self.second_verified_user = UserFactory.create(
            profile__name="Jane Deer")
        self.first_audit_user = UserFactory.create(profile__name="Joe Miller")
        self.second_audit_user = UserFactory.create(
            profile__name="Simon Blackquill")
        self.third_audit_user = UserFactory.create(profile__name="Super Mario")
        self.honor_user = UserFactory.create(profile__name="Princess Peach")
        self.first_refund_user = UserFactory.create(
            profile__name="King Bowsér")
        self.second_refund_user = UserFactory.create(
            profile__name="Súsan Smith")

        # Two are verified, three are audit, one honor

        self.cost = 40
        self.course = CourseFactory.create(org='MITx',
                                           number='999',
                                           display_name=u'Robot Super Course')
        self.course_key = self.course.id
        course_mode = CourseMode(course_id=self.course_key,
                                 mode_slug="honor",
                                 mode_display_name="honor cert",
                                 min_price=self.cost)
        course_mode.save()

        course_mode2 = CourseMode(course_id=self.course_key,
                                  mode_slug="verified",
                                  mode_display_name="verified cert",
                                  min_price=self.cost)
        course_mode2.save()

        # User 1 & 2 will be verified
        self.cart1 = Order.get_cart_for_user(self.first_verified_user)
        CertificateItem.add_to_order(self.cart1, self.course_key, self.cost,
                                     'verified')
        self.cart1.purchase()

        self.cart2 = Order.get_cart_for_user(self.second_verified_user)
        CertificateItem.add_to_order(self.cart2, self.course_key, self.cost,
                                     'verified')
        self.cart2.purchase()

        # Users 3, 4, and 5 are audit
        CourseEnrollment.enroll(self.first_audit_user, self.course_key,
                                "audit")
        CourseEnrollment.enroll(self.second_audit_user, self.course_key,
                                "audit")
        CourseEnrollment.enroll(self.third_audit_user, self.course_key,
                                "audit")

        # User 6 is honor
        CourseEnrollment.enroll(self.honor_user, self.course_key, "honor")

        self.now = datetime.datetime.now(pytz.UTC)

        # Users 7 & 8 are refunds
        self.cart = Order.get_cart_for_user(self.first_refund_user)
        CertificateItem.add_to_order(self.cart, self.course_key, self.cost,
                                     'verified')
        self.cart.purchase()
        CourseEnrollment.unenroll(self.first_refund_user, self.course_key)

        self.cart = Order.get_cart_for_user(self.second_refund_user)
        CertificateItem.add_to_order(self.cart, self.course_key, self.cost,
                                     'verified')
        self.cart.purchase(self.second_refund_user.username, self.course_key)
        CourseEnrollment.unenroll(self.second_refund_user, self.course_key)

        self.test_time = datetime.datetime.now(pytz.UTC)

        first_refund = CertificateItem.objects.get(id=3)
        first_refund.fulfilled_time = self.test_time
        first_refund.refund_requested_time = self.test_time
        first_refund.save()

        second_refund = CertificateItem.objects.get(id=4)
        second_refund.fulfilled_time = self.test_time
        second_refund.refund_requested_time = self.test_time
        second_refund.save()

        self.CORRECT_REFUND_REPORT_CSV = dedent(u"""
            Order Number,Customer Name,Date of Original Transaction,Date of Refund,Amount of Refund,Service Fees (if any)
            3,King Bowsér,{time_str},{time_str},40.00,0.00
            4,Súsan Smith,{time_str},{time_str},40.00,0.00
            """.format(time_str=str(self.test_time)))

        self.CORRECT_CERT_STATUS_CSV = dedent("""
            University,Course,Course Announce Date,Course Start Date,Course Registration Close Date,Course Registration Period,Total Enrolled,Audit Enrollment,Honor Code Enrollment,Verified Enrollment,Gross Revenue,Gross Revenue over the Minimum,Number of Verified Students Contributing More than the Minimum,Number of Refunds,Dollars Refunded
            MITx,999 Robot Super Course,,,,,6,3,1,2,80.00,0.00,0,2,80.00
            """.format(time_str=str(self.test_time)))

        self.CORRECT_UNI_REVENUE_SHARE_CSV = dedent("""
            University,Course,Number of Transactions,Total Payments Collected,Service Fees (if any),Number of Successful Refunds,Total Amount of Refunds
            MITx,999 Robot Super Course,6,80.00,0.00,2,80.00
            """.format(time_str=str(self.test_time)))
Ejemplo n.º 44
0
    def setUp(self):
        super(TestOrderHistoryOnSiteDashboard, self).setUp()

        patcher = patch('student.models.tracker')
        self.mock_tracker = patcher.start()
        self.user = UserFactory.create()
        self.user.set_password('password')
        self.user.save()

        self.addCleanup(patcher.stop)

        # First Order with our (fakeX) site's course.
        course1 = CourseFactory.create(org='fakeX', number='999', display_name='fakeX Course')
        course1_key = course1.id
        course1_mode = CourseMode(course_id=course1_key,
                                  mode_slug="honor",
                                  mode_display_name="honor cert",
                                  min_price=20)
        course1_mode.save()

        cart = Order.get_cart_for_user(self.user)
        PaidCourseRegistration.add_to_order(cart, course1_key)
        cart.purchase(first='FirstNameTesting123', street1='StreetTesting123')
        self.fakex_site_order_id = cart.id

        # Second Order with another(fooX) site's course
        course2 = CourseFactory.create(org='fooX', number='888', display_name='fooX Course')
        course2_key = course2.id
        course2_mode = CourseMode(course_id=course2.id,
                                  mode_slug="honor",
                                  mode_display_name="honor cert",
                                  min_price=20)
        course2_mode.save()

        cart = Order.get_cart_for_user(self.user)
        PaidCourseRegistration.add_to_order(cart, course2_key)
        cart.purchase(first='FirstNameTesting123', street1='StreetTesting123')
        self.foox_site_order_id = cart.id

        # Third Order with course not attributed to any site.
        course3 = CourseFactory.create(org='fakeOtherX', number='777', display_name='fakeOtherX Course')
        course3_key = course3.id
        course3_mode = CourseMode(course_id=course3.id,
                                  mode_slug="honor",
                                  mode_display_name="honor cert",
                                  min_price=20)
        course3_mode.save()

        cart = Order.get_cart_for_user(self.user)
        PaidCourseRegistration.add_to_order(cart, course3_key)
        cart.purchase(first='FirstNameTesting123', street1='StreetTesting123')
        self.order_id = cart.id

        # Fourth Order with course not attributed to any site but with a CertificateItem
        course4 = CourseFactory.create(org='fakeOtherX', number='888')
        course4_key = course4.id
        course4_mode = CourseMode(course_id=course4.id,
                                  mode_slug="verified",
                                  mode_display_name="verified cert",
                                  min_price=20)
        course4_mode.save()

        cart = Order.get_cart_for_user(self.user)
        CertificateItem.add_to_order(cart, course4_key, 20.0, 'verified')
        cart.purchase(first='FirstNameTesting123', street1='StreetTesting123')
        self.certificate_order_id = cart.id

        # Fifth Order with course not attributed to any site but with a Donation
        course5 = CourseFactory.create(org='fakeOtherX', number='999')
        course5_key = course5.id

        cart = Order.get_cart_for_user(self.user)
        Donation.add_to_order(cart, 20.0, course5_key)
        cart.purchase(first='FirstNameTesting123', street1='StreetTesting123')
        self.donation_order_id = cart.id

        # also add a donation not associated with a course to make sure the None case works OK
        Donation.add_to_order(cart, 10.0, None)
        cart.purchase(first='FirstNameTesting123', street1='StreetTesting123')
        self.courseless_donation_order_id = cart.id
Ejemplo n.º 45
0
def create_order(request):
    """
    Submit PhotoVerification and create a new Order for this verified cert
    """
    if not SoftwareSecurePhotoVerification.user_has_valid_or_pending(
            request.user):
        attempt = SoftwareSecurePhotoVerification(user=request.user)
        try:
            b64_face_image = request.POST['face_image'].split(",")[1]
            b64_photo_id_image = request.POST['photo_id_image'].split(",")[1]
        except IndexError:
            context = {
                'success': False,
            }
            return JsonResponse(context)
        attempt.upload_face_image(b64_face_image.decode('base64'))
        attempt.upload_photo_id_image(b64_photo_id_image.decode('base64'))
        attempt.mark_ready()

        attempt.save()

    course_id = request.POST['course_id']
    course_id = CourseKey.from_string(course_id)
    donation_for_course = request.session.get('donation_for_course', {})
    current_donation = donation_for_course.get(unicode(course_id),
                                               decimal.Decimal(0))
    contribution = request.POST.get(
        "contribution", donation_for_course.get(unicode(course_id), 0))
    try:
        amount = decimal.Decimal(contribution).quantize(
            decimal.Decimal('.01'), rounding=decimal.ROUND_DOWN)
    except decimal.InvalidOperation:
        return HttpResponseBadRequest(_("Selected price is not valid number."))

    if amount != current_donation:
        donation_for_course[unicode(course_id)] = amount
        request.session['donation_for_course'] = donation_for_course

    # prefer professional mode over verified_mode
    current_mode = CourseMode.verified_mode_for_course(course_id)

    # make sure this course has a verified mode
    if not current_mode:
        return HttpResponseBadRequest(
            _("This course doesn't support verified certificates"))

    if current_mode.slug == 'professional':
        amount = current_mode.min_price

    if amount < current_mode.min_price:
        return HttpResponseBadRequest(
            _("No selected price or selected price is below minimum."))

    # I know, we should check this is valid. All kinds of stuff missing here
    cart = Order.get_cart_for_user(request.user)
    cart.clear()
    enrollment_mode = current_mode.slug
    CertificateItem.add_to_order(cart, course_id, amount, enrollment_mode)

    # Change the order's status so that we don't accidentally modify it later.
    # We need to do this to ensure that the parameters we send to the payment system
    # match what we store in the database.
    # (Ordinarily we would do this client-side when the user submits the form, but since
    # the JavaScript on this page does that immediately, we make the change here instead.
    # This avoids a second AJAX call and some additional complication of the JavaScript.)
    # If a user later re-enters the verification / payment flow, she will create a new order.
    cart.start_purchase()

    callback_url = request.build_absolute_uri(
        reverse("shoppingcart.views.postpay_callback"))

    params = get_signed_purchase_params(cart,
                                        callback_url=callback_url,
                                        extra_data=[unicode(course_id)])

    params['success'] = True
    return HttpResponse(json.dumps(params), content_type="text/json")
Ejemplo n.º 46
0
 def test_user_cart_has_certificate_items(self):
     cart = Order.get_cart_for_user(self.user)
     CertificateItem.add_to_order(cart, self.course_key, self.cost, 'honor')
     self.assertTrue(Order.user_cart_has_items(self.user, CertificateItem))
     self.assertFalse(Order.user_cart_has_items(self.user, PaidCourseRegistration))
Ejemplo n.º 47
0
 def test_purchase_item_email_smtp_failure(self, error_logger):
     cart = Order.get_cart_for_user(user=self.user)
     CertificateItem.add_to_order(cart, self.course_key, self.cost, 'honor')
     with patch('shoppingcart.models.send_mail', side_effect=smtplib.SMTPException):
         cart.purchase()
         self.assertTrue(error_logger.called)
Ejemplo n.º 48
0
def create_order(request):
    """
    Submit PhotoVerification and create a new Order for this verified cert
    """
    # Only submit photos if photo data is provided by the client.
    # TODO (ECOM-188): Once the A/B test of decoupling verified / payment
    # completes, we may be able to remove photo submission from this step
    # entirely.
    submit_photo = (
        'face_image' in request.POST and
        'photo_id_image' in request.POST
    )

    if (
        submit_photo and not
        SoftwareSecurePhotoVerification.user_has_valid_or_pending(request.user)
    ):
        attempt = SoftwareSecurePhotoVerification(user=request.user)
        try:
            b64_face_image = request.POST['face_image'].split(",")[1]
            b64_photo_id_image = request.POST['photo_id_image'].split(",")[1]
        except IndexError:
            log.error(u"Invalid image data during photo verification.")
            context = {
                'success': False,
            }
            return JsonResponse(context)
        attempt.upload_face_image(b64_face_image.decode('base64'))
        attempt.upload_photo_id_image(b64_photo_id_image.decode('base64'))
        attempt.mark_ready()

        attempt.save()

    course_id = request.POST['course_id']
    course_id = CourseKey.from_string(course_id)
    donation_for_course = request.session.get('donation_for_course', {})
    contribution = request.POST.get("contribution", donation_for_course.get(unicode(course_id), 0))
    try:
        amount = decimal.Decimal(contribution).quantize(decimal.Decimal('.01'), rounding=decimal.ROUND_DOWN)
    except decimal.InvalidOperation:
        return HttpResponseBadRequest(_("Selected price is not valid number."))

    current_mode = None
    paid_modes = CourseMode.paid_modes_for_course(course_id)
    # Check if there are more than 1 paid(mode with min_price>0 e.g verified/professional/no-id-professional) modes
    # for course exist then choose the first one
    if paid_modes:
        if len(paid_modes) > 1:
            log.warn(u"Multiple paid course modes found for course '%s' for create order request", course_id)
        current_mode = paid_modes[0]

    # Make sure this course has a paid mode
    if not current_mode:
        log.warn(u"Create order requested for course '%s' without a paid mode.", course_id)
        return HttpResponseBadRequest(_("This course doesn't support paid certificates"))

    if CourseMode.is_professional_mode(current_mode):
        amount = current_mode.min_price

    if amount < current_mode.min_price:
        return HttpResponseBadRequest(_("No selected price or selected price is below minimum."))

    if current_mode.sku:
        return create_order_with_ecommerce_service(request.user, course_id, current_mode)

    # I know, we should check this is valid. All kinds of stuff missing here
    cart = Order.get_cart_for_user(request.user)
    cart.clear()
    enrollment_mode = current_mode.slug
    CertificateItem.add_to_order(cart, course_id, amount, enrollment_mode)

    # Change the order's status so that we don't accidentally modify it later.
    # We need to do this to ensure that the parameters we send to the payment system
    # match what we store in the database.
    # (Ordinarily we would do this client-side when the user submits the form, but since
    # the JavaScript on this page does that immediately, we make the change here instead.
    # This avoids a second AJAX call and some additional complication of the JavaScript.)
    # If a user later re-enters the verification / payment flow, she will create a new order.
    cart.start_purchase()

    callback_url = request.build_absolute_uri(
        reverse("shoppingcart.views.postpay_callback")
    )

    params = get_signed_purchase_params(
        cart,
        callback_url=callback_url,
        extra_data=[unicode(course_id), current_mode.slug]
    )

    params['success'] = True
    return HttpResponse(json.dumps(params), content_type="text/json")