Exemplo n.º 1
0
    def test_update_exam_authorization_order(self, order_status):
        """
        Verify that update_exam_authorization_final_grade is called when a fulfilled Order saves
        """
        with mute_signals(post_save):
            # muted because enrollment also trigger signal for profile creation. right now we are just
            # looking final grades
            CachedEnrollmentFactory.create(user=self.profile.user, course_run=self.course_run)

        FinalGradeFactory.create(
            user=self.profile.user,
            course_run=self.course_run,
            passed=True,
        )

        order = OrderFactory.create(user=self.profile.user, fulfilled=False)
        LineFactory.create(course_key=self.course_run.edx_course_key, order=order)

        # There is no ExamProfile or ExamAuthorization before creating the FinalGrade.
        assert ExamProfile.objects.filter(profile=self.profile).exists() is False
        assert ExamAuthorization.objects.filter(
            user=self.profile.user,
            course=self.course_run.course
        ).exists() is False

        order.status = order_status
        order.save()

        # assert Exam Authorization and profile created.
        assert ExamProfile.objects.filter(profile=self.profile).exists() is True
        assert ExamAuthorization.objects.filter(
            user=self.profile.user,
            course=self.course_run.course
        ).exists() is True
Exemplo n.º 2
0
 def create(cls, **kwargs):
     """
     Overrides the default .create() method. Creates an Order/Line for an FA course if the client
     asked for a 'verified' enrollment specifically
     """
     created_obj = super().create(**kwargs)
     if kwargs.get('verified') is True:
         course_run = created_obj.course_run
         program = course_run.course.program
         if program.financial_aid_availability:
             LineFactory.create(course_key=course_run.edx_course_key, order__status=Order.FULFILLED)
     return created_obj
Exemplo n.º 3
0
 def create(cls, **kwargs):
     """
     Overrides the default .create() method. Creates an Order/Line for an FA course if the client
     asked for a 'verified' enrollment specifically
     """
     created_obj = super().create(**kwargs)
     if kwargs.get('verified') is True:
         course_run = created_obj.course_run
         program = course_run.course.program
         if program.financial_aid_availability:
             LineFactory.create(course_key=course_run.edx_course_key, order__status=Order.FULFILLED)
     return created_obj
Exemplo n.º 4
0
def test_serialize_order_with_coupon():
    """Test that OrderToDealSerializer produces the correct serialized data for an order with coupon"""
    line = LineFactory.create()
    order = line.order
    coupon_redemption = CouponRedemptionFactory.create(order=order)
    discount = round_half_up(
        coupon_redemption.coupon_version.payment_version.amount
        * line.product_version.price
    )
    serialized_data = OrderToDealSerializer(instance=order).data
    assert serialized_data == {
        "id": order.id,
        "name": f"XPRO-ORDER-{order.id}",
        "purchaser": format_hubspot_id(order.purchaser.id),
        "stage": ORDER_STATUS_MAPPING[order.status],
        "amount": line.product_version.price.to_eng_string(),
        "discount_amount": discount.to_eng_string(),
        "close_date": (
            int(order.updated_on.timestamp() * 1000)
            if order.status == Order.FULFILLED
            else None
        ),
        "coupon_code": coupon_redemption.coupon_version.coupon.coupon_code,
        "company": coupon_redemption.coupon_version.payment_version.company.name,
        "order_type": ORDER_TYPE_B2B,
        "payment_type": coupon_redemption.coupon_version.payment_version.payment_type,
        "payment_transaction": coupon_redemption.coupon_version.payment_version.payment_transaction,
        "discount_percent": (
            coupon_redemption.coupon_version.payment_version.amount * 100
        ).to_eng_string(),
        "lines": [LineSerializer(instance=line).data],
        "status": order.status,
    }
Exemplo n.º 5
0
    def setUpTestData(cls):
        super().setUpTestData()

        cls.user = UserFactory()
        cls.user.social_auth.create(
            provider='not_edx',
        )
        cls.user.social_auth.create(
            provider=EdxOrgOAuth2.name,
            uid="{}_edx".format(cls.user.username),
        )
        cls.order = OrderFactory.create(status=Order.CREATED, user=cls.user)
        cls.line1 = LineFactory.create(order=cls.order)
        cls.line2 = LineFactory.create(order=cls.order)
        cls.course_run1 = CourseRunFactory.create(edx_course_key=cls.line1.course_key)
        cls.course_run2 = CourseRunFactory.create(edx_course_key=cls.line2.course_key)
Exemplo n.º 6
0
def test_serialize_order(status):
    """Test that OrderToDealSerializer produces the correct serialized data"""
    order = OrderFactory.create(status=status)
    line = LineFactory.create(order=order)
    serialized_data = OrderToDealSerializer(instance=order).data
    assert serialized_data == {
        "id": order.id,
        "name": f"XPRO-ORDER-{order.id}",
        "purchaser": format_hubspot_id(order.purchaser.id),
        "stage": ORDER_STATUS_MAPPING[status],
        "amount": line.product_version.price.to_eng_string(),
        "discount_amount": "0.0000",
        "close_date": (
            int(order.updated_on.timestamp() * 1000)
            if status == Order.FULFILLED
            else None
        ),
        "coupon_code": None,
        "company": None,
        "payment_type": None,
        "payment_transaction": None,
        "discount_percent": "0",
        "order_type": ORDER_TYPE_B2C,
        "lines": [LineSerializer(instance=line).data],
        "status": order.status,
    }
