def test_mismatched_basket_owner(self):
        """ Verify the view returns an HTTP 400 status if the posted basket does not belong to the requesting user. """
        basket = factories.BasketFactory()
        self.assert_basket_retrieval_error(basket.id)

        basket = factories.BasketFactory(owner=self.create_user())
        self.assert_basket_retrieval_error(basket.id)
    def test_transfers_vouchers_to_new_basket(self):
        baskets = [factories.BasketFactory(), factories.BasketFactory()]
        voucher = factories.VoucherFactory()
        baskets[0].vouchers.add(voucher)
        baskets[1].merge(baskets[0])

        self.assertEqual(1, baskets[1].vouchers.all().count())
Exemple #3
0
    def test_moving_to_saved_basket_updates_existing(self):
        self.user = factories.UserFactory()
        product = factories.ProductFactory()

        basket = factories.BasketFactory(owner=self.user)
        basket.add_product(product)

        saved_basket = factories.BasketFactory(owner=self.user,
                                               status=Basket.SAVED)
        saved_basket.add_product(product)

        response = self.get(reverse('basket:summary'))
        formset = response.context['formset']
        form = formset.forms[0]

        data = {
            formset.add_prefix('INITIAL_FORMS'): 1,
            formset.add_prefix('TOTAL_FORMS'): 1,
            formset.add_prefix('MIN_FORMS'): 0,
            formset.add_prefix('MAX_NUM_FORMS'): 1,
            form.add_prefix('id'): form.instance.pk,
            form.add_prefix('quantity'): form.initial['quantity'],
            form.add_prefix('save_for_later'): True,
        }
        response = self.post(reverse('basket:summary'), params=data)

        self.assertRedirects(response, reverse('basket:summary'))
        self.assertFalse(Basket.open.get(pk=basket.pk).lines.exists())
        self.assertEqual(Basket.saved.get(pk=saved_basket.pk).lines.get(
            product=product).quantity, 2)
Exemple #4
0
 def setUp(self):
     super(AddSiteToBasketsBasketsCommandTests, self).setUp()
     self.site = Site.objects.create(domain='acme.fake')
     site = Site.objects.create(domain='test.fake')
     self.associated_baskets = [
         factories.BasketFactory(site=site) for __ in range(0, 2)
     ]
     self.unassociated_baskets = [
         factories.BasketFactory() for __ in range(0, 3)
     ]
Exemple #5
0
    def test_track_completed_discounted_order_with_offer(self):
        """ An event including a discount but no coupon should be sent to Segment"""
        with mock.patch(
                'ecommerce.extensions.checkout.signals.track_segment_event'
        ) as mock_track:
            # Orders may be discounted by a fixed value
            offer_discount = 5
            product = ProductFactory(categories=[],
                                     stockrecords__price_currency='USD')
            _range = factories.RangeFactory(products=[product], )
            site_offer = factories.ConditionalOfferFactory(
                offer_type=ConditionalOffer.SITE,
                benefit=factories.BenefitFactory(range=_range,
                                                 value=offer_discount),
                condition=factories.ConditionFactory(type=Condition.COVERAGE,
                                                     value=1,
                                                     range=_range))

            basket = factories.BasketFactory(owner=self.user, site=self.site)
            basket.add_product(product)
            Applicator().apply_offers(basket, [site_offer])

            order = factories.create_order(basket=basket, user=self.user)
            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)
