def test_with_orders(self):
        """
        The view should return a list of the user's orders, sorted reverse chronologically,
        filtered by current site's partner.
        """
        order = create_order(site=self.site, user=self.user)
        site = SiteConfigurationFactory().site
        create_order(site=site, user=self.user)
        response = self.client.get(self.path, HTTP_AUTHORIZATION=self.token)
        self.assertEqual(response.status_code, 200)
        content = json.loads(response.content.decode('utf-8'))

        self.assertEqual(Order.objects.count(), 2)
        self.assertEqual(content['count'], 1)
        self.assertEqual(content['results'][0]['number'],
                         six.text_type(order.number))

        # Test ordering
        order_2 = create_order(site=self.site, user=self.user)
        response = self.client.get(self.path, HTTP_AUTHORIZATION=self.token)
        self.assertEqual(response.status_code, 200)
        content = json.loads(response.content.decode('utf-8'))

        self.assertEqual(content['count'], 2)
        self.assertEqual(content['results'][0]['number'],
                         six.text_type(order_2.number))
        self.assertEqual(content['results'][1]['number'],
                         six.text_type(order.number))
    def test_create_refund_for_duplicate_orders_only(self, commit):
        """
        Test that refund is generated for manual enrollment orders only if having some duplicate enrollments.
        """

        orders = self.create_manual_order()
        filename = 'orders_file.txt'
        self.create_orders_file(orders, filename)

        # create duplicate order having course_entitlement product
        order_with_duplicate = orders[0]
        order_without_duplicate = orders[1]

        course_uuid = FAKER.uuid4()  # pylint: disable=no-member
        order = Order.objects.get(number=order_with_duplicate['detail'])
        course_entitlement = create_or_update_course_entitlement(
            'verified', 100, order.partner, course_uuid, 'Course Entitlement'
        )
        basket = factories.BasketFactory(owner=order.user, site=order.site)
        basket.add_product(course_entitlement, 1)
        create_order(basket=basket, user=order.user)
        self.mock_access_token_response()
        self.mock_course_run_detail_endpoint(
            self.course,
            discovery_api_url=order.site.siteconfiguration.discovery_api_url,
            course_run_info={
                'course_uuid': course_uuid
            }
        )

        self.assertFalse(Refund.objects.exists())
        with LogCapture(LOGGER_NAME) as log_capture:
            params = ['create_refund_for_orders', '--order-numbers-file={}'.format(filename), '--refund-duplicate-only',
                      '--sleep-time=0.5']
            if not commit:
                params.append('--no-commit')
            call_command(*params)
            log_capture.check_present(
                (LOGGER_NAME, 'INFO', 'Sleeping for 0.5 second/seconds'),
            )
            log_capture.check_present(
                (
                    LOGGER_NAME,
                    'ERROR',
                    '[Ecommerce Order Refund]: Completed refund generation. 0 of 2 failed and 1 skipped.\n'
                    'Failed orders: \n'
                    'Skipped orders: {}\n'.format(order_without_duplicate['detail']),
                ),
            )
        if commit:
            self.assertEqual(Refund.objects.count(), 1)

            refund = Refund.objects.get(order=order)
            self.assert_refund_matches_order(refund, order)
            order = Order.objects.get(number=order_without_duplicate['detail'])
            self.assertFalse(order.refunds.exists())
        else:
            self.assertEqual(Refund.objects.count(), 0)
Beispiel #3
0
    def test_enable_hoist_order_history(self, enable_hoist_order_history_flag):
        """ Verify that orders contain the Order History flag value """
        with override_flag(ENABLE_HOIST_ORDER_HISTORY, active=enable_hoist_order_history_flag):
            create_order(site=self.site, user=self.user)
            response = self.client.get(self.path, HTTP_AUTHORIZATION=self.token)
            self.assertEqual(response.status_code, 200)
            content = json.loads(response.content.decode('utf-8'))

            self.assertEqual(content['results'][0]['enable_hoist_order_history'], enable_hoist_order_history_flag)
