def get_package_product(): """ :rtype: shuup.core.models.Product """ shop = get_default_shop() supplier = get_default_supplier() return create_package_product("PackageParent", shop=shop, supplier=supplier)
def test_package_edit_view(admin_user, rf, supplier_enabled): shop = get_default_shop() supplier = get_supplier(SimpleSupplierModule.identifier, shop=shop, stock_managed=True) supplier.enabled = supplier_enabled supplier.save() package = create_package_product(printable_gibberish(), shop, supplier) request = apply_all_middleware(rf.get("/"), user=admin_user) response = ProductPackageView.as_view()(request=request, pk=package.pk) product_ids = [] for shop_product in ShopProduct.objects.filter( suppliers=supplier, product__mode=ProductMode.NORMAL): supplier.adjust_stock(product_id=shop_product.product_id, delta=shop_product.product_id) product_ids.append(shop_product.product_id) assert response.status_code == 200 response.render() content = response.content.decode("utf-8") for product_id in product_ids: is_inside = ("Logical count: %s" % product_id) in content assert is_inside == supplier_enabled
def test_order_creator_with_package_product(rf, admin_user): 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 shop = get_default_shop() supplier = get_simple_supplier() package_product = create_package_product("Package-Product-Test", shop=shop, supplier=supplier, children=2) shop_product = package_product.get_shop_instance(shop) quantity_map = package_product.get_package_child_to_quantity_map() product_1, product_2 = quantity_map.keys() product_1.stock_behavior = StockBehavior.STOCKED product_1.save() product_2.stock_behavior = StockBehavior.STOCKED product_2.save() assert quantity_map[product_1] == 1 assert quantity_map[product_2] == 2 supplier.adjust_stock(product_1.pk, 1) supplier.adjust_stock(product_2.pk, 2) assert supplier.get_stock_status(product_1.pk).logical_count == 1 assert supplier.get_stock_status(product_2.pk).logical_count == 2 creator = OrderCreator() # There should be no exception when creating order with only package product source = seed_source(admin_user) source.add_line( type=OrderLineType.PRODUCT, product=package_product, supplier=supplier, quantity=1, base_unit_price=source.create_price(10), ) order = creator.create_order(source) # However, there should not be enough stock for both package and child products source = seed_source(admin_user) source.add_line( type=OrderLineType.PRODUCT, product=package_product, supplier=supplier, quantity=1, base_unit_price=source.create_price(10), ) source.add_line( type=OrderLineType.PRODUCT, product=product_1, supplier=supplier, quantity=1, base_unit_price=source.create_price(10), ) # And a validation error should be raised with pytest.raises(ValidationError): order = creator.create_order(source)
def test_product_package(admin_user): shop1 = get_default_shop() supplier1 = create_simple_supplier("supplier1") product4 = create_package_product("product4", shop=shop1, supplier=supplier1) request = get_request("/api/shuup/front/shop_products/", admin_user) response = FrontShopProductViewSet.as_view({"get": "list"})(request) response.render() products_data = json.loads(response.content.decode("utf-8")) products = sorted(products_data, key=lambda p: p["id"]) assert products[0]["product_id"] == product4.id assert products[0]["is_orderable"] is True assert len(products[0]["package_content"]) == product4.get_all_package_children().count()
def test_modify_order_with_package_product(admin_user): package_children = 4 package = create_package_product("parent", get_default_shop(), get_default_supplier(), 100, package_children) order, source = get_order_and_source(admin_user, package) source.add_line( type=OrderLineType.OTHER, quantity=1, base_unit_price=source.create_price(10), require_verification=True, ) modifier = OrderModifier() modifier.update_order_from_source(source, order) assert order.lines.products().count() == 1 + package_children # parent + children assert order.lines.other().count() == 2 # one added here + one from original order
def test_basket_whit_package_products(rf): with override_settings(**CORE_BASKET_SETTINGS): shop = factories.get_default_shop() user = factories.create_random_user() supplier = factories.get_default_supplier() request = apply_request_middleware(rf.get("/"), user=user, shop=shop) basket_class = cached_load("SHUUP_BASKET_CLASS_SPEC") basket = basket_class(request, "basket", shop=shop) assert basket.shop == shop supplier.stock_managed = True supplier.save() package_product = factories.create_package_product("product", shop, supplier, default_price=10, children=4) product_stock = supplier.get_stock_status(package_product.id) stock = product_stock.physical_count supplier.adjust_stock(package_product.id, -(stock - 6)) product_stock = supplier.get_stock_status(package_product.id) for index, child_product in enumerate( list(package_product.get_package_child_to_quantity_map().keys( )), 1): child_product_stock = supplier.get_stock_status(child_product.id) stock = child_product_stock.physical_count supplier.adjust_stock(child_product.id, -(stock - 10 * index)) child_product_stock = supplier.get_stock_status(child_product.id) basket.add_product(supplier, shop, package_product, 2, force_new_line=True) basket.add_product(supplier, shop, package_product, 2, force_new_line=True) basket.add_product(supplier, shop, package_product, 2, force_new_line=True) basket.uncache() assert len(basket.get_unorderable_lines()) == 0
def get_unstocked_package_product_and_stocked_child(shop, supplier, child_logical_quantity=1): package_product = create_package_product("Package-Product-Test", shop=shop, supplier=supplier, children=1) quantity_map = package_product.get_package_child_to_quantity_map() assert len(quantity_map.keys()) == 1 child_product = list(quantity_map.keys())[0] assert quantity_map[child_product] == 1 supplier.adjust_stock(child_product.id, child_logical_quantity) stock_status = supplier.get_stock_status(child_product.id) assert stock_status.logical_count == child_logical_quantity return package_product, child_product
def test_package_edit_view(admin_user, rf, supplier_enabled): shop = get_default_shop() supplier = get_supplier(SimpleSupplierModule.identifier, shop=shop, stock_managed=True) supplier.enabled = supplier_enabled supplier.save() package = create_package_product(printable_gibberish(), shop, supplier) request = apply_all_middleware(rf.get("/"), user=admin_user) response = ProductPackageView.as_view()(request=request, pk=package.pk) product_ids = [] for shop_product in ShopProduct.objects.filter(suppliers=supplier, product__mode=ProductMode.NORMAL): supplier.adjust_stock(product_id=shop_product.product_id, delta=shop_product.product_id) product_ids.append(shop_product.product_id) assert response.status_code == 200 response.render() content = response.content.decode("utf-8") for product_id in product_ids: is_inside = ("Logical count: %s" % product_id) in content assert is_inside == supplier_enabled
def test_get_products(admin_user): shop1 = get_default_shop() person1 = create_random_person() person1.user = admin_user person1.save() person2 = create_random_person() person2.save() client = _get_client(admin_user) client.customer = person1 client.shop = shop1 # list all orderable products request = get_request("/api/shuup/front/products/", admin_user, shop1, person1) response = FrontProductViewSet.as_view({"get": "list"})(request) response.render() assert response.status_code == status.HTTP_200_OK products_data = json.loads(response.content.decode("utf-8")) assert len(products_data) == 0 shop2 = Shop.objects.create() supplier1 = create_simple_supplier("supplier1") supplier2 = create_simple_supplier("supplier2") # create 2 products for shop2 product1 = create_product("product1", shop=shop2, supplier=supplier1) product2 = create_product("product2", shop=shop2, supplier=supplier2) # add images for products 1 and 2 add_product_image(product1) add_product_image(product2) # list all orderable products - None, since the 2 just created are for shop2 request = get_request("/api/shuup/front/products/", admin_user, shop1, person1) response = FrontProductViewSet.as_view({"get": "list"})(request) response.render() products_data = json.loads(response.content.decode("utf-8")) assert len(products_data) == 0 # create the product for shop1 but set it as not visible product3 = create_product("product3", shop=shop1, supplier=supplier1) shop1_product3 = ShopProduct.objects.get(shop=shop1, product=product3) shop1_product3.visibility = ShopProductVisibility.NOT_VISIBLE shop1_product3.save() # list all orderable products - No one yet request = get_request("/api/shuup/front/products/", admin_user, shop1, person1) response = FrontProductViewSet.as_view({"get": "list"})(request) response.render() products_data = json.loads(response.content.decode("utf-8")) assert len(products_data) == 0 # now product3 becomes visible shop1_product3.visibility = ShopProductVisibility.ALWAYS_VISIBLE shop1_product3.save() request = get_request("/api/shuup/front/products/", admin_user, shop1, person1) response = FrontProductViewSet.as_view({"get": "list"})(request) response.render() products_data = json.loads(response.content.decode("utf-8")) assert len(products_data) == 1 assert products_data[0]["shop_products"][0]["orderable"] is True # product should be visible only for some groups group = create_random_contact_group() group.members.add(person2) product3.visibility = ProductVisibility.VISIBLE_TO_GROUPS product3.save() shop1_product3.visibility_limit = ProductVisibility.VISIBLE_TO_GROUPS shop1_product3.visibility_groups.add(group) shop1_product3.save() request = get_request("/api/shuup/front/products/", admin_user, shop1, person1) response = FrontProductViewSet.as_view({"get": "list"})(request) response.render() products_data = json.loads(response.content.decode("utf-8")) assert len(products_data) == 0 # visible for person2 which is in the same group request = get_request("/api/shuup/front/products/", admin_user, shop1, person2) response = FrontProductViewSet.as_view({"get": "list"})(request) response.render() products_data = json.loads(response.content.decode("utf-8")) assert len(products_data) == 1 # product1 and product2 are visible in shop2 request = get_request("/api/shuup/front/products/", admin_user, shop2, person1) response = FrontProductViewSet.as_view({"get": "list"})(request) response.render() products_data = json.loads(response.content.decode("utf-8")) products = sorted(products_data, key=lambda p: p["id"]) assert products[0]["id"] == product1.id assert products[0]["shop_products"][0]["orderable"] is True assert products[1]["id"] == product2.id assert products[1]["shop_products"][0]["orderable"] is True # check for medias assert products[0]["primary_image"]["file"] == request.build_absolute_uri(product1.primary_image.url) assert products[0]["media"][0]["file"] == request.build_absolute_uri(product1.media.first().url) assert products[0]["media"][1]["file"] == request.build_absolute_uri(product1.media.all()[1].url) assert products[1]["primary_image"]["file"] == request.build_absolute_uri(product2.primary_image.url) assert products[1]["media"][0]["file"] == request.build_absolute_uri(product2.media.first().url) assert products[1]["media"][1]["file"] == request.build_absolute_uri(product2.media.all()[1].url) # ordering by -id request = get_request("/api/shuup/front/products/?ordering=-id", admin_user, shop2, person1) response = FrontProductViewSet.as_view({"get": "list"})(request) response.render() products_data = json.loads(response.content.decode("utf-8")) assert products_data[0]["id"] == product2.id assert products_data[0]["shop_products"][0]["orderable"] is True assert products_data[1]["id"] == product1.id assert products_data[1]["shop_products"][0]["orderable"] is True # add categories to products category1 = Category.objects.create(parent=None, identifier="category1", name="category1") shop2_product1 = ShopProduct.objects.get(shop=shop2, product=product1) shop2_product1.primary_category = category1 shop2_product1.categories.add(category1) shop2_product1.save() category2 = Category.objects.create(parent=None, identifier="category2", name="category2") shop2_product2 = ShopProduct.objects.get(shop=shop2, product=product2) shop2_product2.primary_category = category2 shop2_product2.categories.add(category2) shop2_product2.save() # fetch by category1 request = get_request("/api/shuup/front/products/?category=%d" % category1.id, admin_user, shop2, person1) response = FrontProductViewSet.as_view({"get": "list"})(request) response.render() products_data = json.loads(response.content.decode("utf-8")) assert len(products_data) == 1 assert products_data[0]["id"] == product1.id # fetch by category2 request = get_request("/api/shuup/front/products/?category=%d" % category2.id, admin_user, shop2, person1) response = FrontProductViewSet.as_view({"get": "list"})(request) response.render() products_data = json.loads(response.content.decode("utf-8")) assert len(products_data) == 1 assert products_data[0]["id"] == product2.id # create a package product product4 = create_package_product("product4", shop=shop1, supplier=supplier1) # make product3 orderable again product3.visibility = ProductVisibility.VISIBLE_TO_ALL product3.save() shop1_product3.visibility_limit = ProductVisibility.VISIBLE_TO_ALL shop1_product3.visibility_groups.all().delete() shop1_product3.save() # product3 and product4 are visible in shop1 request = get_request("/api/shuup/front/products/", admin_user, shop1, person1) response = FrontProductViewSet.as_view({"get": "list"})(request) response.render() products_data = json.loads(response.content.decode("utf-8")) products = sorted(products_data, key=lambda p: p["id"]) assert products[0]["id"] == product3.id assert products[0]["shop_products"][0]["orderable"] is True assert products[1]["id"] == product4.id assert products[1]["shop_products"][0]["orderable"] is True # change the shop of the first child product to make the package not orderable sp = product4.get_all_package_children()[0].shop_products.first() sp.shop = shop2 sp.save() # product3 is orderable and product4 doesn't request = get_request("/api/shuup/front/products/", admin_user, shop1, person1) response = FrontProductViewSet.as_view({"get": "list"})(request) response.render() products_data = json.loads(response.content.decode("utf-8")) products = sorted(products_data, key=lambda p: p["id"]) assert products[0]["id"] == product3.id assert products[0]["shop_products"][0]["orderable"] is True assert products[1]["id"] == product4.id assert products[1]["shop_products"][0]["orderable"] is False # assign cross sell of product1 and product2 ProductCrossSell.objects.create(product1=product1, product2=product2, type=ProductCrossSellType.RECOMMENDED) ProductCrossSell.objects.create(product1=product1, product2=product2, type=ProductCrossSellType.RELATED) ProductCrossSell.objects.create(product1=product1, product2=product2, type=ProductCrossSellType.COMPUTED) ProductCrossSell.objects.create(product1=product1, product2=product2, type=ProductCrossSellType.BOUGHT_WITH) # product1 must have cross shell of product2 request = get_request("/api/shuup/front/products/", admin_user, shop2, person1) response = FrontProductViewSet.as_view({"get": "list"})(request) response.render() products_data = json.loads(response.content.decode("utf-8")) products = sorted(products_data, key=lambda p: p["id"]) assert products[0]["id"] == product1.id assert products[0]["cross_sell"]["recommended"] == [product2.id] assert products[0]["cross_sell"]["related"] == [product2.id] assert products[0]["cross_sell"]["computed"] == [product2.id] assert products[0]["cross_sell"]["bought_with"] == [product2.id] assert products[1]["id"] == product2.id assert products[1]["cross_sell"]["recommended"] == [] assert products[1]["cross_sell"]["related"] == [] assert products[1]["cross_sell"]["computed"] == [] assert products[1]["cross_sell"]["bought_with"] == []
def test_get_products(admin_user): shop1 = get_default_shop() person1 = create_random_person() person1.user = admin_user person1.save() person2 = create_random_person() person2.save() client = _get_client(admin_user) client.customer = person1 client.shop = shop1 # list all orderable products request = get_request("/api/shuup/front/products/", admin_user, shop1, person1) response = FrontProductViewSet.as_view({"get": "list"})(request) response.render() assert response.status_code == status.HTTP_200_OK products_data = json.loads(response.content.decode("utf-8")) assert len(products_data) == 0 shop2 = Shop.objects.create() supplier1 = create_simple_supplier("supplier1") supplier2 = create_simple_supplier("supplier2") # create 2 products for shop2 product1 = create_product("product1", shop=shop2, supplier=supplier1) product2 = create_product("product2", shop=shop2, supplier=supplier2) # add images for products 1 and 2 add_product_image(product1) add_product_image(product2) # list all orderable products - None, since the 2 just created are for shop2 request = get_request("/api/shuup/front/products/", admin_user, shop1, person1) response = FrontProductViewSet.as_view({"get": "list"})(request) response.render() products_data = json.loads(response.content.decode("utf-8")) assert len(products_data) == 0 # create the product for shop1 but set it as not visible product3 = create_product("product3", shop=shop1, supplier=supplier1) shop1_product3 = ShopProduct.objects.get(shop=shop1, product=product3) shop1_product3.visibility = ShopProductVisibility.NOT_VISIBLE shop1_product3.save() # list all orderable products - No one yet request = get_request("/api/shuup/front/products/", admin_user, shop1, person1) response = FrontProductViewSet.as_view({"get": "list"})(request) response.render() products_data = json.loads(response.content.decode("utf-8")) assert len(products_data) == 0 # now product3 becomes visible shop1_product3.visibility = ShopProductVisibility.ALWAYS_VISIBLE shop1_product3.save() request = get_request("/api/shuup/front/products/", admin_user, shop1, person1) response = FrontProductViewSet.as_view({"get": "list"})(request) response.render() products_data = json.loads(response.content.decode("utf-8")) assert len(products_data) == 1 assert products_data[0]["shop_products"][0]["orderable"] is True # product should be visible only for some groups group = create_random_contact_group() group.members.add(person2) product3.visibility = ProductVisibility.VISIBLE_TO_GROUPS product3.save() shop1_product3.visibility_limit = ProductVisibility.VISIBLE_TO_GROUPS shop1_product3.visibility_groups.add(group) shop1_product3.save() request = get_request("/api/shuup/front/products/", admin_user, shop1, person1) response = FrontProductViewSet.as_view({"get": "list"})(request) response.render() products_data = json.loads(response.content.decode("utf-8")) assert len(products_data) == 0 # visible for person2 which is in the same group request = get_request("/api/shuup/front/products/", admin_user, shop1, person2) response = FrontProductViewSet.as_view({"get": "list"})(request) response.render() products_data = json.loads(response.content.decode("utf-8")) assert len(products_data) == 1 # product1 and product2 are visible in shop2 request = get_request("/api/shuup/front/products/", admin_user, shop2, person1) response = FrontProductViewSet.as_view({"get": "list"})(request) response.render() products_data = json.loads(response.content.decode("utf-8")) products = sorted(products_data, key=lambda p: p["id"]) assert products[0]["id"] == product1.id assert products[0]["shop_products"][0]["orderable"] is True assert products[1]["id"] == product2.id assert products[1]["shop_products"][0]["orderable"] is True # check for medias assert products[0]["primary_image"]["file"] == request.build_absolute_uri( product1.primary_image.url) assert products[0]["media"][0]["file"] == request.build_absolute_uri( product1.media.first().url) assert products[0]["media"][1]["file"] == request.build_absolute_uri( product1.media.all()[1].url) assert products[1]["primary_image"]["file"] == request.build_absolute_uri( product2.primary_image.url) assert products[1]["media"][0]["file"] == request.build_absolute_uri( product2.media.first().url) assert products[1]["media"][1]["file"] == request.build_absolute_uri( product2.media.all()[1].url) # ordering by -id request = get_request("/api/shuup/front/products/?ordering=-id", admin_user, shop2, person1) response = FrontProductViewSet.as_view({"get": "list"})(request) response.render() products_data = json.loads(response.content.decode("utf-8")) assert products_data[0]["id"] == product2.id assert products_data[0]["shop_products"][0]["orderable"] is True assert products_data[1]["id"] == product1.id assert products_data[1]["shop_products"][0]["orderable"] is True # add categories to products category1 = Category.objects.create(parent=None, identifier="category1", name="category1") shop2_product1 = ShopProduct.objects.get(shop=shop2, product=product1) shop2_product1.primary_category = category1 shop2_product1.categories.add(category1) shop2_product1.save() category2 = Category.objects.create(parent=None, identifier="category2", name="category2") shop2_product2 = ShopProduct.objects.get(shop=shop2, product=product2) shop2_product2.primary_category = category2 shop2_product2.categories.add(category2) shop2_product2.save() # fetch by category1 request = get_request( "/api/shuup/front/products/?category=%d" % category1.id, admin_user, shop2, person1) response = FrontProductViewSet.as_view({"get": "list"})(request) response.render() products_data = json.loads(response.content.decode("utf-8")) assert len(products_data) == 1 assert products_data[0]["id"] == product1.id # fetch by category2 request = get_request( "/api/shuup/front/products/?category=%d" % category2.id, admin_user, shop2, person1) response = FrontProductViewSet.as_view({"get": "list"})(request) response.render() products_data = json.loads(response.content.decode("utf-8")) assert len(products_data) == 1 assert products_data[0]["id"] == product2.id # create a package product product4 = create_package_product("product4", shop=shop1, supplier=supplier1) # make product3 orderable again product3.visibility = ProductVisibility.VISIBLE_TO_ALL product3.save() shop1_product3.visibility_limit = ProductVisibility.VISIBLE_TO_ALL shop1_product3.visibility_groups.all().delete() shop1_product3.save() # product3 and product4 are visible in shop1 request = get_request("/api/shuup/front/products/", admin_user, shop1, person1) response = FrontProductViewSet.as_view({"get": "list"})(request) response.render() products_data = json.loads(response.content.decode("utf-8")) products = sorted(products_data, key=lambda p: p["id"]) assert products[0]["id"] == product3.id assert products[0]["shop_products"][0]["orderable"] is True assert products[1]["id"] == product4.id assert products[1]["shop_products"][0]["orderable"] is True # change the shop of the first child product to make the package not orderable sp = product4.get_all_package_children()[0].shop_products.first() sp.shop = shop2 sp.save() # product3 is orderable and product4 doesn't request = get_request("/api/shuup/front/products/", admin_user, shop1, person1) response = FrontProductViewSet.as_view({"get": "list"})(request) response.render() products_data = json.loads(response.content.decode("utf-8")) products = sorted(products_data, key=lambda p: p["id"]) assert products[0]["id"] == product3.id assert products[0]["shop_products"][0]["orderable"] is True assert products[1]["id"] == product4.id assert products[1]["shop_products"][0]["orderable"] is False # assign cross sell of product1 and product2 ProductCrossSell.objects.create(product1=product1, product2=product2, type=ProductCrossSellType.RECOMMENDED) ProductCrossSell.objects.create(product1=product1, product2=product2, type=ProductCrossSellType.RELATED) ProductCrossSell.objects.create(product1=product1, product2=product2, type=ProductCrossSellType.COMPUTED) ProductCrossSell.objects.create(product1=product1, product2=product2, type=ProductCrossSellType.BOUGHT_WITH) # product1 must have cross shell of product2 request = get_request("/api/shuup/front/products/", admin_user, shop2, person1) response = FrontProductViewSet.as_view({"get": "list"})(request) response.render() products_data = json.loads(response.content.decode("utf-8")) products = sorted(products_data, key=lambda p: p["id"]) assert products[0]["id"] == product1.id assert products[0]["cross_sell"]["recommended"] == [product2.id] assert products[0]["cross_sell"]["related"] == [product2.id] assert products[0]["cross_sell"]["computed"] == [product2.id] assert products[0]["cross_sell"]["bought_with"] == [product2.id] assert products[1]["id"] == product2.id assert products[1]["cross_sell"]["recommended"] == [] assert products[1]["cross_sell"]["related"] == [] assert products[1]["cross_sell"]["computed"] == [] assert products[1]["cross_sell"]["bought_with"] == []