def test_discount_for_multi_group_using_customer(rf, admin_user, price, discount, anonymous_discount): customer = create_customer() anonymous = AnonymousContact() request, shop, _ = initialize_test(rf, True, customer) product = create_product("product", shop=shop, default_price=price) CgpDiscount.objects.create(product=product, group=customer.groups.first(), shop=shop, discount_amount_value=discount) CgpDiscount.objects.create(product=product, group=anonymous.get_default_group(), shop=shop, discount_amount_value=anonymous_discount) # discount for customer request, shop, _ = initialize_test(rf, True, customer) price_info = product.get_price_info(request) assert price_info.price == shop.create_price(max(price - discount, 0)) # discount for anonymous request, shop, _ = initialize_test(rf, True, anonymous) price_info = product.get_price_info(request) assert price_info.price == shop.create_price( max(price - anonymous_discount, 0))
def test_intra_request_user_changing(rf, regular_user): get_default_shop() # Create a shop mw = WshopFrontMiddleware() request = apply_request_middleware(rf.get("/"), user=regular_user) mw.process_request(request) assert request.person == get_person_contact(regular_user) logout(request) assert request.user == AnonymousUser() assert request.person == AnonymousContact() assert request.customer == AnonymousContact()
def orderer(self): if self._orderer or isinstance(self._orderer, AnonymousContact): return self._orderer orderer_id = self._get_value_from_data("orderer_id") if orderer_id: if orderer_id == ANONYMOUS_ID: return AnonymousContact() return PersonContact.objects.get(pk=orderer_id) return getattr(self.request, "person", AnonymousContact())
def customer(self): if self._customer or isinstance(self._customer, AnonymousContact): return self._customer customer_id = self._get_value_from_data("customer_id") if customer_id: if customer_id == ANONYMOUS_ID: return AnonymousContact() return Contact.objects.get(pk=customer_id) return getattr(self.request, "customer", AnonymousContact())
def test_set_from_admin_to_anonymous(admin_user, rf): """ Set anonymous to the basket customer """ with override_settings(**CORE_BASKET_SETTINGS): request = apply_request_middleware(rf.get("/"), user=admin_user) basket = get_basket(request, "basket") basket.customer = get_person_contact(admin_user) assert basket_commands.handle_set_customer(request, basket, AnonymousContact())["ok"] is True assert basket.customer == AnonymousContact() assert basket.orderer == AnonymousContact() assert basket.creator == admin_user
def test_with_inactive_contact(rf, regular_user, admin_user): get_default_shop() # Create a shop # Get or create contact for regular user contact = get_person_contact(regular_user) assert contact.is_active contact.is_active = False contact.save() request = apply_request_middleware(rf.get("/"), user=regular_user) mw = WshopFrontMiddleware() mw.process_request(request) assert request.user == AnonymousUser() assert request.person == AnonymousContact() assert request.customer == AnonymousContact()
def _get_template_engine_and_context(product_sku='6.0745'): engine = django.template.engines['jinja2'] assert isinstance(engine, django_jinja.backend.Jinja2) shop = get_default_shop() shop.currency = 'USD' shop.prices_include_tax = False shop.save() request = RequestFactory().get('/') request.shop = shop request.customer = AnonymousContact() request.person = request.customer PriceDisplayOptions(include_taxes=False).set_for_request(request) tax = get_default_tax() create_default_tax_rule(tax) tax_class = get_default_tax_class() order, order_line = _get_order_and_order_line(request) product = create_product(sku=product_sku, shop=shop, tax_class=tax_class) context = { 'request': request, 'prod': product, # TODO: Test also with variant products 'sline': _get_source_line(request), 'bline': _get_basket_line(request), 'oline': order_line, 'order': order } return (engine, context)
def get_price_info_mock(context, product, quantity=1): if context.customer.get_default_group() == AnonymousContact( ).get_default_group(): price = context.shop.create_price(anonymous_price) else: price = context.shop.create_price(customer_price) return PriceInfo(quantity * price, quantity * price, quantity)
def test_filter_parameter_contact_groups(): customer_price = 10.3 anonymous_price = 14.6 def get_price_info_mock(context, product, quantity=1): if context.customer.get_default_group() == AnonymousContact( ).get_default_group(): price = context.shop.create_price(anonymous_price) else: price = context.shop.create_price(customer_price) return PriceInfo(quantity * price, quantity * price, quantity) with patch.object(DummyPricingModule, 'get_price_info', side_effect=get_price_info_mock): (engine, context) = _get_template_engine_and_context(product_sku="123") # test with anonymous context['request'].customer = AnonymousContact() context['request'].person = context['request'].customer result = engine.from_string("{{ prod|price(quantity=2) }}") assert result.render(context) == "$%0.2f" % (anonymous_price * 2) # Get fresh content. I guess the prices shouldn't change between request. (engine, context) = _get_template_engine_and_context(product_sku="1234") # test with customer context['request'].customer = create_random_person() context['request'].person = context['request'].customer result = engine.from_string("{{ prod|price(quantity=2) }}") assert result.render(context) == "$%0.2f" % (customer_price * 2)
def test_complex_order_tax(include_taxes): tax = get_default_tax() quantities = [44, 23, 65] product = get_default_product() supplier = get_default_supplier() shop = get_default_shop() shop.prices_include_tax = include_taxes shop.save() order = create_empty_order(shop=shop) order.full_clean() order.save() pricing_context = get_pricing_module().get_context_from_data( shop=shop, customer=order.customer or AnonymousContact(), ) total_price = Decimal("0") price = Decimal("50") for quantity in quantities: total_price += quantity * price add_product_to_order(order, supplier, product, quantity, price, tax.rate, pricing_context) order.cache_prices() order.save() currency = "EUR" summary = order.get_tax_summary()[0] assert summary.tax_rate == tax.rate assert summary.based_on == Money(total_price, currency) assert summary.tax_amount == Money(total_price * tax.rate, currency) assert summary.taxful == summary.based_on + summary.tax_amount assert order.get_total_tax_amount() == Money(total_price * tax.rate, currency)
def test_get_company_contact(regular_user): person_contact = get_person_contact(regular_user) assert person_contact != AnonymousContact() assert not get_company_contact(regular_user) company_contact = create_random_company() company_contact.members.add(person_contact) assert get_company_contact(regular_user) == company_contact
def test_set_from_anonymous_to_customer_auth(rf): """ Set some random customer to the basket when authenticated """ with override_settings(**CORE_BASKET_SETTINGS): user = factories.create_random_user() request = apply_request_middleware(rf.get("/"), user=user) basket = get_basket(request, "basket") basket.customer = AnonymousContact() # can not set the customer for something different as the request customer with pytest.raises(ValidationError) as exc: basket_commands.handle_set_customer(request, basket, factories.create_random_person()) assert exc.value.code == "no_permission" assert basket.customer == AnonymousContact() assert basket_commands.handle_set_customer(request, basket, get_person_contact(user))["ok"] is True assert basket.customer == get_person_contact(user)
def test_anonymous_set_company_customer(rf): """ Set a company as the basket customer """ with override_settings(**CORE_BASKET_SETTINGS): user = factories.create_random_user() request = apply_request_middleware(rf.get("/"), user=user) basket = get_basket(request, "basket") basket.customer = AnonymousContact() person = factories.create_random_person() company = factories.create_random_company() company.members.add(person) with pytest.raises(ValidationError) as exc: basket_commands.handle_set_customer(request, basket, company, person) assert exc.value.code == "not_company_member" assert basket.customer == AnonymousContact()
def test_omniscience(admin_user, regular_user): assert not get_person_contact(admin_user).is_all_seeing configuration.set(None, get_all_seeing_key(admin_user), True) assert get_person_contact(admin_user).is_all_seeing assert not get_person_contact(regular_user).is_all_seeing assert not get_person_contact(None).is_all_seeing assert not get_person_contact(AnonymousUser()).is_all_seeing assert not AnonymousContact().is_all_seeing configuration.set(None, get_all_seeing_key(admin_user), False)
def test_discount_for_anonymous(rf, admin_user, price, discount): request, shop, group = initialize_test(rf, True, AnonymousContact()) product = create_product("product", shop=shop, default_price=price) CgpDiscount.objects.create(product=product, group=group, shop=shop, discount_amount_value=discount) price_info = product.get_price_info(request) assert price_info.price == shop.create_price(max(price - discount, 0))
def test_anonymous_customers_default_group(rf): request, shop, group = initialize_test(rf, True) discount_value = 49 product = create_product("random-52", shop=shop, default_price=121) request.customer = AnonymousContact() CgpPrice.objects.create(product=product, group=request.customer.get_default_group(), shop=shop, price_value=discount_value) price_info = product.get_price_info(request) assert price_info.price == shop.create_price(discount_value)
def test_set_from_anonymous_to_customer_not_auth(rf): """ Set some customer to the basket when not authenticated """ with override_settings(**CORE_BASKET_SETTINGS): request = apply_request_middleware(rf.get("/")) basket = get_basket(request, "basket") basket.customer = AnonymousContact() customer = factories.create_random_person() assert basket_commands.handle_set_customer(request, basket, customer)["ok"] is True assert basket.customer == customer
def test_product_orderability(): anon_contact = AnonymousContact() shop_product = get_default_shop_product() supplier = get_default_supplier() with modify(shop_product, visibility_limit=ProductVisibility.VISIBLE_TO_ALL, orderable=True): shop_product.raise_if_not_orderable(supplier=supplier, customer=anon_contact, quantity=1) assert shop_product.is_orderable(supplier=supplier, customer=anon_contact, quantity=1) with modify(shop_product, visibility_limit=ProductVisibility.VISIBLE_TO_LOGGED_IN, orderable=True): with pytest.raises(ProductNotOrderableProblem): shop_product.raise_if_not_orderable(supplier=supplier, customer=anon_contact, quantity=1) assert not shop_product.is_orderable(supplier=supplier, customer=anon_contact, quantity=1)
def test_sample_data_wizard_pane(rf, admin_user, settings): settings.WSHOP_SETUP_WIZARD_PANE_SPEC = [ "wshop.admin.modules.sample_data.views.SampleObjectsWizardPane" ] shop = get_default_shop() get_default_tax_class() data = { 'pane_id': 'sample', 'sample-business_segment': 'default', 'sample-categories': True, 'sample-products': True, 'sample-carousel': True } request = apply_request_middleware(rf.post("/", data=data), user=admin_user) response = WizardView.as_view()(request) assert response.status_code == 200 assert Product.objects.count() == len( BUSINESS_SEGMENTS["default"]["products"]) anon_contact = AnonymousContact() supplier = get_default_supplier() # check for the injected plugin using the carousel assert Carousel.objects.count() == 1 carousel = Carousel.objects.first() assert Slide.objects.count() == len( BUSINESS_SEGMENTS["default"]["carousel"]["slides"]) svc = SavedViewConfig.objects.first() assert svc.view_name == "IndexView" layout = svc.get_layout_data("front_content") assert layout['rows'][0]['cells'][0]['config']['carousel'] == carousel.pk assert layout['rows'][0]['cells'][0]['plugin'] == CarouselPlugin.identifier for product in Product.objects.all(): # all products must be orderable and have images assert product.get_shop_instance(shop).is_orderable( supplier=supplier, customer=anon_contact, quantity=1) assert product.primary_image is not None assert Category.objects.count() == len( BUSINESS_SEGMENTS["default"]["categories"]) request = apply_request_middleware(rf.get("/"), user=admin_user) response = WizardView.as_view()(request) assert response.status_code == 302 assert response["Location"] == reverse("wshop_admin:dashboard")
def test_product_query(visibility, show_in_list, show_in_search, admin_user, regular_user): shop = get_default_shop() product = create_product("test-sku", shop=shop) shop_product = product.get_shop_instance(shop) anon_contact = AnonymousContact() regular_contact = get_person_contact(regular_user) admin_contact = get_person_contact(admin_user) shop_product.visibility = visibility shop_product.save() assert shop_product.visibility_limit == ProductVisibility.VISIBLE_TO_ALL # Anonymous contact should be the same as no contact assert (product in Product.objects.listed(shop=shop)) == show_in_list assert (product in Product.objects.searchable(shop=shop)) == show_in_search assert (product in Product.objects.listed(shop=shop, customer=anon_contact)) == show_in_list assert (product in Product.objects.searchable( shop=shop, customer=anon_contact)) == show_in_search # Admin should see all non-deleted results configuration.set(None, get_all_seeing_key(admin_contact), True) assert product in Product.objects.listed(shop=shop, customer=admin_contact) assert product in Product.objects.searchable(shop=shop, customer=admin_contact) # Anonymous contact shouldn't see products with logged in visibility limit shop_product.visibility_limit = ProductVisibility.VISIBLE_TO_LOGGED_IN shop_product.save() assert product not in Product.objects.listed(shop=shop, customer=anon_contact) assert product not in Product.objects.searchable(shop=shop, customer=anon_contact) # Reset visibility limit shop_product.visibility_limit = ProductVisibility.VISIBLE_TO_ALL shop_product.save() # No one should see deleted products product.soft_delete() assert product not in Product.objects.listed(shop=shop) assert product not in Product.objects.searchable(shop=shop) assert product not in Product.objects.listed(shop=shop, customer=admin_contact) assert product not in Product.objects.searchable(shop=shop, customer=admin_contact) configuration.set(None, get_all_seeing_key(admin_contact), False)
def get_price_info(shop, customer, product, quantity): """ Get price info of given product for given context parameters. :type shop: wshop.core.models.Shop :type customer: wshop.core.models.Contact :type product: wshop.core.models.Product :type quantity: numbers.Number """ pricing_mod = get_pricing_module() pricing_ctx = pricing_mod.get_context_from_data( shop=shop, customer=(customer or AnonymousContact()), ) return product.get_price_info(pricing_ctx, quantity=quantity)
def test_copy_order_to_basket_for_anonymous(): with override_settings(**REQUIRED_SETTINGS): set_configuration() shop = factories.get_default_shop() order = _create_order(shop, AnonymousContact()) basket = factories.get_basket(shop) assert basket.customer is None client = APIClient() assert basket.customer is None _fill_new_basket_from_order(client, basket, None, order) # do it again, basket should clear first then read items _fill_new_basket_from_order(client, basket, None, order)
def test_customer_is_anonymous(rf): request, shop, group = initialize_test(rf, True) price = shop.create_price product = create_product("random-1", shop=shop, default_price=100) CgpPrice.objects.create(product=product, group=group, shop=shop, price_value=50) request.customer = AnonymousContact() price_info = product.get_price_info(request) assert price_info.price == price(100)
def _handle_set_customer(self, request, basket, customer, orderer=None): try: cmd_kwargs = { "request": request, "basket": basket, "customer": customer or AnonymousContact(), "orderer": orderer } self._handle_cmd(self.request, "set_customer", cmd_kwargs) except ValidationError as exc: if exc.code in [ "no_permission", "orderer_not_company_member", "not_company_member" ]: raise exceptions.PermissionDenied(exc.message) else: raise exceptions.ValidationError(exc.message)
def _get_order(prices_include_tax=False, include_basket_campaign=False, include_catalog_campaign=False): shop = get_shop(prices_include_tax=prices_include_tax) supplier = get_simple_supplier() if include_basket_campaign: _add_basket_campaign(shop) if include_catalog_campaign: _add_catalog_campaign(shop) _add_taxes() source = BasketishOrderSource(shop) source.status = get_initial_order_status() ctx = get_pricing_module().get_context_from_data(shop, AnonymousContact()) for product_data in _get_product_data(): quantity = product_data.pop("quantity") product = create_product( sku=product_data.pop("sku"), shop=shop, supplier=supplier, stock_behavior=StockBehavior.STOCKED, tax_class=get_default_tax_class(), **product_data) shop_product = product.get_shop_instance(shop) shop_product.categories.add(get_default_category()) shop_product.save() supplier.adjust_stock(product.id, INITIAL_PRODUCT_QUANTITY) pi = product.get_price_info(ctx) source.add_line( type=OrderLineType.PRODUCT, product=product, supplier=supplier, quantity=quantity, base_unit_price=pi.base_unit_price, discount_amount=pi.discount_amount ) oc = OrderCreator() order = oc.create_order(source) order.create_payment(Money("1", "EUR")) assert not order.has_refunds() assert order.can_create_refund() assert order.shipping_status == ShippingStatus.NOT_SHIPPED assert order.payment_status == PaymentStatus.PARTIALLY_PAID return order
def test_anonymous_contact(): a1 = AnonymousContact() a2 = AnonymousContact() # Basic Contact stuff assert a1.is_anonymous, "AnonymousContact is anonymous" assert not a1.is_all_seeing, "AnonymousContact is not all seeing" assert a1.identifier is None assert a1.is_active, "AnonymousContact is active" assert a1.language == '' assert a1.marketing_permission assert a1.phone == '' assert a1.www == '' assert a1.timezone is None assert a1.prefix == '' assert a1.name == '', "AnonymousContact has no name" assert a1.suffix == '' assert a1.name_ext == '' assert a1.email == '', "AnonymousContact has no email" assert str(a1) == '' # Primary key / id assert a1.pk is None assert a1.id is None # AnonymousContact instance evaluates as false assert not a1 # All AnonymousContacts should be equal assert a1 == a2 # Cannot be saved with pytest.raises(NotImplementedError): a1.save() # Cannot be deleted with pytest.raises(NotImplementedError): a1.delete() assert isinstance(a1.groups, QuerySet) assert a1.groups.first( ).identifier == AnonymousContact.default_contact_group_identifier assert a1.groups.count() == 1 assert len(a1.groups.all()) == 1
def test_pricing_module_is_active(): """ Make sure that our custom pricing module is active. """ shop = Shop(currency='USD', prices_include_tax=False) customer = AnonymousContact() product = Product(sku='6.0745') pricing_mod = get_pricing_module() pricing_ctx = pricing_mod.get_context_from_data(shop, customer) pi = product.get_price_info(pricing_ctx, quantity=2) price = shop.create_price assert pi.price == price('12.149') assert pi.base_price == price('48.596') assert pi.quantity == 2 assert pi.discounted_unit_price == price('6.0745') assert pi.base_unit_price == price('24.298') assert pi.discount_rate == Decimal('0.75')
def test_category_visibility(admin_user, regular_user): visible_public_category = Category.objects.create(status=CategoryStatus.VISIBLE, visibility=CategoryVisibility.VISIBLE_TO_ALL, identifier="visible_public", name=DEFAULT_NAME) hidden_public_category = Category.objects.create(status=CategoryStatus.INVISIBLE, visibility=CategoryVisibility.VISIBLE_TO_ALL, identifier="hidden_public", name=DEFAULT_NAME) deleted_public_category = Category.objects.create(status=CategoryStatus.DELETED, visibility=CategoryVisibility.VISIBLE_TO_ALL, identifier="deleted_public", name=DEFAULT_NAME) logged_in_category = Category.objects.create(status=CategoryStatus.VISIBLE, visibility=CategoryVisibility.VISIBLE_TO_LOGGED_IN, identifier="visible_logged_in", name=DEFAULT_NAME) group_visible_category = Category.objects.create(status=CategoryStatus.VISIBLE, visibility=CategoryVisibility.VISIBLE_TO_GROUPS, identifier="visible_groups", name=DEFAULT_NAME) assert visible_public_category.name == DEFAULT_NAME assert str(visible_public_category) == DEFAULT_NAME anon_contact = AnonymousContact() regular_contact = get_person_contact(regular_user) admin_contact = get_person_contact(admin_user) configuration.set(None, get_all_seeing_key(admin_contact), True) for (customer, category, expect) in [ (anon_contact, visible_public_category, True), (anon_contact, hidden_public_category, False), (anon_contact, deleted_public_category, False), (anon_contact, logged_in_category, False), (anon_contact, group_visible_category, False), (regular_contact, visible_public_category, True), (regular_contact, hidden_public_category, False), (regular_contact, deleted_public_category, False), (regular_contact, logged_in_category, True), (regular_contact, group_visible_category, False), (admin_contact, visible_public_category, True), (admin_contact, hidden_public_category, True), (admin_contact, deleted_public_category, False), (admin_contact, logged_in_category, True), (admin_contact, group_visible_category, True), ]: result = Category.objects.all_visible(customer=customer).filter(pk=category.pk).exists() assert result == expect, "Queryset visibility of %s for %s as expected" % (category.identifier, customer) assert category.is_visible(customer) == expect, "Direct visibility of %s for %s as expected" % (category.identifier, customer) assert not Category.objects.all_except_deleted().filter(pk=deleted_public_category.pk).exists(), "Deleted category does not show up in 'all_except_deleted'" configuration.set(None, get_all_seeing_key(admin_contact), False)
def test_simple_supplier_out_of_stock(rf, anonymous): supplier = get_simple_supplier() shop = get_default_shop() product = create_product("simple-test-product", shop, supplier, stock_behavior=StockBehavior.STOCKED) if anonymous: customer = AnonymousContact() else: customer = create_random_person() ss = supplier.get_stock_status(product.pk) assert ss.product == product assert ss.logical_count == 0 num = random.randint(100, 500) supplier.adjust_stock(product.pk, +num) assert supplier.get_stock_status(product.pk).logical_count == num shop_product = product.get_shop_instance(shop) assert shop_product.is_orderable(supplier, customer, 1) # Create order order = create_order_with_product(product, supplier, num, 3, shop=shop) order.get_product_ids_and_quantities() pss = supplier.get_stock_status(product.pk) assert pss.logical_count == 0 assert pss.physical_count == num assert not shop_product.is_orderable(supplier, customer, 1) # Create shipment shipment = order.create_shipment_of_all_products(supplier) assert isinstance(shipment, Shipment) pss = supplier.get_stock_status(product.pk) assert pss.logical_count == 0 assert pss.physical_count == 0 assert not shop_product.is_orderable(supplier, customer, 1)
def test_anonymous_contact_vs_person(regular_user): anon = AnonymousContact() person = get_person_contact(regular_user) assert anon != person assert person != anon