Beispiel #4
0
    def test_non_course_order(self):
        """ Refunds should NOT be created for orders with no line items related to courses. """
        Refund.objects.all().delete()
        create_order(site=self.site, user=self.user)
        self.assertEqual(Refund.objects.count(), 0)

        data = self._get_data(self.user.username, self.course_id)
        response = self.client.post(self.path, data, JSON_CONTENT_TYPE)

        self.assert_ok_response(response)
        self.assertEqual(Refund.objects.count(), 0)
Beispiel #5
0
    def test_with_other_users_orders(self):
        """ The view should only return orders for the authenticated users. """
        other_user = self.create_user()
        create_order(site=self.site, user=other_user)
        response = self.client.get(self.path, HTTP_AUTHORIZATION=self.token)
        self.assert_empty_result_response(response)

        order = create_order(site=self.site, user=self.user)
        response = self.client.get(self.path, HTTP_AUTHORIZATION=self.token)
        content = json.loads(response.content.decode('utf-8'))
        self.assertEqual(content['count'], 1)
        self.assertEqual(content['results'][0]['number'], six.text_type(order.number))
    def test_username_filter_with_staff(self):
        """ Verify the staff user can filter data by username."""

        # create two orders for different users
        order = create_order(site=self.site, user=self.user)
        other_user = self.create_user()
        other_order = create_order(site=self.site, user=other_user)

        requester = self.create_user(is_staff=True)
        self.client.login(email=requester.email, password=self.password)

        self.assert_list_with_username_filter(self.user, order)
        self.assert_list_with_username_filter(other_user, other_order)
    def test_notify_purchaser(self, mock_task):
        """ Verify the notification is scheduled if the site has notifications enabled
        and the refund is for a course seat.
        """
        site_configuration = self.site.siteconfiguration
        site_configuration.send_refund_notifications = True

        user = UserFactory()

        course = CourseFactory(partner=self.partner)
        price = Decimal(100.00)
        product = course.create_or_update_seat('verified', True, price)

        basket = create_basket(site=self.site, owner=user, empty=True)
        basket.add_product(product)

        order = create_order(basket=basket, user=user)
        order_url = get_receipt_page_url(site_configuration, order.number)

        refund = Refund.create_with_lines(order, order.lines.all())

        with LogCapture(REFUND_MODEL_LOGGER_NAME) as logger:
            refund._notify_purchaser()  # pylint: disable=protected-access

        msg = 'Course refund notification scheduled for Refund [{}].'.format(refund.id)
        logger.check_present(
            (REFUND_MODEL_LOGGER_NAME, 'INFO', msg)
        )

        amount = format_currency(order.currency, price)
        mock_task.assert_called_once_with(
            user.email, refund.id, amount, course.name, order.number, order_url, site_code=self.partner.short_code
        )