Exemplo n.º 7
0
    def setUpTestData(cls):
        super().setUpTestData()

        cls.user = UserFactory()
        cls.user.social_auth.create(
            provider='not_edx',
        )
        cls.user.social_auth.create(
            provider=EdxOrgOAuth2.name,
            uid="{}_edx".format(cls.user.username),
        )
        cls.order = OrderFactory.create(status=Order.CREATED, user=cls.user)
        cls.line1 = LineFactory.create(order=cls.order)
        cls.line2 = LineFactory.create(order=cls.order)
        cls.course_run1 = CourseRunFactory.create(edx_course_key=cls.line1.course_key)
        cls.course_run2 = CourseRunFactory.create(edx_course_key=cls.line2.course_key)
Exemplo n.º 8
0
 def test_line_str(self):
     """Test Line.__str__"""
     line = LineFactory.create()
     assert str(line) == "Line for order {}, course_key={}, price={}".format(
         line.order.id,
         line.course_key,
         line.price,
     )
Exemplo n.º 9
0
def create_order(user, course_run):
    """"
    create payment for course
    """
    return LineFactory.create(
        course_key=course_run.edx_course_key,
        order__fulfilled=True,
        order__user=user,
    ).order
Exemplo n.º 10
0
def test_product_version_save_text_id_badproduct(mocker):
    """ProductVersion.text_id should None if ProductVersion.product is invalid"""
    mock_log = mocker.patch("ecommerce.models.log")
    product_version = ProductVersionFactory.create(
        product=ProductFactory.create(content_object=LineFactory()))
    assert product_version.text_id is None
    assert mock_log.called_once_with(
        f"The content object for this ProductVersion ({product_version.id}) does not have a `text_id` property"
    )
Exemplo n.º 11
0
def create_order(user, course_run):
    """"
    create payment for course
    """
    return LineFactory.create(
        course_key=course_run.edx_course_key,
        order__fulfilled=True,
        order__user=user,
    ).order
Exemplo n.º 12
0
def test_sync_line_item_with_hubspot(mock_hubspot_request):
    """Test that send_hubspot_request is called properly for a LINE_ITEM sync"""
    line = LineFactory.create()
    sync_line_item_with_hubspot(line.id)
    body = make_line_item_sync_message(line.id)
    body[0]["changeOccurredTimestamp"] = ANY
    mock_hubspot_request.assert_called_once_with("LINE_ITEM",
                                                 HUBSPOT_SYNC_URL,
                                                 "PUT",
                                                 body=body)
Exemplo n.º 13
0
    def test_another_user_already_redeemed(self, order_status, other_user_redeemed, is_automatic, expected):
        """
        Tests for Coupon.another_user_already_redeemed
        """
        run1 = CourseRunFactory.create(course__program__financial_aid_availability=True)
        run2 = CourseRunFactory.create(course=run1.course)
        coupon = CouponFactory.create(
            content_object=run1.course,
            coupon_type=Coupon.DISCOUNTED_PREVIOUS_COURSE if is_automatic else Coupon.STANDARD,
        )

        line1 = LineFactory.create(course_key=run1.edx_course_key, order__status=Order.FULFILLED)
        RedeemedCoupon.objects.create(order=line1.order, coupon=coupon)

        if other_user_redeemed:
            line2 = LineFactory.create(course_key=run2.edx_course_key, order__status=order_status)
            RedeemedCoupon.objects.create(order=line2.order, coupon=coupon)

        assert coupon.another_user_already_redeemed(line1.order.user) is expected
Exemplo n.º 14
0
 def test_to_dict(self):
     """
     Test Order.to_dict()
     """
     order = OrderFactory.create()
     lines = [LineFactory.create(order=order) for _ in range(5)]
     data = order.to_dict()
     lines_data = data.pop('lines')
     assert serialize_model_object(order) == data
     assert lines_data == [serialize_model_object(line) for line in lines]
Exemplo n.º 15
0
def test_serialize_line():
    """Test that LineSerializer produces the correct serialized data"""
    line = LineFactory.create()
    serialized_data = LineSerializer(instance=line).data
    assert serialized_data == {
        "id": line.id,
        "product": format_hubspot_id(line.product_version.product.id),
        "order": format_hubspot_id(line.order_id),
        "quantity": line.quantity,
        "status": line.order.status,
        "product_id": line.product_version.text_id,
    }
Exemplo n.º 16
0
 def pay_for_fa_course(self, course_id, status=Order.FULFILLED):
     """
     Helper function to pay for a financial aid course
     """
     order = OrderFactory.create(
         user=self.user,
         status=status
     )
     return LineFactory.create(
         order=order,
         course_key=course_id
     )
Exemplo n.º 17
0
 def pay_for_fa_course(self, course_id, status=Order.FULFILLED):
     """
     Helper function to pay for a financial aid course
     """
     order = OrderFactory.create(
         user=self.user,
         status=status
     )
     return LineFactory.create(
         order=order,
         course_key=course_id
     )
