def test_add_invalid_product(): shop = get_default_shop() supplier = get_default_supplier() request = get_request_with_basket() basket = request.basket # cannot add simple/variable variation parent to the basket parent = create_product("parent", shop=shop, supplier=supplier) child = create_product("child", shop=shop, supplier=supplier) child.link_to_parent(parent) parent.refresh_from_db() assert parent.mode == ProductMode.SIMPLE_VARIATION_PARENT with pytest.raises(ValidationError) as excinfo: basket_commands.handle_add(request, basket, product_id=parent.pk, quantity=2) assert excinfo.value.code == 'invalid_product' child.unlink_from_parent() child.link_to_parent(parent, variables={"size": "XXL"}) parent.refresh_from_db() assert parent.mode == ProductMode.VARIABLE_VARIATION_PARENT with pytest.raises(ValidationError) as excinfo: basket_commands.handle_add(request, basket, product_id=parent.pk, quantity=3) assert excinfo.value.code == 'invalid_product'
def create(self, request, *args, **kwargs): basket = self.get_basket() serializer = self.get_serializer_class()(data=request.data) serializer.is_valid(raise_exception=True) try: product = serializer.validated_data['product'] product.get_shop_instance(shop=self.request.shop) except ObjectDoesNotExist: return ValidationError({ 'code': 'product_not_available', 'error': [_('The requested product does not exists or is not available in the current store')] }) try: handle_add(PricingContext(self.request.shop, basket.customer), basket, product.id, serializer.validated_data['quantity']) basket.save() except ShopMismatchBasketCompatibilityError: raise ValidationError({ 'code': 'shop_mismatch', 'error': _('The requested belongs to another shop') }) # trigger reload, otherwise we have a cached version new_basket = self.get_basket() return Response(APIBasketSerializer(new_basket, context={'request': self.request}).data)
def test_parallel_baskets(rf): request = get_request_with_basket() shop = get_default_shop() customer = create_random_person() request = rf.get("/") request.shop = shop apply_request_middleware(request) request.customer = customer basket_one = get_basket(request, basket_name="basket_one") basket_two = get_basket(request, basket_name="basket_two") product_one = get_default_product() product_two = get_default_product() product_two.sku = "derpy-hooves" sales_unit = SalesUnit.objects.create(identifier="test-sales-partial", decimals=2, name="Partial unit") product_two.sales_unit = sales_unit # Set the sales unit for the product product_two.save() basket_commands.handle_add(request, basket_one, product_id=product_one.pk, quantity=1) basket_commands.handle_add(request, basket_two, product_id=product_two.pk, quantity=3.5) assert basket_one.product_count == 1 assert basket_two.product_count == 3.5
def test_add_and_remove_and_clear(): product = create_product('fractionable', fractional=True) complete_product(product) supplier = get_default_supplier() request = get_request_with_basket() basket = request.basket with pytest.raises(ValidationError): # Ordering antimatter is not supported basket_commands.handle_add(request, basket, product_id=product.pk, quantity=-3) # These will get merged into one line... basket_commands.handle_add(request, basket, **{"product_id": product.pk, "quantity": 1, "supplier_id": supplier.pk}) basket_commands.handle_add(request, basket, **{"product_id": product.pk, "quantity": 2}) # Fractions should also be supported basket_commands.handle_add(request, basket, **{"product_id": product.pk, "quantity": 0.75}) # ... so there will be 3 products but one line assert basket.product_count == 3.75 lines = basket.get_lines() assert len(lines) == 1 # ... and deleting that line will clear the basket... basket_commands.handle_del(request, basket, lines[0].line_id) assert basket.product_count == 0 # ... and adding another product will create a new line... basket_commands.handle_add(request, basket, product_id=product.pk, quantity=1) assert basket.product_count == 1 # ... that can be cleared. basket_commands.handle_clear(request, basket) assert basket.product_count == 0
def test_basket_update_errors(): request = get_request_with_basket() basket = request.basket product = get_default_product() basket_commands.handle_add(request, basket, product_id=product.pk, quantity=1) # Hide product and now updating quantity should give errors shop_product = product.get_shop_instance(request.shop) shop_product.suppliers.clear() line_id = basket.get_lines()[0].line_id basket_commands.handle_update(request, basket, **{"q_%s" % line_id: "2"}) error_messages = messages.get_messages(request) # One warning is added to messages assert len(error_messages) == 1 assert any("not supplied" in msg.message for msg in error_messages) shop_product.visible = False shop_product.save() basket_commands.handle_update(request, basket, **{"q_%s" % line_id: "2"}) error_messages = messages.get_messages(request) # Two warnings is added to messages assert len(error_messages) == 3 assert any("not visible" in msg.message for msg in error_messages) assert all("[" not in msg.message for msg in error_messages)
def test_basket_partial_quantity_update(): request = get_request_with_basket() basket = request.basket product = get_default_product() sales_unit = SalesUnit.objects.create(identifier="test-sales-partial", decimals=2, name="Partial unit") product.sales_unit = sales_unit # Set the sales unit for the product product.save() basket_commands.handle_add(request, basket, product_id=product.pk, quantity=1.5) assert basket.product_count == 1.5 line_id = basket.get_lines()[0].line_id basket_commands.handle_update(request, basket, **{"q_%s" % line_id: "1.5"}) assert basket.product_count == 1.5 basket_commands.handle_update(request, basket, **{"q_%s" % line_id: "3.5"}) assert basket.product_count == 3.5 basket_commands.handle_update(request, basket, **{"q_%s" % line_id: "3.0"}) assert basket.product_count == 3.0 basket_commands.handle_update(request, basket, **{"q_%s" % line_id: "4"}) assert basket.product_count == 4 basket_commands.handle_update(request, basket, **{"delete_%s" % line_id: "1"}) assert basket.product_count == 0
def test_add_invalid_product(): shop = get_default_shop() supplier = get_default_supplier() request = get_request_with_basket() basket = request.basket # cannot add simple/variable variation parent to the basket parent = create_product("parent", shop=shop, supplier=supplier) child = create_product("child", shop=shop, supplier=supplier) child.link_to_parent(parent) parent.refresh_from_db() assert parent.mode == ProductMode.SIMPLE_VARIATION_PARENT with pytest.raises(ValidationError) as excinfo: basket_commands.handle_add(request, basket, product_id=parent.pk, quantity=2) assert excinfo.value.code == "invalid_product" child.unlink_from_parent() child.link_to_parent(parent, variables={"size": "XXL"}) parent.refresh_from_db() assert parent.mode == ProductMode.VARIABLE_VARIATION_PARENT with pytest.raises(ValidationError) as excinfo: basket_commands.handle_add(request, basket, product_id=parent.pk, quantity=3) assert excinfo.value.code == "invalid_product"
def test_basket_update(): request = get_request_with_basket() basket = request.basket product = get_default_product() basket_commands.handle_add(request, basket, product_id=product.pk, quantity=1) assert basket.product_count == 1 line_id = basket.get_lines()[0].line_id basket_commands.handle_update(request, basket, **{"q_%s" % line_id: "2"}) assert basket.product_count == 2 basket_commands.handle_update(request, basket, **{"delete_%s" % line_id: "1"}) assert basket.product_count == 0
def test_basket_update(): request = get_request_with_basket() basket = request.basket product = create_product('fractionable', fractional=True) complete_product(product) basket_commands.handle_add(request, basket, product_id=product.pk, quantity=1.75) assert basket.product_count == 1.75 line_id = basket.get_lines()[0].line_id basket_commands.handle_update(request, basket, **{"q_%s" % line_id: "2"}) assert basket.product_count == 2 basket_commands.handle_update(request, basket, **{"delete_%s" % line_id: "1"}) assert basket.product_count == 0
def test_add_and_invalid_product(): shop = get_default_shop() product = create_product('fractionable', fractional=True) complete_product(product) supplier = get_default_supplier() request = get_request_with_basket() basket = request.basket # remove the shop product product.get_shop_instance(shop).delete() with pytest.raises(ValidationError) as exc: basket_commands.handle_add(request, basket, **{ "product_id": product.pk, "quantity": 1, "supplier_id": supplier.pk }) assert "Product not available in this shop" in exc.value.message
def test_basket_update_with_package_product(): if "shuup.simple_supplier" not in settings.INSTALLED_APPS: pytest.skip("Need shuup.simple_supplier in INSTALLED_APPS") from shuup_tests.simple_supplier.utils import get_simple_supplier request = get_request_with_basket() basket = request.basket shop = get_default_shop() supplier = get_simple_supplier() parent, child = get_unstocked_package_product_and_stocked_child(shop, supplier, child_logical_quantity=2) # There should be enough stock for 1 parent and 1 extra child, each of quantity 1 basket_commands.handle_add(request, basket, product_id=parent.pk, quantity=1) assert basket.product_count == 1 basket_commands.handle_add(request, basket, product_id=child.pk, quantity=1) assert basket.product_count == 2 assert not messages.get_messages(request) basket_lines = {line.product.id: line for line in basket.get_lines()} package_line = basket_lines[parent.id] extra_child_line = basket_lines[child.id] # Trying to increase package product line quantity should fail, with error message basket_commands.handle_update(request, basket, **{"q_%s" % package_line.line_id: "2"}) assert basket.product_count == 2 assert len(messages.get_messages(request)) == 1 # So should increasing the extra child line quantity basket_commands.handle_update(request, basket, **{"q_%s" % extra_child_line.line_id: "2"}) assert basket.product_count == 2 assert len(messages.get_messages(request)) == 2 # However, if we delete the parent line, we can increase the extra child basket_commands.handle_update(request, basket, **{"delete_%s" % package_line.line_id: "1"}) assert basket.product_count == 1 basket_commands.handle_update(request, basket, **{"q_%s" % extra_child_line.line_id: "2"}) assert basket.product_count == 2 # Resetting to original basket contents basket_commands.handle_update(request, basket, **{"q_%s" % extra_child_line.line_id: "1"}) basket_commands.handle_add(request, basket, product_id=parent.pk, quantity=1) basket_lines = {line.product.id: line for line in basket.get_lines()} package_line = basket_lines[parent.id] # Package line will have a new ID assert basket.product_count == 2 # Like above, delete the child line and we can now increase the parent basket_commands.handle_update(request, basket, **{"delete_%s" % extra_child_line.line_id: "1"}) assert basket.product_count == 1 basket_commands.handle_update(request, basket, **{"q_%s" % package_line.line_id: "2"}) assert basket.product_count == 2
def test_basket_update_with_package_product(): if "shuup.simple_supplier" not in settings.INSTALLED_APPS: pytest.skip("Need shuup.simple_supplier in INSTALLED_APPS") from shuup_tests.simple_supplier.utils import get_simple_supplier request = get_request_with_basket() basket = request.basket shop = get_default_shop() supplier = get_simple_supplier() parent, child = get_unstocked_package_product_and_stocked_child(shop, supplier, child_logical_quantity=2) # There should be enough stock for 1 parent and 1 extra child, each of quantity 1 basket_commands.handle_add(request, basket, product_id=parent.pk, quantity=1) assert basket.product_count == 1 basket_commands.handle_add(request, basket, product_id=child.pk, quantity=1) assert basket.product_count == 2 assert not messages.get_messages(request) basket_lines = {line.product.id: line for line in basket.get_lines()} package_line = basket_lines[parent.id] extra_child_line = basket_lines[child.id] # Trying to increase package product line quantity should fail, with error message basket_commands.handle_update(request, basket, **{"q_%s" % package_line.line_id: "2"}) assert basket.product_count == 2 assert len(messages.get_messages(request)) == 1 # So should increasing the extra child line quantity basket_commands.handle_update(request, basket, **{"q_%s" % extra_child_line.line_id: "2"}) assert basket.product_count == 2 assert len(messages.get_messages(request)) == 2 # However, if we delete the parent line, we can increase the extra child basket_commands.handle_update(request, basket, **{"delete_%s" % package_line.line_id: "1"}) assert basket.product_count == 1 basket_commands.handle_update(request, basket, **{"q_%s" % extra_child_line.line_id: "2"}) assert basket.product_count == 2 # Resetting to original basket contents basket_commands.handle_update(request, basket, **{"q_%s" % extra_child_line.line_id: "1"}) basket_commands.handle_add(request, basket, product_id=parent.pk, quantity=1) basket_lines = {line.product.id: line for line in basket.get_lines()} package_line = basket_lines[parent.id] # Package line will have a new ID assert basket.product_count == 2 # Like above, delete the child line and we can now increase the parent basket_commands.handle_update(request, basket, **{"delete_%s" % extra_child_line.line_id: "1"}) assert basket.product_count == 1 basket_commands.handle_update(request, basket, **{"q_%s" % package_line.line_id: "2"}) assert basket.product_count == 2 # Clear basket basket_commands.handle_clear(request, basket) assert basket.product_count == 0 # Remove the Shop Product from the child child.get_shop_instance(shop).delete() # Child not available for this shop with pytest.raises(ProductNotOrderableProblem): basket_commands.handle_add(request, basket, product_id=parent.pk, quantity=1) # use the update methods object to check orderability errors update_methods = BasketUpdateMethods(request, basket) errors = update_methods._get_orderability_errors(parent, supplier, 1) assert len(errors) == 2 assert any(["product_not_available_in_shop" in error.code for error in errors])
def test_basket_update_with_package_product(): if "shuup.simple_supplier" not in settings.INSTALLED_APPS: pytest.skip("Need shuup.simple_supplier in INSTALLED_APPS") from shuup_tests.simple_supplier.utils import get_simple_supplier request = get_request_with_basket() basket = request.basket shop = get_default_shop() supplier = get_simple_supplier() parent, child = get_unstocked_package_product_and_stocked_child( shop, supplier, child_logical_quantity=2) # There should be enough stock for 1 parent and 1 extra child, each of quantity 1 basket_commands.handle_add(request, basket, product_id=parent.pk, quantity=1) assert basket.product_count == 1 basket_commands.handle_add(request, basket, product_id=child.pk, quantity=1) assert basket.product_count == 2 assert not messages.get_messages(request) basket_lines = {line.product.id: line for line in basket.get_lines()} package_line = basket_lines[parent.id] extra_child_line = basket_lines[child.id] # Trying to increase package product line quantity should fail, with error message basket_commands.handle_update(request, basket, **{"q_%s" % package_line.line_id: "2"}) assert basket.product_count == 2 assert len(messages.get_messages(request)) == 1 # So should increasing the extra child line quantity basket_commands.handle_update(request, basket, **{"q_%s" % extra_child_line.line_id: "2"}) assert basket.product_count == 2 assert len(messages.get_messages(request)) == 2 # However, if we delete the parent line, we can increase the extra child basket_commands.handle_update(request, basket, **{"delete_%s" % package_line.line_id: "1"}) assert basket.product_count == 1 basket_commands.handle_update(request, basket, **{"q_%s" % extra_child_line.line_id: "2"}) assert basket.product_count == 2 # Resetting to original basket contents basket_commands.handle_update(request, basket, **{"q_%s" % extra_child_line.line_id: "1"}) basket_commands.handle_add(request, basket, product_id=parent.pk, quantity=1) basket_lines = {line.product.id: line for line in basket.get_lines()} package_line = basket_lines[parent.id] # Package line will have a new ID assert basket.product_count == 2 # Like above, delete the child line and we can now increase the parent basket_commands.handle_update( request, basket, **{"delete_%s" % extra_child_line.line_id: "1"}) assert basket.product_count == 1 basket_commands.handle_update(request, basket, **{"q_%s" % package_line.line_id: "2"}) assert basket.product_count == 2 # Clear basket basket_commands.handle_clear(request, basket) assert basket.product_count == 0 # Remove the Shop Product from the child child.get_shop_instance(shop).delete() # Child not available for this shop with pytest.raises(ProductNotOrderableProblem): basket_commands.handle_add(request, basket, product_id=parent.pk, quantity=1) # use the update methods object to check orderability errors update_methods = BasketUpdateMethods(request, basket) errors = update_methods._get_orderability_errors(parent, supplier, 1) assert len(errors) == 2 assert any( ["product_not_available_in_shop" in error.code for error in errors])