Beispiel #8
0
    def create_order_with_billing_address(self):
        """ Creates an order object with a bit of extra information for HubSpot unit tests"""
        enrollment_code = Product.objects.get(
            product_class__name=ENROLLMENT_CODE_PRODUCT_CLASS_NAME)
        user = UserFactory()
        basket = factories.BasketFactory(owner=user, site=self.site)
        basket.add_product(enrollment_code, self.QUANTITY)

        # add organization and purchaser attributes manually to the basket for testing purposes
        basket_data = {
            'organization': 'Dummy Business Client',
            PURCHASER_BEHALF_ATTRIBUTE: 'True'
        }
        basket_add_organization_attribute(basket, basket_data)

        # add some additional data the billing address to exercise some of the code paths in the unit we are testing
        billing_address = factories.BillingAddressFactory()
        billing_address.line2 = 'Suite 321'
        billing_address.line4 = "City"
        billing_address.state = "State"
        billing_address.country.name = "United States of America"

        # create new order adding in the additional billing address info
        return create_order(number=2,
                            basket=basket,
                            user=user,
                            billing_address=billing_address)
    def test_stop_sailthru_update_on_multi_product_baskets(
            self, mock_log_error, mock_update_course_enrollment):
        """ Verify Sailthru is not contacted for multi-product baskets. """
        # Create multi-product basket
        seat = self.course.create_or_update_seat('verified', False, 100, None)
        other_course = CourseFactory(partner=self.partner)
        other_seat = other_course.create_or_update_seat(
            'verified', False, 100, None)
        basket = BasketFactory(owner=self.user, site=self.site)
        basket.add_product(seat)
        basket.add_product(other_seat)
        multi_product_order = create_order(number=2,
                                           basket=basket,
                                           user=self.user,
                                           site=self.site)

        # This method takes an argument to determine whether that product is part of a multi-product basket
        process_basket_addition(None,
                                request=self.request,
                                user=self.user,
                                product=seat,
                                is_multi_product_basket=True)
        self.assertFalse(mock_update_course_enrollment.called)
        self.assertFalse(mock_log_error.called)

        # This method looks at the number of lines in the order to determine if the basket has multiple products
        process_checkout_complete(None,
                                  order=multi_product_order,
                                  request=None)
        self.assertFalse(mock_update_course_enrollment.called)
        self.assertFalse(mock_log_error.called)
Beispiel #10
0
    def test_handle_post_order_for_bulk_purchase(self, __):
        """
        Ensure that the bulk purchase order is linked to the provided business
        client when the method `handle_post_order` is invoked.
        """
        toggle_switch(ENROLLMENT_CODE_SWITCH, True)

        course = CourseFactory(partner=self.partner)
        course.create_or_update_seat('verified',
                                     True,
                                     50,
                                     create_enrollment_code=True)
        enrollment_code = Product.objects.get(
            product_class__name=ENROLLMENT_CODE_PRODUCT_CLASS_NAME)
        user = UserFactory()
        basket = BasketFactory(owner=user, site=self.site)
        basket.add_product(enrollment_code, quantity=1)
        order = create_order(number=1, basket=basket, user=user)
        request_data = {
            'organization': 'Dummy Business Client',
            PURCHASER_BEHALF_ATTRIBUTE: 'False',
        }
        # Manually add organization and purchaser attributes on the basket for testing
        basket_add_organization_attribute(basket, request_data)

        EdxOrderPlacementMixin().handle_post_order(order)

        # Now verify that a new business client has been created in current
        # order is now linked with that client through Invoice model.
        business_client = BusinessClient.objects.get(
            name=request_data['organization'])
        assert Invoice.objects.get(
            order=order).business_client == business_client
Beispiel #11
0
    def test_handle_post_order_for_seat_purchase(self, __):
        """
        Ensure that the single seat purchase order is not linked any business
        client when the method `handle_post_order` is invoked.
        """
        toggle_switch(ENROLLMENT_CODE_SWITCH, False)

        course = CourseFactory(partner=self.partner)
        verified_product = course.create_or_update_seat('verified', True, 50)
        user = UserFactory()
        basket = BasketFactory(owner=user, site=self.site)
        basket.add_product(verified_product, quantity=1)
        order = create_order(number=1, basket=basket, user=user)
        request_data = {
            'organization': 'Dummy Business Client',
            PURCHASER_BEHALF_ATTRIBUTE: 'False',
        }
        # Manually add organization and purchaser attributes on the basket for testing
        basket_add_organization_attribute(basket, request_data)

        EdxOrderPlacementMixin().handle_post_order(order)

        # Now verify that the single seat order is not linked to business
        # client by checking that there is no record for BusinessClient.
        assert not BusinessClient.objects.all()