Exemplo n.º 18
0
    def test_zero_price_checkout_failed_enroll(self):
        """
        If we do a $0 checkout but the enrollment fails, we should send an email but leave the order as fulfilled
        """
        user = UserFactory.create()
        self.client.force_login(user)

        course_run = CourseRunFactory.create(
            course__program__live=True,
            course__program__financial_aid_availability=True,
        )
        order = LineFactory.create(
            order__status=Order.CREATED,
            order__total_price_paid=0,
            price=0,
        ).order
        with patch(
                'ecommerce.views.create_unfulfilled_order',
                autospec=True,
                return_value=order,
        ) as create_mock, patch(
                'ecommerce.views.enroll_user_on_success',
                side_effect=KeyError,
        ) as enroll_user_mock, patch(
                'ecommerce.views.MailgunClient.send_individual_email',
        ) as send_email:
            resp = self.client.post(reverse('checkout'),
                                    {'course_id': course_run.edx_course_key},
                                    format='json')

        assert resp.status_code == status.HTTP_200_OK
        assert resp.json() == {
            'payload': {},
            'url':
            'http://testserver/dashboard/?status=receipt&course_key={}'.format(
                quote_plus(course_run.edx_course_key)),
            'method':
            'GET',
        }

        assert create_mock.call_count == 1
        assert create_mock.call_args[0] == (course_run.edx_course_key, user)

        assert enroll_user_mock.call_count == 1
        assert enroll_user_mock.call_args[0] == (order, )

        assert send_email.call_count == 1
        assert send_email.call_args[0][
            0] == 'Error occurred when enrolling user during $0 checkout'
        assert send_email.call_args[0][1].startswith(
            'Error occurred when enrolling user during $0 checkout for {order}. '
            'Exception: '.format(order=order, ))
        assert send_email.call_args[0][2] == '*****@*****.**'
Exemplo n.º 19
0
def test_create_hubspot_line_resync(settings, mock_hubspot_line_error,
                                    mock_retry_lines):
    """Test that lines are re-synced if the error is INVALID_ASSOCIATION_PROPERTY and the order has since been synced"""
    HubspotErrorCheckFactory.create(checked_on=TIMESTAMPS[0])
    order = OrderFactory(id=FAKE_OBJECT_ID)
    line = LineFactory(order=order, id=FAKE_OBJECT_ID)

    settings.HUBSPOT_API_KEY = "dkfjKJ2jfd"
    check_hubspot_api_errors()
    assert mock_hubspot_line_error.call_count == 2
    assert mock_retry_lines.call_count == 1
    assert HubspotLineResync.objects.count() == 1
    assert HubspotLineResync.objects.first().line == line
Exemplo n.º 20
0
    def test_zero_price_checkout_failed_enroll(self):
        """
        If we do a $0 checkout but the enrollment fails, we should send an email but leave the order as fulfilled
        """
        user = UserFactory.create()
        self.client.force_login(user)

        course_run = CourseRunFactory.create(
            course__program__live=True,
            course__program__financial_aid_availability=True,
        )
        order = LineFactory.create(
            order__status=Order.CREATED,
            order__total_price_paid=0,
            price=0,
        ).order
        with patch(
            'ecommerce.views.create_unfulfilled_order',
            autospec=True,
            return_value=order,
        ) as create_mock, patch(
            'ecommerce.views.enroll_user_on_success', side_effect=KeyError,
        ) as enroll_user_mock, patch(
            'ecommerce.views.MailgunClient.send_individual_email',
        ) as send_email:
            resp = self.client.post(reverse('checkout'), {'course_id': course_run.edx_course_key}, format='json')

        assert resp.status_code == status.HTTP_200_OK
        assert resp.json() == {
            'payload': {},
            'url': 'http://testserver/dashboard/?status=receipt&course_key={}'.format(
                quote_plus(course_run.edx_course_key)
            ),
            'method': 'GET',
        }

        assert create_mock.call_count == 1
        assert create_mock.call_args[0] == (course_run.edx_course_key, user)

        assert enroll_user_mock.call_count == 1
        assert enroll_user_mock.call_args[0] == (order,)

        assert send_email.call_count == 1
        assert send_email.call_args[0][0] == 'Error occurred when enrolling user during $0 checkout'
        assert send_email.call_args[0][1].startswith(
            'Error occurred when enrolling user during $0 checkout for {order}. '
            'Exception: '.format(
                order=order,
            )
        )
        assert send_email.call_args[0][2] == '*****@*****.**'
Exemplo n.º 21
0
def test_make_line_item_sync_message():
    """Test make_line_item_sync_message serializes a line_item and returns a properly formatted sync message"""
    line = LineFactory()
    line_item_sync_message = api.make_line_item_sync_message(line.id)

    serialized_line = LineSerializer(line).data
    assert line_item_sync_message == [
        {
            "integratorObjectId": "{}-{}".format(settings.HUBSPOT_ID_PREFIX, line.id),
            "action": "UPSERT",
            "changeOccurredTimestamp": any_instance_of(int),
            "propertyNameToValues": serialized_line,
        }
    ]