Exemple #6
0
    def test_get_applicable_lines(self):
        """ Assert that basket lines matching the range's discovery query are selected. """
        basket = factories.BasketFactory(site=self.site, owner=self.user)
        entitlement_product = self.create_entitlement_product()
        course, seat = self.create_course_and_seat()
        no_certificate_product = factories.ProductFactory(
            stockrecords__price_currency='USD')

        basket.add_product(entitlement_product)
        basket.add_product(seat)
        applicable_lines = [(line.product.stockrecords.first().price_excl_tax,
                             line) for line in basket.all_lines()]
        basket.add_product(no_certificate_product)

        self.mock_access_token_response()

        # Verify that the method raises an exception when it fails to reach the Discovery Service
        with self.assertRaises(Exception):
            self.benefit.get_applicable_lines(self.offer, basket)

        self.mock_catalog_query_contains_endpoint(
            course_run_ids=[],
            course_uuids=[entitlement_product.attr.UUID, course.id],
            absent_ids=[],
            query=self.benefit.range.catalog_query,
            discovery_api_url=self.site_configuration.discovery_api_url)

        self.assertEqual(self.benefit.get_applicable_lines(self.offer, basket),
                         applicable_lines)

        # Verify that the API return value is cached
        httpretty.disable()
        self.assertEqual(self.benefit.get_applicable_lines(self.offer, basket),
                         applicable_lines)
    def test_is_single_use_range_condition_satisfied(self):
        """
        Verify that the condition for a single use coupon is only satisfied by single-product baskets.
        """
        valid_user_email = 'valid@{domain}'.format(domain=self.valid_sub_domain)
        basket = factories.BasketFactory(site=self.site, owner=factories.UserFactory(email=valid_user_email))
        product1 = self.create_entitlement_product()
        product2 = self.create_entitlement_product()

        _range = factories.RangeFactory()
        _range.course_seat_types = ','.join(Range.ALLOWED_SEAT_TYPES)
        _range.catalog_query = 'uuid:*'
        benefit = factories.BenefitFactory(range=_range)
        offer = factories.ConditionalOfferFactory(benefit=benefit)
        offer.set_voucher(
            factories.VoucherFactory(usage='Single-use')
        )
        self.mock_access_token_response()
        self.mock_catalog_query_contains_endpoint(
            course_run_ids=[], course_uuids=[product1.attr.UUID, product2.attr.UUID], absent_ids=[],
            query=benefit.range.catalog_query, discovery_api_url=self.site_configuration.discovery_api_url
        )

        # Verify that each product individually satisfies the condition
        basket.add_product(product1)
        self.assertTrue(offer.is_condition_satisfied(basket))

        basket.flush()
        basket.add_product(product2)
        self.assertTrue(offer.is_condition_satisfied(basket))

        # Verify that the offer cannot be applied to a multi-product basket
        basket.add_product(product1)
        self.assertFalse(offer.is_condition_satisfied(basket))
Exemple #8
0
    def test_deactivate_user(self):
        """ Verify an SDN failure is logged. """
        response = {'description': 'Bad dude.'}
        product1 = factories.ProductFactory(
            stockrecords__partner__short_code='first')
        product2 = factories.ProductFactory(
            stockrecords__partner__short_code='second')
        basket = factories.BasketFactory(owner=self.user,
                                         site=self.site_configuration.site)
        basket.add(product1)
        basket.add(product2)
        self.assertEqual(SDNCheckFailure.objects.count(), 0)
        with mock.patch.object(User,
                               'deactivate_account') as deactivate_account:
            deactivate_account.return_value = True
            self.sdn_validator.deactivate_user(basket, self.name, self.city,
                                               self.country, response)

            self.assertEqual(SDNCheckFailure.objects.count(), 1)
            sdn_object = SDNCheckFailure.objects.first()
            self.assertEqual(sdn_object.full_name, self.name)
            self.assertEqual(sdn_object.city, self.city)
            self.assertEqual(sdn_object.country, self.country)
            self.assertEqual(sdn_object.site, self.site_configuration.site)
            self.assertEqual(sdn_object.sdn_check_response, response)
            self.assertEqual(sdn_object.products.count(), basket.lines.count())
            self.assertIn(product1, sdn_object.products.all())
            self.assertIn(product2, sdn_object.products.all())
Exemple #9
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)
Exemple #10
0
 def setUp(self):
     super(InvoiceManagementCommandTests, self).setUp()
     self.product = factories.ProductFactory(product_class=ProductClass.objects.get(name='Coupon'))
     client = Client.objects.create(username='******')
     self.basket = factories.BasketFactory(owner=client)
     self.basket.add_product(self.product, 1)
     self.order = factories.create_order(basket=self.basket)
Exemple #11
0
    def test_track_completed_discounted_order_with_voucher_with_offer(self):
        with mock.patch(
                'ecommerce.extensions.checkout.signals.track_segment_event'
        ) as mock_track:
            # Orders may be discounted by a fixed value
            fixed_benefit = 5.00
            offer_discount = 6
            product = ProductFactory(categories=[],
                                     stockrecords__price_currency='USD')
            _range = factories.RangeFactory(products=[product], )
            voucher, product = prepare_voucher(_range=_range,
                                               benefit_value=fixed_benefit,
                                               benefit_type=Benefit.FIXED)
            factories.ConditionalOfferFactory(
                offer_type=ConditionalOffer.SITE,
                benefit=factories.BenefitFactory(range=_range,
                                                 value=offer_discount),
                condition=factories.ConditionFactory(type=Condition.COVERAGE,
                                                     value=1,
                                                     range=_range))

            basket = factories.BasketFactory(owner=self.user, site=self.site)
            basket.add_product(product)
            basket.vouchers.add(voucher)
            Applicator().apply(basket, user=basket.owner, request=self.request)

            order = factories.create_order(basket=basket, user=self.user)
            track_completed_order(None, order)
            properties = self._generate_event_properties(order, voucher)
            mock_track.assert_called_once_with(order.site,
                                               order.user,
                                               'Order Completed',
                                               properties,
                                               traits=properties)