Beispiel #12
0
    def test_notify_purchaser(self, mock_task):
        """ Verify the notification is scheduled if the site has notifications enabled
        and the refund is for a course seat.
        """
        site_configuration = self.site.siteconfiguration
        site_configuration.send_refund_notifications = True

        user = UserFactory()

        course = CourseFactory()
        price = Decimal(100.00)
        product = course.create_or_update_seat('verified', True, price, self.partner)

        basket = create_basket(empty=True)
        basket.site = self.site
        basket.add_product(product)

        order = create_order(basket=basket, user=user)
        order_url = get_receipt_page_url(site_configuration, order.number)

        refund = Refund.create_with_lines(order, order.lines.all())

        with LogCapture(REFUND_MODEL_LOGGER_NAME) as l:
            refund._notify_purchaser()  # pylint: disable=protected-access

        msg = 'Course refund notification scheduled for Refund [{}].'.format(refund.id)
        l.check(
            (REFUND_MODEL_LOGGER_NAME, 'INFO', msg)
        )

        amount = format_currency(order.currency, price)
        mock_task.assert_called_once_with(
            user.email, refund.id, amount, course.name, order.number, order_url, site_code=self.partner.short_code
        )
Beispiel #13
0
    def test_create_assignments_for_multi_use_per_customer(self, __):
        """
        Verify the `create_assignments_for_multi_use_per_customer` works as expected for `MULTI_USE_PER_CUSTOMER`.
        """
        coupon_max_global_applications = 10
        enterprise_offer = EnterpriseOfferFactory(
            max_global_applications=coupon_max_global_applications)
        voucher = VoucherFactory(usage=Voucher.MULTI_USE_PER_CUSTOMER)
        voucher.offers.add(enterprise_offer)
        basket = create_basket(owner=self.user, site=self.site)
        basket.vouchers.add(voucher)
        order = create_order(user=self.user, basket=basket)

        assert OfferAssignment.objects.all().count() == 0

        EdxOrderPlacementMixin().create_assignments_for_multi_use_per_customer(
            order)
        EdxOrderPlacementMixin().update_assigned_voucher_offer_assignment(
            order)

        assert OfferAssignment.objects.all().count(
        ) == coupon_max_global_applications
        assert OfferAssignment.objects.filter(
            offer=enterprise_offer,
            code=voucher.code,
            user_email=basket.owner.email,
            status=OFFER_ASSIGNED).count() == 9
        assert OfferAssignment.objects.filter(
            offer=enterprise_offer,
            code=voucher.code,
            user_email=basket.owner.email,
            status=OFFER_REDEEMED).count() == 1
Beispiel #14
0
    def create_order(self, user=None, credit=False, multiple_lines=False, free=False,
                     entitlement=False, status=ORDER.COMPLETE, id_verification_required=False):
        user = user or self.user
        basket = BasketFactory(owner=user, site=self.site)

        if credit:
            basket.add_product(self.credit_product)
        elif multiple_lines:
            basket.add_product(self.verified_product)
            basket.add_product(self.honor_product)
        elif free:
            basket.add_product(self.honor_product)
        elif entitlement:
            course_entitlement = create_or_update_course_entitlement(
                certificate_type='verified',
                price=100,
                partner=self.partner,
                UUID='111',
                title='Foo',
                id_verification_required=id_verification_required
            )
            basket.add_product(course_entitlement)
        else:
            basket.add_product(self.verified_product)

        order = create_order(basket=basket, user=user)
        order.status = status
        if entitlement:
            entitlement_option = Option.objects.get(code='course_entitlement')
            line = order.lines.first()
            line.attributes.create(option=entitlement_option, value='111')
        order.save()
        return order
    def test_notify_purchaser_course_entielement(self, mock_task):
        """ Verify the notification is scheduled if the site has notifications enabled
        and the refund is for a course entitlement.
        """
        site_configuration = self.site.siteconfiguration
        site_configuration.send_refund_notifications = True

        user = UserFactory()

        course_entitlement = create_or_update_course_entitlement(
            'verified', 100, self.partner, '111-222-333-444',
            'Course Entitlement')
        basket = create_basket(site=self.site, owner=user, empty=True)
        basket.add_product(course_entitlement, 1)

        order = create_order(number=1, basket=basket, user=user)
        order_url = get_receipt_page_url(site_configuration, order.number)

        refund = Refund.create_with_lines(order, order.lines.all())

        with LogCapture(REFUND_MODEL_LOGGER_NAME) as l:
            refund._notify_purchaser()  # pylint: disable=protected-access

        msg = 'Course refund notification scheduled for Refund [{}].'.format(
            refund.id)
        l.check((REFUND_MODEL_LOGGER_NAME, 'INFO', msg))

        amount = format_currency(order.currency, 100)
        mock_task.assert_called_once_with(user.email,
                                          refund.id,
                                          amount,
                                          course_entitlement.title,
                                          order.number,
                                          order_url,
                                          site_code=self.partner.short_code)