Exemplo n.º 22
0
    def test_update_exam_authorization_order(self, order_status):
        """
        Verify that update_exam_authorization_final_grade is called when a fulfilled Order saves
        """
        with mute_signals(post_save):
            # muted because enrollment also trigger signal for profile creation. right now we are just
            # looking final grades
            CachedEnrollmentFactory.create(user=self.profile.user,
                                           course_run=self.course_run)

        FinalGradeFactory.create(
            user=self.profile.user,
            course_run=self.course_run,
            passed=True,
        )

        order = OrderFactory.create(user=self.profile.user, fulfilled=False)
        LineFactory.create(course_key=self.course_run.edx_course_key,
                           order=order)

        # There is no ExamProfile or ExamAuthorization before creating the FinalGrade.
        assert ExamProfile.objects.filter(
            profile=self.profile).exists() is False
        assert ExamAuthorization.objects.filter(
            user=self.profile.user,
            course=self.course_run.course).exists() is False

        order.status = order_status
        order.save()

        # assert Exam Authorization and profile created.
        assert ExamProfile.objects.filter(
            profile=self.profile).exists() is True
        assert ExamAuthorization.objects.filter(
            user=self.profile.user,
            course=self.course_run.course).exists() is True
Exemplo n.º 23
0
    def test_user_has_redemptions_left(self, order_status, has_unpurchased_run, another_already_redeemed, expected):
        """
        Coupon.user_has_redemptions_left should be true if user has not yet purchased all course runs
        """
        run1 = CourseRunFactory.create(course__program__financial_aid_availability=True)
        if has_unpurchased_run:
            CourseRunFactory.create(course__program=run1.course.program)

        line = LineFactory.create(course_key=run1.edx_course_key, order__status=order_status)
        coupon = CouponFactory.create(content_object=run1.course.program)
        with patch(
            'ecommerce.models.Coupon.another_user_already_redeemed',
            autospec=True,
        ) as _already_redeemed:
            _already_redeemed.return_value = another_already_redeemed
            assert coupon.user_has_redemptions_left(line.order.user) is expected
        _already_redeemed.assert_called_with(coupon, line.order.user)
Exemplo n.º 24
0
    def test_creates_order(self):
        """
        An order is created using create_unfulfilled_order and a payload
        is generated using generate_cybersource_sa_payload
        """
        user = UserFactory.create()
        self.client.force_login(user)

        course_run = CourseRunFactory.create(
            course__program__live=True,
            course__program__financial_aid_availability=True,
        )
        order = LineFactory.create(order__status=Order.CREATED).order
        fake_ip = "195.0.0.1"
        payload = {
            'a': 'payload',
        }
        with patch(
                'ecommerce.views.create_unfulfilled_order',
                autospec=True,
                return_value=order,
        ) as create_mock, patch(
                'ecommerce.views.generate_cybersource_sa_payload',
                autospec=True,
                return_value=payload,
        ) as generate_mock, patch("ecommerce.views.get_client_ip",
                                  return_value=(fake_ip,
                                                True)) as mock_ip_call:
            resp = self.client.post(reverse('checkout'),
                                    {'course_id': course_run.edx_course_key},
                                    format='json')

        assert mock_ip_call.call_count == 1
        assert resp.status_code == status.HTTP_200_OK
        assert resp.json() == {
            'payload': payload,
            'url': CYBERSOURCE_SECURE_ACCEPTANCE_URL,
            'method': 'POST',
        }

        assert create_mock.call_count == 1
        assert create_mock.call_args[0] == (course_run.edx_course_key, user)
        assert generate_mock.call_count == 1
        assert generate_mock.call_args[0] == (order,
                                              'http://testserver/dashboard/',
                                              fake_ip)
Exemplo n.º 25
0
    def test_zero_price_checkout(self):
        """
        If the order total is $0, we should just fulfill the order and direct the user to our order receipt page
        """
        user = UserFactory.create()
        self.client.force_login(user)

        course_run = CourseRunFactory.create(
            course__program__live=True,
            course__program__financial_aid_availability=True,
        )
        order = LineFactory.create(
            order__status=Order.CREATED,
            order__total_price_paid=0,
            price=0,
        ).order
        with patch(
                'ecommerce.views.create_unfulfilled_order',
                autospec=True,
                return_value=order,
        ) as create_mock, patch('ecommerce.views.enroll_user_on_success',
                                autospec=True) as enroll_user_mock:
            resp = self.client.post(reverse('checkout'),
                                    {'course_id': course_run.edx_course_key},
                                    format='json')

        assert resp.status_code == status.HTTP_200_OK
        assert resp.json() == {
            'payload': {},
            'url':
            'http://testserver/dashboard/?status=receipt&course_key={}'.format(
                quote_plus(course_run.edx_course_key)),
            'method':
            'GET',
        }

        assert create_mock.call_count == 1
        assert create_mock.call_args[0] == (course_run.edx_course_key, user)

        assert enroll_user_mock.call_count == 1
        assert enroll_user_mock.call_args[0] == (order, )