Exemple #12
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)
Exemple #13
0
    def test_track_completed_discounted_order_with_voucher(self):
        """ An event including coupon information should be sent to Segment"""
        with mock.patch(
                'ecommerce.extensions.checkout.signals.track_segment_event'
        ) as mock_track:
            # Orders may be discounted by percent
            percent_benefit = 66
            product = ProductFactory(categories=[],
                                     stockrecords__price_currency='USD')
            _range = factories.RangeFactory(products=[product], )
            voucher, product = prepare_voucher(_range=_range,
                                               benefit_value=percent_benefit)

            basket = factories.BasketFactory(owner=self.user, site=self.site)
            basket.add_product(product)
            basket.vouchers.add(voucher)
            Applicator().apply(basket, user=basket.owner, request=self.request)

            order = factories.create_order(basket=basket, user=self.user)
            track_completed_order(None, order)
            properties = self._generate_event_properties(order, voucher)
            mock_track.assert_called_once_with(order.site,
                                               order.user,
                                               'Order Completed',
                                               properties,
                                               traits=properties)
Exemple #14
0
    def test_is_range_condition_satisfied(self):
        """
        Verify that a basket satisfies a condition only when all of its products are in its range's catalog queryset.
        """
        valid_user_email = 'valid@{domain}'.format(
            domain=self.valid_sub_domain)
        basket = factories.BasketFactory(
            site=self.site, owner=UserFactory(email=valid_user_email))
        product = self.create_entitlement_product()
        another_product = self.create_entitlement_product()

        _range = factories.RangeFactory()
        _range.course_seat_types = ','.join(Range.ALLOWED_SEAT_TYPES)
        _range.catalog_query = 'uuid:{course_uuid}'.format(
            course_uuid=product.attr.UUID)
        benefit = factories.BenefitFactory(range=_range)
        offer = factories.ConditionalOfferFactory(benefit=benefit)
        self.mock_access_token_response()
        self.mock_catalog_query_contains_endpoint(
            course_run_ids=[],
            course_uuids=[product.attr.UUID],
            absent_ids=[another_product.attr.UUID],
            query=benefit.range.catalog_query,
            discovery_api_url=self.site_configuration.discovery_api_url)

        basket.add_product(product)
        self.assertTrue(offer.is_condition_satisfied(basket))

        basket.add_product(another_product)
        self.assertFalse(offer.is_condition_satisfied(basket))

        # Verify that API return values are cached
        httpretty.disable()
        self.assertFalse(offer.is_condition_satisfied(basket))
Exemple #15
0
 def setUp(self):
     super(InvoiceCommandTests, self).setUp()
     coupon_pc = factories.ProductClassFactory(name='Coupon')
     self.product = factories.ProductFactory(product_class=coupon_pc)
     self.basket = factories.BasketFactory()
     self.basket.add_product(self.product, 1)
     self.order = factories.create_order(basket=self.basket)
     self.invoice = Invoice.objects.create(order=self.order)
Exemple #16
0
 def apply_voucher(self, user, site, voucher):
     """ Apply the voucher to a basket. """
     basket = factories.BasketFactory(owner=user, site=site)
     product = voucher.offers.first().benefit.range.all_products()[0]
     basket.add_product(product)
     basket.vouchers.add(voucher)
     Applicator().apply(basket, self.user)
     return basket
 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()
    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)
Exemple #19
0
 def create_basket_with_product(self):
     """
     creates a basket for testing.
     """
     product = self.course.create_or_update_seat('verified', True, 100)
     basket = factories.BasketFactory(owner=self.user, site=self.site)
     basket.add_product(product, 1)
     basket.freeze()
     return basket
Exemple #20
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)
Exemple #21
0
        def worker():
            order_number = threading.current_thread().name

            basket = factories.BasketFactory()
            basket.add_product(product)
            place_order(creator,
                        basket=basket,
                        order_number=order_number,
                        user=user)