Beispiel #16
0
    def test_issue_credit(self):
        """
            Tests issuing credit with AuthorizeNet processor
        """
        with patch(
            'ecommerce.extensions.payment.processors.authorizenet.createTransactionController',
            autospec=True
        ) as mock_controller:
            reference_transaction_id = self.transaction_id
            expected_transaction_id = self.refund_transaction_id

            record_transaction_detail_processor_response(self.processor, reference_transaction_id, self.basket)

            data = {
                "result_code": "Ok",
                "message_code": "I00001",
                "response_code": "1",
                "transaction_id": expected_transaction_id,
                "reference_transaction_id": reference_transaction_id,
                "sub_template": refund_success_response,
            }

            refund_response_xml = get_authorizenet_refund_reponse_xml(data)
            refund_response = objectify.fromstring(refund_response_xml)
            mock_controller.return_value.getresponse.return_value = refund_response

            expected_refund_transaction_dict = LxmlObjectJsonEncoder().encode(refund_response)
            order = create_order(basket=self.basket)
            actual_transaction_id = self.processor.issue_credit(
                order.number, order.basket, reference_transaction_id, order.total_incl_tax, order.currency)

            self.assertEqual(int(expected_transaction_id), actual_transaction_id)
            self.assert_processor_response_recorded(
                self.processor_name, actual_transaction_id, expected_refund_transaction_dict, basket=self.basket)
Beispiel #17
0
    def setUp(self):
        super(DeleteOrderedBasketsCommandTests, self).setUp()

        # Create baskets with and without orders
        self.orders = [create_order() for __ in range(0, 2)]
        self.unordered_baskets = [
            factories.BasketFactory() for __ in range(0, 3)
        ]

        # Create invoiced baskets.
        self.invoiced_orders = [create_order() for __ in range(0, 2)]
        self.invoiced_baskets = [
            order.basket for order in self.invoiced_orders
        ]
        for order in self.invoiced_orders:
            Invoice.objects.create(basket=order.basket, order=order)
Beispiel #18
0
 def setUp(self):
     super(CouponFulfillmentModuleTest, self).setUp()
     coupon = self.create_coupon()
     user = factories.UserFactory()
     basket = factories.BasketFactory(owner=user, site=self.site)
     basket.add_product(coupon, 1)
     self.order = create_order(number=1, basket=basket, user=user)
Beispiel #19
0
    def test_track_completed_order(self):
        """ An event should be sent to Segment. """

        with mock.patch(
                'ecommerce.extensions.checkout.signals.track_segment_event'
        ) as mock_track:
            order = self.prepare_order('verified')
            track_completed_order(None, order)
            properties = self._generate_event_properties(order)
            mock_track.assert_called_once_with(order.site,
                                               order.user,
                                               'Order Completed',
                                               properties,
                                               traits=properties)

            # We should be able to fire events even if the product is not related to a course.
            mock_track.reset_mock()
            order = create_order()
            track_completed_order(None, order)
            properties = self._generate_event_properties(order)
            mock_track.assert_called_once_with(order.site,
                                               order.user,
                                               'Order Completed',
                                               properties,
                                               traits=properties)