Exemplo n.º 26
0
    def test_creates_order(self):
        """
        An order is created using create_unfulfilled_order and a payload
        is generated using generate_cybersource_sa_payload
        """
        user = UserFactory.create()
        self.client.force_login(user)

        course_run = CourseRunFactory.create(
            course__program__live=True,
            course__program__financial_aid_availability=True,
        )
        order = LineFactory.create(order__status=Order.CREATED).order
        payload = {
            'a': 'payload'
        }
        with patch(
            'ecommerce.views.create_unfulfilled_order',
            autospec=True,
            return_value=order,
        ) as create_mock, patch(
            'ecommerce.views.generate_cybersource_sa_payload',
            autospec=True,
            return_value=payload,
        ) as generate_mock:
            resp = self.client.post(reverse('checkout'), {'course_id': course_run.edx_course_key}, format='json')

        assert resp.status_code == status.HTTP_200_OK
        assert resp.json() == {
            'payload': payload,
            'url': CYBERSOURCE_SECURE_ACCEPTANCE_URL,
            'method': 'POST',
        }

        assert create_mock.call_count == 1
        assert create_mock.call_args[0] == (course_run.edx_course_key, user)
        assert generate_mock.call_count == 1
        assert generate_mock.call_args[0] == (order, 'http://testserver/dashboard/')
Exemplo n.º 27
0
    def test_zero_price_checkout(self):
        """
        If the order total is $0, we should just fulfill the order and direct the user to our order receipt page
        """
        user = UserFactory.create()
        self.client.force_login(user)

        course_run = CourseRunFactory.create(
            course__program__live=True,
            course__program__financial_aid_availability=True,
        )
        order = LineFactory.create(
            order__status=Order.CREATED,
            order__total_price_paid=0,
            price=0,
        ).order
        with patch(
            'ecommerce.views.create_unfulfilled_order',
            autospec=True,
            return_value=order,
        ) as create_mock, patch('ecommerce.views.enroll_user_on_success', autospec=True) as enroll_user_mock:
            resp = self.client.post(reverse('checkout'), {'course_id': course_run.edx_course_key}, format='json')

        assert resp.status_code == status.HTTP_200_OK
        assert resp.json() == {
            'payload': {},
            'url': 'http://testserver/dashboard/?status=receipt&course_key={}'.format(
                quote_plus(course_run.edx_course_key)
            ),
            'method': 'GET',
        }

        assert create_mock.call_count == 1
        assert create_mock.call_args[0] == (course_run.edx_course_key, user)

        assert enroll_user_mock.call_count == 1
        assert enroll_user_mock.call_args[0] == (order,)
Exemplo n.º 28
0
def test_send_enrollment_failure_message(mocker, is_program):
    """Test that send_enrollment_failure_message sends a message with proper formatting"""
    patched_django_mail = mocker.patch("ecommerce.mail_api.mail")
    product_object = (ProgramFactory.create()
                      if is_program else CourseRunFactory.create())
    product_version = ProductVersionFactory.create(
        product=ProductFactory.create(content_object=product_object))
    order = LineFactory.create(product_version=product_version).order
    details = "TestException on line 21"
    expected_message = "{name}({email}): Order #{order_id}, {error_obj} #{obj_id} ({obj_title})\n\n{details}".format(
        name=order.purchaser.username,
        email=order.purchaser.email,
        order_id=order.id,
        error_obj=("Program" if is_program else "Run"),
        obj_id=product_object.id,
        obj_title=product_object.title,
        details=details,
    )

    send_enrollment_failure_message(order, product_object, details)
    patched_django_mail.send_mail.assert_called_once()
    send_mail_args = patched_django_mail.send_mail.call_args[0]
    assert send_mail_args[0] == ENROLL_ERROR_EMAIL_SUBJECT
    assert send_mail_args[1] == expected_message
Exemplo n.º 29
0
def test_send_ecommerce_order_receipt(mocker, receipt_data):
    """send_ecommerce_order_receipt should send a receipt email"""
    patched_mail_api = mocker.patch("ecommerce.mail_api.api")
    date = datetime.datetime(2010, 1, 1, 0, tzinfo=UTC)
    user = UserFactory.create(
        name="test",
        email="*****@*****.**",
        legal_address__first_name="Test",
        legal_address__last_name="User",
        legal_address__street_address_1="11 Main Street",
        legal_address__country="US",
        legal_address__state_or_territory="US-CO",
        legal_address__city="Boulder",
        legal_address__postal_code="80309",
    )
    line = LineFactory.create(
        order__status=Order.CREATED,
        order__id=1,
        order__created_on=date,
        order__total_price_paid=0,
        order__purchaser=user,
        product_version__price=100,
        quantity=1,
        product_version__product__content_object=CourseRunFactory.create(
            title="test_run_title"),
        product_version__product__content_object__course__readable_id=
        "course:/v7/choose-agency",
    )
    # pylint: disable=expression-not-assigned
    (ReceiptFactory.create(order=line.order, data=receipt_data)
     if receipt_data else None)
    send_ecommerce_order_receipt(line.order)
    patched_mail_api.context_for_user.assert_called_once_with(
        user=None,
        extra_context={
            "coupon":
            None,
            "content_title":
            "test_run_title",
            "lines": [{
                "quantity":
                1,
                "total_paid":
                "100.00",
                "discount":
                "0.0",
                "price":
                "100.00",
                "readable_id":
                get_readable_id(line.product_version.product.content_object),
                "start_date":
                None,
                "end_date":
                None,
                "content_title":
                "test_run_title",
                "CEUs":
                line.product_version.product.content_object.course.page.
                certificate_page.CEUs,
            }],
            "order_total":
            "100.00",
            "order": {
                "id": 1,
                "created_on": line.order.created_on,
                "reference_number": "xpro-b2c-dev-1",
            },
            "receipt": {
                "card_number": "1234",
                "card_type": "Visa",
                "name": "MIT Doof",
                "payment_method": "card",
                "bill_to_email": "*****@*****.**",
            },
            "purchaser": {
                "name": " ".join(["Test", "User"]),
                "email": "*****@*****.**",
                "street_address": ["11 Main Street"],
                "state_code": "CO",
                "postal_code": "80309",
                "city": "Boulder",
                "country": "United States",
                "company": user.profile.company,
            },
        },
    )
    patched_mail_api.messages_for_recipients.assert_called_once_with(
        [("*****@*****.**", patched_mail_api.context_for_user.return_value)],
        EMAIL_PRODUCT_ORDER_RECEIPT,
    )