Exemple #22
0
    def test_for_empty_price_excl_tax(self):
        basket = factories.BasketFactory()
        product_class = factories.ProductClassFactory(track_stock=False)
        product = factories.ProductFactory(product_class=product_class, stockrecords=[])
        factories.StockRecordFactory.build(price_excl_tax=None, product=product)

        data = {'quantity': 1}
        form = forms.AddToBasketForm(basket=basket, product=product, data=data)
        self.assertFalse(form.is_valid())
        self.assertEqual(form.errors['__all__'][0], 'unavailable')
Exemple #23
0
    def test_overflow_shipping_cost_scenario_handled_correctly(self):
        basket = factories.BasketFactory()
        product_attribute_value = factories.ProductAttributeValueFactory(
            value_float=2.5)
        basket.add_product(product_attribute_value.product)

        self.standard.bands.create(upper_limit=1, charge=D('1.00'))
        self.standard.bands.create(upper_limit=2, charge=D('2.00'))
        charge = self.standard.calculate(basket)

        self.assertEqual(D('1.00') + D('2.00'), charge.excl_tax)
Exemple #24
0
 def setUp(self):
     super(EnterpriseDiscountMixinTests, self).setUp()
     course = CourseFactory(id='edX/DemoX/Demo_Course',
                            name='Demo Course',
                            partner=self.partner)
     user = UserFactory()
     basket = factories.BasketFactory(owner=user, site=self.site)
     basket.add_product(
         course.create_or_update_seat('test-certificate-type', False, 100,
                                      None), 1)
     self.order = create_order(number=1, basket=basket, user=user)
Exemple #25
0
    def test_track_completed_coupon_order(self):
        """ Make sure we do not send GA events for Coupon orders """
        with mock.patch('ecommerce.extensions.checkout.signals.track_segment_event') as mock_track:

            coupon = self.create_coupon()
            basket = factories.BasketFactory(owner=self.user, site=self.site)
            basket.add_product(coupon)

            order = factories.create_order(basket=basket, user=self.user)
            track_completed_order(None, order)
            assert not mock_track.called
Exemple #26
0
    def test_simple_shipping_cost_scenario_handled_correctly(self):
        basket = factories.BasketFactory()
        product_attribute_value = factories.ProductAttributeValueFactory(
            value_float=2.5)
        basket.add_product(product_attribute_value.product)

        expected_charge = D('3.00')
        self.standard.bands.create(upper_limit=3, charge=expected_charge)
        charge = self.standard.calculate(basket)

        self.assertEqual(expected_charge, charge.excl_tax)
Exemple #27
0
    def test_cannot_add_a_product_without_price(self):
        basket = factories.BasketFactory()
        product = factories.create_product(price=None)

        data = {'quantity': 1}
        form = forms.AddToBasketForm(basket=basket, product=product, data=data)
        self.assertFalse(form.is_valid())
        self.assertEqual(
            form.errors['__all__'][0],
            'This product cannot be added to the basket because a price '
            'could not be determined for it.',
        )
        def worker():
            order_number = threading.current_thread().name

            basket = factories.BasketFactory()
            basket.add_product(product)
            surcharges = SurchargeApplicator().get_applicable_surcharges(
                basket)

            place_order(creator,
                        surcharges=surcharges,
                        basket=basket,
                        order_number=order_number,
                        user=user)
Exemple #29
0
    def prepare_basket(self, price, bundle=False):
        """ Helper function that creates a basket and adds a product with set price to it. """
        basket = factories.BasketFactory(owner=self.user, site=self.site)
        self.course_run.create_or_update_seat('verified', True, Decimal(price))
        basket.add_product(self.course_run.seat_products[0])
        self.assertEqual(basket.lines.count(), 1)
        self.assertEqual(basket.total_incl_tax, Decimal(price))

        if bundle:
            BasketAttribute.objects.update_or_create(
                basket=basket,
                attribute_type=BasketAttributeType.objects.get(name='bundle_identifier'),
                value_text=self.bundle_attribute_value
            )
Exemple #30
0
 def setUp(self):
     super(DonationsFromCheckoutTestFulfillmentModuleTest, self).setUp()
     donation_class = ProductClass.objects.get(
         name=DONATIONS_FROM_CHECKOUT_TESTS_PRODUCT_TYPE_NAME,
         track_stock=False)
     donation = factories.create_product(product_class=donation_class,
                                         title='Test product')
     user = factories.UserFactory()
     basket = factories.BasketFactory(owner=user, site=self.site)
     factories.create_stockrecord(donation,
                                  num_in_stock=2,
                                  price_excl_tax=10)
     basket.add_product(donation, 1)
     self.order = create_order(number=1, basket=basket, user=user)