Beispiel #20
0
    def test_handle_shipping_event_email_opt_in(self, expected_opt_in):
        """
        Verify that the shipping sends email opt in if specified.
        """
        basket = create_basket()
        product = factories.create_product()
        factories.create_stockrecord(product, num_in_stock=2)
        basket.add_product(product)

        order = create_order(basket=basket)
        lines = order.lines.all()

        with mock.patch(
                'ecommerce.extensions.order.processing.fulfillment_api.fulfill_order'
        ) as mock_fulfill:
            EventHandler().handle_shipping_event(
                order,
                self.shipping_event_type,
                lines,
                [1, 1],
                email_opt_in=expected_opt_in,
            )
            mock_fulfill.assert_called_once_with(order,
                                                 lines,
                                                 email_opt_in=expected_opt_in)
Beispiel #21
0
    def test_issue_credit_error(self):
        """
            Verify the processor raises RefundError on receiving error response from AuthorizeNet (Refund) API.
        """
        with patch(
            'ecommerce.extensions.payment.processors.authorizenet.createTransactionController',
            autospec=True
        ) as mock_controller:
            reference_transaction_id = self.transaction_id
            record_transaction_detail_processor_response(self.processor, reference_transaction_id, self.basket)

            data = {
                "result_code": "Error",
                "message_code": "E00001",
                "response_code": "3",
                "transaction_id": "0",
                "reference_transaction_id": reference_transaction_id,
                "sub_template": refund_error_response,
            }

            refund_response_xml = get_authorizenet_refund_reponse_xml(data)
            refund_response = objectify.fromstring(refund_response_xml)
            mock_controller.return_value.getresponse.return_value = refund_response

            order = create_order(basket=self.basket)
            self.assertRaises(
                RefundError, self.processor.issue_credit, order.number, order.basket, reference_transaction_id,
                order.total_incl_tax, order.currency
            )
Beispiel #22
0
    def test_issue_credit_error(self):
        order = create_order(basket=self.basket)

        with mock.patch('stripe.Refund.create') as refund_mock:
            refund_mock.side_effect = stripe.error.APIError
            self.assertRaises(GatewayError, self.processor.issue_credit,
                              order.number, order.basket, '123',
                              order.total_incl_tax, order.currency)
 def setUp(self):
     super(JournalFulfillmentModuleTest, self).setUp()
     user = self.create_user(is_staff=True)
     self.client.login(username=user.username, password=self.password)
     basket = factories.BasketFactory(owner=user, site=self.site)
     basket.add_product(self.create_product(self.client), 1)
     self.order = create_order(number=1, basket=basket, user=user)
     self.lines = self.order.lines.all()
Beispiel #24
0
    def _create_order(self, price, mode='verified'):
        seat = self.course.create_or_update_seat(mode, False, price, self.partner, None)

        basket = BasketFactory(owner=self.user, site=self.site)
        basket.add_product(seat, 1)
        order = create_order(number=1, basket=basket, user=self.user, site=self.site)
        order.total_excl_tax = price
        return seat, order
Beispiel #25
0
    def test_contains_coupon(self):
        self.assertFalse(self.order.contains_coupon)

        product = factories.create_product(product_class=COUPON_PRODUCT_CLASS_NAME)
        basket = create_basket(empty=True)
        factories.create_stockrecord(product, num_in_stock=1)
        basket.add_product(product)
        order = create_order(basket=basket)
        self.assertTrue(order.contains_coupon)
Beispiel #26
0
 def test_already_purchased_product(self):
     """
     Verify student can not place multiple orders for single course seat
     """
     course = CourseFactory()
     product = course.create_or_update_seat("Verified", True, 0, self.partner)
     stock_record = StockRecordFactory(product=product, partner=self.partner)
     catalog = Catalog.objects.create(partner=self.partner)
     catalog.stock_records.add(stock_record)
     sku = stock_record.partner_sku
     basket = factories.BasketFactory(owner=self.user, site=self.site)
     basket.add_product(product, 1)
     create_order(user=self.user, basket=basket)
     url = '{path}?sku={sku}'.format(path=self.path, sku=sku)
     expected_content = 'You have already purchased {course} seat.'.format(course=product.course.name)
     response = self.client.get(url)
     self.assertEqual(response.status_code, 200)
     self.assertEqual(response.context['error'], expected_content)