Exemplo n.º 30
0
    def create_exams(self, current, edx_passed, exam_passed, new_offering, can_schedule, future_exam, need_to_pay):
        """Create an exam and mark it and the related course as passed or not passed"""
        # pylint: disable-msg=too-many-arguments
        self.make_fa_program_enrollment(FinancialAidStatus.AUTO_APPROVED)
        course = Course.objects.get(title='Digital Learning 200')
        if current:
            course_run = CourseRunFactory(course=course)
            call_command(
                "alter_data", 'set_to_enrolled', '--username', 'staff',
                '--course-run-key', course_run.edx_course_key
            )
            FinalGradeFactory.create(
                user=self.user, course_run=course_run, grade=0.8 if edx_passed else 0.2, passed=True
            )
        else:
            if edx_passed:
                call_command(
                    "alter_data", 'set_to_passed', '--username', 'staff',
                    '--course-title', 'Digital Learning 200', '--grade', '75',
                )
            else:
                call_command(
                    "alter_data", 'set_to_failed', '--username', 'staff',
                    '--course-title', 'Digital Learning 200', '--grade', '45',
                )
            course_run = course.courserun_set.first()

        ExamProfileFactory.create(status='success', profile=self.user.profile)
        exam_run = ExamRunFactory.create(course=course, eligibility_past=True, scheduling_past=True)
        ExamAuthorizationFactory.create(
            user=self.user, course=course, exam_run=exam_run, status='success', exam_taken=True
        )
        LineFactory.create(
            order__status=Order.FULFILLED,
            course_key=course_run
        )

        ProctoredExamGradeFactory.create(
            user=self.user,
            course=course,
            exam_run=exam_run,
            passed=exam_passed,
            percentage_grade=0.8 if exam_passed else 0.3
        )
        if new_offering:
            CourseRunFactory.create(course=course)

        if can_schedule:
            exam_run = ExamRunFactory.create(
                scheduling_past=False,
                scheduling_future=False,
                authorized=True,
                course=course
            )
            ExamAuthorizationFactory.create(
                user=self.user, course=course, exam_run=exam_run, status='success',
            )

        if future_exam:
            ExamRunFactory.create(
                scheduling_past=False,
                scheduling_future=True,
                authorized=True,
                course=course
            )
        if need_to_pay:
            exam_run = ExamRunFactory.create(course=course, eligibility_past=True, scheduling_past=True)
            ExamAuthorizationFactory.create(
                user=self.user, course=course, exam_run=exam_run, status='success', exam_taken=True
            )
            ProctoredExamGradeFactory.create(
                user=self.user,
                course=course,
                exam_run=exam_run,
                passed=False,
                percentage_grade=0.3
            )
Exemplo n.º 31
0
def test_serialize_order_receipt(receipt_data):
    """ Test that the OrderReceiptSerializer has correct data """
    line = LineFactory.create(order__status=Order.FULFILLED)
    product_version = line.product_version
    order = line.order
    purchaser = order.purchaser.legal_address
    receipt = (
        ReceiptFactory.create(order=order, data=receipt_data) if receipt_data else None
    )
    serialized_data = OrderReceiptSerializer(instance=order).data
    assert serialized_data == {
        "coupon": None,
        "lines": [
            {
                "readable_id": get_readable_id(product_version.product.content_object),
                "content_title": product_version.product.content_object.title,
                "discount": "0.0",
                "start_date": None,
                "end_date": None,
                "price": str(product_version.price),
                "total_paid": str(line.quantity * product_version.price),
                "quantity": line.quantity,
                "CEUs": product_version.product.content_object.course.page.certificate_page.CEUs,
            }
        ],
        "order": {
            "id": order.id,
            "created_on": order.created_on,
            "reference_number": order.reference_number,
        },
        "purchaser": {
            "first_name": purchaser.first_name,
            "last_name": purchaser.last_name,
            "email": order.purchaser.email,
            "country": purchaser.country,
            "state_or_territory": purchaser.state_or_territory,
            "city": purchaser.city,
            "postal_code": purchaser.postal_code,
            "company": order.purchaser.profile.company,
            "street_address": [
                line
                for line in [
                    purchaser.street_address_1,
                    purchaser.street_address_2,
                    purchaser.street_address_3,
                    purchaser.street_address_4,
                    purchaser.street_address_5,
                ]
                if line
            ],
        },
        "receipt": {
            "card_number": receipt_data["req_card_number"]
            if "req_card_number" in receipt_data
            else None,
            "card_type": CYBERSOURCE_CARD_TYPES[receipt_data["req_card_type"]]
            if "req_card_type" in receipt_data
            else None,
            "payment_method": receipt.data["req_payment_method"]
            if "req_payment_method" in receipt.data
            else None,
            "bill_to_email": receipt.data["req_bill_to_email"]
            if "req_bill_to_email" in receipt.data
            else None,
            "name": f"{receipt.data.get('req_bill_to_forename')} {receipt.data.get('req_bill_to_surname')}"
            if "req_bill_to_forename" in receipt.data
            or "req_bill_to_surname" in receipt.data
            else None,
        }
        if receipt
        else None,
    }