Beispiel #27
0
 def setUp(self):
     super(EnrollmentCodeFulfillmentModuleTests, self).setUp()
     course = CourseFactory(partner=self.partner)
     course.create_or_update_seat('verified', True, 50, create_enrollment_code=True)
     enrollment_code = Product.objects.get(product_class__name=ENROLLMENT_CODE_PRODUCT_CLASS_NAME)
     user = UserFactory()
     basket = factories.BasketFactory(owner=user, site=self.site)
     basket.add_product(enrollment_code, self.QUANTITY)
     self.order = create_order(number=1, basket=basket, user=user)
Beispiel #28
0
    def test_create_offer_assignments_for_updated_max_uses(self, __):
        """
        Verify the `create_assignments_for_multi_use_per_customer` works as expected for
        `MULTI_USE_PER_CUSTOMER` when `max_global_applications` is updated for existing voucher.
        """
        coupon_max_global_applications = 1
        enterprise_offer = EnterpriseOfferFactory(
            max_global_applications=coupon_max_global_applications)
        voucher = VoucherFactory(usage=Voucher.MULTI_USE_PER_CUSTOMER)
        voucher.offers.add(enterprise_offer)
        basket = create_basket(owner=self.user, site=self.site)
        basket.vouchers.add(voucher)
        order = create_order(user=self.user, basket=basket)

        assert OfferAssignment.objects.all().count() == 0

        EdxOrderPlacementMixin().create_assignments_for_multi_use_per_customer(
            order)
        EdxOrderPlacementMixin().update_assigned_voucher_offer_assignment(
            order)

        assert OfferAssignment.objects.all().count(
        ) == coupon_max_global_applications
        assert OfferAssignment.objects.filter(
            offer=enterprise_offer,
            code=voucher.code,
            user_email=basket.owner.email,
            status=OFFER_REDEEMED).count() == 1

        # update max_global_applications
        coupon_new_max_global_applications = 5
        enterprise_offer.max_global_applications = coupon_new_max_global_applications
        enterprise_offer.save()

        assert voucher.enterprise_offer.max_global_applications == coupon_new_max_global_applications

        EdxOrderPlacementMixin().create_assignments_for_multi_use_per_customer(
            order)

        assert OfferAssignment.objects.all().count(
        ) == coupon_new_max_global_applications
        assert OfferAssignment.objects.filter(
            offer=enterprise_offer,
            code=voucher.code,
            user_email=basket.owner.email,
            status=OFFER_ASSIGNED).count() == 4
        assert OfferAssignment.objects.filter(
            offer=enterprise_offer,
            code=voucher.code,
            user_email=basket.owner.email,
            status=OFFER_REDEEMED).count() == 1

        # call once again to verify nothing is created because all available slots are assigned
        EdxOrderPlacementMixin().create_assignments_for_multi_use_per_customer(
            order)
        assert OfferAssignment.objects.all().count(
        ) == coupon_new_max_global_applications
Beispiel #29
0
    def test_staff_superuser(self, is_staff, is_superuser):
        """ The view should return all orders for when authenticating as a staff member or superuser. """
        admin_user = self.create_user(is_staff=is_staff, is_superuser=is_superuser)
        order = create_order(site=self.site, user=self.user)

        response = self.client.get(self.path, HTTP_AUTHORIZATION=self.generate_jwt_token_header(admin_user))
        content = json.loads(response.content.decode('utf-8'))
        self.assertEqual(content['count'], 1)
        self.assertEqual(content['results'][0]['number'], six.text_type(order.number))