Exemplo n.º 32
0
def test_order_audit(has_user, has_lines):
    """
    Order.save_and_log() should save the order's information to an audit model.
    """
    coupon_redemption = CouponRedemptionFactory.create()
    assert str(coupon_redemption
               ) == "CouponRedemption for order {}, coupon version {}".format(
                   str(coupon_redemption.order),
                   str(coupon_redemption.coupon_version))
    order = coupon_redemption.order
    contents = [CourseRunFactory.create(), ProgramFactory.create()]
    lines = ([
        LineFactory.create(order=order,
                           product_version__product__content_object=content)
        for content in contents
    ] if has_lines else [])

    assert OrderAudit.objects.count() == 0
    order.save_and_log(UserFactory.create() if has_user else None)

    assert OrderAudit.objects.count() == 1
    order_audit = OrderAudit.objects.first()
    assert order_audit.order == order

    assert order_audit.data_after == {
        **serialize_model_object(order),
        "purchaser_email":
        order.purchaser.email,
        "lines": [{
            **serialize_model_object(line),
            "product_version_info": {
                **serialize_model_object(line.product_version),
                "product_info": {
                    **serialize_model_object(line.product_version.product),
                    "content_type_string":
                    str(line.product_version.product.content_type),
                    "content_object":
                    serialize_model_object(
                        line.product_version.product.content_object),
                },
            },
        } for line in lines],
        "coupons": [{
            **serialize_model_object(coupon_redemption.coupon_version.coupon),
            "coupon_version_info": {
                **serialize_model_object(coupon_redemption.coupon_version),
                "payment_version_info":
                serialize_model_object(
                    coupon_redemption.coupon_version.payment_version),
            },
        } for coupon_redemption in order.couponredemption_set.all()],
        "run_enrollments": [
            enrollment.run.courseware_id
            for enrollment in order.courserunenrollment_set.all()
        ],
        "total_price":
        str(
            get_product_version_price_with_discount(
                product_version=lines[0].product_version,
                coupon_version=order.couponredemption_set.first().
                coupon_version,
            )) if has_lines else "",
        "receipts": [
            serialize_model_object(receipt)
            for receipt in order.receipt_set.all()
        ],
    }
Exemplo n.º 33
0
 def setUpTestData(cls):
     with mute_signals(post_save):
         cls.profile = profile = ProfileFactory.create()
     cls.user = profile.user
     EducationFactory.create(profile=profile)
     EmploymentFactory.create(profile=profile)
     # create a normal program
     program = ProgramFactory.create()
     cls.enrollments = cls._generate_cached_enrollments(cls.user,
                                                        program,
                                                        num_course_runs=2)
     certificate_grades_vals = [0.7, 0.8]
     cls.current_grades_vals = [0.9, 1.0]
     cls.certificates = []
     cls.current_grades = []
     for i, enrollment in enumerate(cls.enrollments):
         cls.certificates.append(
             CachedCertificateFactory.create(
                 user=cls.user,
                 course_run=enrollment.course_run,
                 data={
                     "grade": certificate_grades_vals[i],
                     "certificate_type": "verified",
                     "course_id": enrollment.course_run.edx_course_key,
                     "status": "downloadable",
                 }))
         cls.current_grades.append(
             CachedCurrentGradeFactory.create(
                 user=cls.user,
                 course_run=enrollment.course_run,
                 data={
                     "passed": True,
                     "percent": cls.current_grades_vals[i],
                     "course_key": enrollment.course_run.edx_course_key,
                 }))
         FinalGradeFactory.create(
             user=cls.user,
             course_run=enrollment.course_run,
             grade=certificate_grades_vals[i],
             passed=True,
         )
     non_fa_cached_edx_data = CachedEdxUserData(cls.user, program=program)
     non_fa_mmtrack = MMTrack(cls.user, program, non_fa_cached_edx_data)
     cls.serialized_enrollments = UserProgramSearchSerializer.serialize_enrollments(
         non_fa_mmtrack)
     cls.serialized_course_enrollments = UserProgramSearchSerializer.serialize_course_enrollments(
         non_fa_mmtrack)
     cls.semester_enrollments = UserProgramSearchSerializer.serialize_course_runs_enrolled(
         non_fa_mmtrack)
     cls.program_enrollment = ProgramEnrollment.objects.create(
         user=cls.user, program=program)
     # create a financial aid program
     cls.fa_program, _ = create_program()
     cls.fa_program_enrollment = ProgramEnrollment.objects.create(
         user=cls.user, program=cls.fa_program)
     cls.fa_enrollments = cls._generate_cached_enrollments(
         cls.user, cls.fa_program, num_course_runs=2)
     cls.current_grades = []
     for i, enrollment in enumerate(cls.fa_enrollments):
         order = OrderFactory.create(user=cls.user, status='fulfilled')
         LineFactory.create(order=order,
                            course_key=enrollment.course_run.edx_course_key)
         cls.current_grades.append(
             CachedCurrentGradeFactory.create(
                 user=cls.user,
                 course_run=enrollment.course_run,
                 data={
                     "passed": True,
                     "percent": cls.current_grades_vals[i],
                     "course_key": enrollment.course_run.edx_course_key,
                 }))
         FinalGradeFactory.create(
             user=cls.user,
             course_run=enrollment.course_run,
             grade=cls.current_grades_vals[i],
             passed=True,
         )
     fa_cached_edx_data = CachedEdxUserData(cls.user,
                                            program=cls.fa_program)
     fa_mmtrack = MMTrack(cls.user, cls.fa_program, fa_cached_edx_data)
     cls.fa_serialized_course_enrollments = (
         UserProgramSearchSerializer.serialize_course_enrollments(
             fa_mmtrack))
     cls.fa_serialized_enrollments = (
         UserProgramSearchSerializer.serialize_enrollments(fa_mmtrack))