Beispiel #30
0
    def setUp(self):
        super(OrderDetailViewTestMixin, self).setUp()

        user = self.create_user()
        self.order = factories.create_order(user=user)

        # Add a product attribute to one of the order items
        ProductAttributeValueFactory(product=self.order.lines.first().product)

        self.token = self.generate_jwt_token_header(user)
Beispiel #31
0
    def setUp(self):
        super(OrderDetailViewTestMixin, self).setUp()

        user = self.create_user()
        self.order = factories.create_order(site=self.site, user=user)

        # Add a product attribute to one of the order items
        ProductAttributeValueFactory(product=self.order.lines.first().product)

        self.token = self.generate_jwt_token_header(user)
    def test_orders_with_multiple_sites(self):
        """
        The view should return a list of the user's orders for multiple sites against same partner.
        """
        order = create_order(site=self.site, user=self.user)
        second_order = create_order(site=self.site, user=self.user)
        response = self.client.get(self.path, HTTP_AUTHORIZATION=self.token)
        self.assertEqual(response.status_code, 200)
        content = json.loads(response.content.decode('utf-8'))

        self.assertEqual(Order.objects.count(), 2)
        self.assertEqual(content['count'], 2)
        self.assertEqual(content['results'][0]['number'],
                         six.text_type(second_order.number))
        self.assertEqual(content['results'][1]['number'],
                         six.text_type(order.number))

        # Configure new site for same partner.
        domain = 'testserver.fake.internal'
        site_configuration = SiteConfigurationFactory(
            from_email='*****@*****.**',
            oauth_settings={
                'SOCIAL_AUTH_EDX_OAUTH2_KEY': 'key',
                'SOCIAL_AUTH_EDX_OAUTH2_SECRET': 'secret'
            },
            partner=self.partner,
            segment_key='fake_segment_key',
            site__domain=domain,
            base_cookie_domain=domain,
        )

        self.request.site = site_configuration.site
        self.client = self.client_class(SERVER_NAME=domain)

        response = self.client.get(self.path, HTTP_AUTHORIZATION=self.token)
        self.assertEqual(response.status_code, 200)
        content = json.loads(response.content.decode('utf-8'))

        self.assertEqual(content['count'], 2)
        self.assertEqual(content['results'][0]['number'],
                         six.text_type(second_order.number))
        self.assertEqual(content['results'][1]['number'],
                         six.text_type(order.number))
Beispiel #33
0
    def test_notify_purchaser_with_notifications_disabled(self, mock_task):
        """ Verify no notification is sent if the functionality is disabled for the site. """
        self.site.siteconfiguration.send_refund_notifications = False
        order = create_order(site=self.site)
        refund = self.create_refund(order=order)

        with LogCapture(REFUND_MODEL_LOGGER_NAME) as l:
            refund._notify_purchaser()  # pylint: disable=protected-access

        msg = 'Refund notifications are disabled for Partner [{code}]. ' \
              'No notification will be sent for Refund [{id}]'.format(code=self.partner.short_code, id=refund.id)
        l.check(
            (REFUND_MODEL_LOGGER_NAME, 'INFO', msg)
        )
        self.assertFalse(mock_task.called)
Beispiel #34
0
    def test_notify_purchaser_without_course_product_class(self, mock_task):
        """ Verify a notification is not sent if the refunded item is not a course seat. """
        self.site.siteconfiguration.send_refund_notifications = True

        order = create_order(site=self.site)
        product_class = order.lines.first().product.get_product_class().name
        self.assertNotEqual(product_class, SEAT_PRODUCT_CLASS_NAME)

        refund = self.create_refund(order=order)

        with LogCapture(REFUND_MODEL_LOGGER_NAME) as l:
            refund._notify_purchaser()  # pylint: disable=protected-access

        msg = ('No refund notification will be sent for Refund [{id}]. The notification supports product '
               'lines of type Course, not [{product_class}].').format(product_class=product_class, id=refund.id)
        l.check(
            (REFUND_MODEL_LOGGER_NAME, 'WARNING', msg)
        )
        self.assertFalse(mock_task.called)