Exemplo n.º 34
0
 def setUpTestData(cls):
     with mute_signals(post_save):
         cls.profile = profile = ProfileFactory.create()
     cls.user = profile.user
     EducationFactory.create(profile=profile)
     EmploymentFactory.create(profile=profile)
     # create a normal program
     program = ProgramFactory.create()
     cls.enrollments = cls._generate_cached_enrollments(cls.user, program, num_course_runs=2)
     certificate_grades_vals = [0.7, 0.8]
     cls.current_grades_vals = [0.9, 1.0]
     cls.certificates = []
     cls.current_grades = []
     for i, enrollment in enumerate(cls.enrollments):
         cls.certificates.append(
             CachedCertificateFactory.create(
                 user=cls.user,
                 course_run=enrollment.course_run,
                 data={
                     "grade": certificate_grades_vals[i],
                     "certificate_type": "verified",
                     "course_id": enrollment.course_run.edx_course_key,
                     "status": "downloadable",
                 }
             )
         )
         cls.current_grades.append(
             CachedCurrentGradeFactory.create(
                 user=cls.user,
                 course_run=enrollment.course_run,
                 data={
                     "passed": True,
                     "percent": cls.current_grades_vals[i],
                     "course_key": enrollment.course_run.edx_course_key,
                 }
             )
         )
         FinalGradeFactory.create(
             user=cls.user,
             course_run=enrollment.course_run,
             grade=certificate_grades_vals[i],
             passed=True,
         )
     non_fa_cached_edx_data = CachedEdxUserData(cls.user, program=program)
     non_fa_mmtrack = MMTrack(cls.user, program, non_fa_cached_edx_data)
     cls.serialized_enrollments = UserProgramSearchSerializer.serialize_enrollments(non_fa_mmtrack)
     cls.serialized_course_enrollments = UserProgramSearchSerializer.serialize_course_enrollments(non_fa_mmtrack)
     cls.semester_enrollments = UserProgramSearchSerializer.serialize_course_runs_enrolled(non_fa_mmtrack)
     cls.program_enrollment = ProgramEnrollment.objects.create(user=cls.user, program=program)
     # create a financial aid program
     cls.fa_program, _ = create_program()
     cls.fa_program_enrollment = ProgramEnrollment.objects.create(user=cls.user, program=cls.fa_program)
     cls.fa_enrollments = cls._generate_cached_enrollments(cls.user, cls.fa_program, num_course_runs=2)
     cls.current_grades = []
     for i, enrollment in enumerate(cls.fa_enrollments):
         order = OrderFactory.create(user=cls.user, status='fulfilled')
         LineFactory.create(order=order, course_key=enrollment.course_run.edx_course_key)
         cls.current_grades.append(
             CachedCurrentGradeFactory.create(
                 user=cls.user,
                 course_run=enrollment.course_run,
                 data={
                     "passed": True,
                     "percent": cls.current_grades_vals[i],
                     "course_key": enrollment.course_run.edx_course_key,
                 }
             )
         )
         FinalGradeFactory.create(
             user=cls.user,
             course_run=enrollment.course_run,
             grade=cls.current_grades_vals[i],
             passed=True,
         )
     fa_cached_edx_data = CachedEdxUserData(cls.user, program=cls.fa_program)
     fa_mmtrack = MMTrack(cls.user, cls.fa_program, fa_cached_edx_data)
     cls.fa_serialized_course_enrollments = (
         UserProgramSearchSerializer.serialize_course_enrollments(fa_mmtrack)
     )
     cls.fa_serialized_enrollments = (
         UserProgramSearchSerializer.serialize_enrollments(fa_mmtrack)
     )
Exemplo n.º 35
0
 def test_order_str(self):
     """Test Order.__str__"""
     order = LineFactory.create().order
     assert str(order) == "Order {}, status={} for user={}".format(order.id, order.status, order.user)