def test_get_visible_products_filter():
    context = get_jinja_context()
    shop = get_default_shop()
    supplier = get_default_supplier()

    product_1 = create_product(
        "test-sku-1",
        supplier=supplier,
        shop=shop,
    )
    product_2 = create_product(
        "test-sku-2",
        supplier=supplier,
        shop=shop,
    )
    filter_dict = {"id": product_1.id}
    product_list = general.get_visible_products(context,
                                                n_products=2,
                                                filter_dict=filter_dict)
    assert product_1 in product_list
    assert product_2 not in product_list

    # Test also with orderable_only False
    product_list = general.get_visible_products(context,
                                                n_products=2,
                                                filter_dict=filter_dict,
                                                orderable_only=False)
    assert product_1 in product_list
    assert product_2 not in product_list
Example #2
0
def test_basket_shipping_error(rf):
    StoredBasket.objects.all().delete()
    shop = get_default_shop()
    supplier = get_default_supplier()
    shipped_product = create_product(
        printable_gibberish(), shop=shop, supplier=supplier, default_price=50,
        shipping_mode=ShippingMode.SHIPPED
    )
    unshipped_product = create_product(
        printable_gibberish(), shop=shop, supplier=supplier, default_price=50,
        shipping_mode=ShippingMode.NOT_SHIPPED
    )

    request = rf.get("/")
    request.session = {}
    request.shop = shop
    apply_request_middleware(request)
    basket = get_basket(request)

    # With a shipped product but no shipping methods, we oughta get an error
    basket.add_product(supplier=supplier, shop=shop, product=shipped_product, quantity=1)
    assert any(ve.code == "no_common_shipping" for ve in basket.get_validation_errors())
    basket.clear_all()

    # But with an unshipped product, we should not
    basket.add_product(supplier=supplier, shop=shop, product=unshipped_product, quantity=1)
    assert not any(ve.code == "no_common_shipping" for ve in basket.get_validation_errors())
Example #3
0
def test_simple_variation():
    shop = get_default_shop()
    parent = create_product("SimpleVarParent")
    children = [create_product("SimpleVarChild-%d" % x) for x in range(10)]
    for child in children:
        child.link_to_parent(parent)
        sp = ShopProduct.objects.create(shop=shop, product=child, listed=True)
        assert child.is_variation_child()
        assert not sp.is_list_visible()  # Variation children are not list visible

    assert parent.mode == ProductMode.SIMPLE_VARIATION_PARENT
    assert not list(get_all_available_combinations(parent))  # Simple variations can't have these.

    # Validation tests

    dummy = create_product("InvalidSimpleVarChild")

    with pytest.raises(ValueError):
        dummy.link_to_parent(parent, variables={"size": "XL"})

    with pytest.raises(ValueError):
        parent.link_to_parent(dummy)

    with pytest.raises(ValueError):
        dummy.link_to_parent(children[0])

    # Unlinkage

    for child in children:
        child.unlink_from_parent()
        assert not child.is_variation_child()
        assert child.mode == ProductMode.NORMAL

    assert not parent.is_variation_parent()
    assert parent.variation_children.count() == 0
Example #4
0
def test_package():
    shop = get_default_shop()
    supplier = get_default_supplier()
    package_product = create_product("PackageParent", shop=shop, supplier=supplier)
    assert not package_product.get_package_child_to_quantity_map()
    children = [create_product("PackageChild-%d" % x, shop=shop, supplier=supplier) for x in range(4)]
    package_def = {child: 1 + i for (i, child) in enumerate(children)}
    package_product.make_package(package_def)
    assert package_product.mode == ProductMode.PACKAGE_PARENT
    package_product.save()
    sp = package_product.get_shop_instance(shop)
    assert not list(sp.get_orderability_errors(supplier=supplier, quantity=1, customer=AnonymousContact()))

    with pytest.raises(ValueError):  # Test re-packaging fails
        package_product.make_package(package_def)

    # Check that OrderCreator can deal with packages

    source = BasketishOrderSource()
    source.lines.append(SourceLine(
        type=OrderLineType.PRODUCT,
        product=package_product,
        supplier=get_default_supplier(),
        quantity=10,
        unit_price=TaxlessPrice(10),
    ))

    source.shop = get_default_shop()
    source.status = get_initial_order_status()
    creator = OrderCreator(request=None)
    order = creator.create_order(source)
    pids_to_quantities = order.get_product_ids_and_quantities()
    for child, quantity in six.iteritems(package_def):
        assert pids_to_quantities[child.pk] == 10 * quantity
Example #5
0
def test_basket_campaign_case2(rf):
    request, shop, group = initialize_test(rf, False)
    price = shop.create_price

    basket = get_basket(request)
    supplier = get_default_supplier()
    # create a basket rule that requires at least value of 200
    rule = BasketTotalAmountCondition.objects.create(value="200")

    single_product_price = "50"
    discount_amount_value = "10"

    unique_shipping_method = get_shipping_method(shop, price=50)

    for x in range(3):
        product = create_product(printable_gibberish(),
                                 shop=shop,
                                 supplier=supplier,
                                 default_price=single_product_price)
        basket.add_product(supplier=supplier,
                           shop=shop,
                           product=product,
                           quantity=1)

    assert basket.product_count == 3

    campaign = BasketCampaign.objects.create(
        shop=shop,
        public_name="test",
        name="test",
        discount_amount_value=discount_amount_value,
        active=True)
    campaign.conditions.add(rule)
    campaign.save()

    assert len(basket.get_final_lines()) == 3
    assert basket.total_price == price(
        single_product_price) * basket.product_count

    # check that shipping method affects campaign
    basket.shipping_method = unique_shipping_method
    basket.save()
    basket.uncache()
    assert len(basket.get_final_lines()
               ) == 4  # Shipping should not affect the rule being triggered

    line_types = [l.type for l in basket.get_final_lines()]
    assert OrderLineType.DISCOUNT not in line_types

    product = create_product(printable_gibberish(),
                             shop=shop,
                             supplier=supplier,
                             default_price=single_product_price)
    basket.add_product(supplier=supplier,
                       shop=shop,
                       product=product,
                       quantity=1)

    assert len(basket.get_final_lines()) == 6  # Discount included
    assert OrderLineType.DISCOUNT in [l.type for l in basket.get_final_lines()]
Example #6
0
def test_price_infos(rf):
    request, shop, group = initialize_test(rf, True)
    price = shop.create_price

    product_one = create_product("Product_1", shop, default_price=150)
    product_two = create_product("Product_2", shop, default_price=250)

    spp = SimpleProductPrice(product=product_one, shop=shop, group=group, price_value=100)
    spp.save()

    spp = SimpleProductPrice(product=product_two, shop=shop, group=group, price_value=200)
    spp.save()

    product_ids = [product_one.pk, product_two.pk]

    spm = get_pricing_module()
    assert isinstance(spm, SimplePricingModule)
    pricing_context = spm.get_context_from_request(request)
    price_infos = spm.get_price_infos(pricing_context, product_ids)

    assert len(price_infos) == 2
    assert product_one.pk in price_infos
    assert product_two.pk in price_infos

    assert price_infos[product_one.pk].price == price(100)
    assert price_infos[product_two.pk].price == price(200)

    assert price_infos[product_one.pk].base_price == price(100)
    assert price_infos[product_two.pk].base_price == price(200)
Example #7
0
def test_complex_variation():
    request = get_request_with_basket()
    basket = request.basket
    shop = get_default_shop()
    supplier = get_default_supplier()

    parent = create_product("SuperComplexVarParent", shop=shop, supplier=supplier)
    color_var = ProductVariationVariable.objects.create(product=parent, identifier="color")
    size_var = ProductVariationVariable.objects.create(product=parent, identifier="size")

    ProductVariationVariableValue.objects.create(variable=color_var, identifier="yellow")
    ProductVariationVariableValue.objects.create(variable=size_var, identifier="small")

    combinations = list(parent.get_all_available_combinations())
    for combo in combinations:
        child = create_product("xyz-%s" % combo["sku_part"], shop=shop, supplier=supplier)
        child.link_to_parent(parent, combo["variable_to_value"])

    # Elided product should not yield a result
    yellow_color_value = ProductVariationVariableValue.objects.get(variable=color_var, identifier="yellow")
    small_size_value = ProductVariationVariableValue.objects.get(variable=size_var, identifier="small")

    # add to basket yellow + small
    kwargs = {"var_%d" % color_var.pk: yellow_color_value.pk, "var_%d" % size_var.pk: small_size_value.pk}

    basket_commands.handle_add_var(request, basket, 1, **kwargs)
    assert basket.get_product_ids_and_quantities()[child.pk] == 1

    with pytest.raises(ValidationError):
        kwargs = {"var_%d" % color_var.pk: yellow_color_value.pk, "var_%d" % size_var.pk: small_size_value.pk + 1}
        basket_commands.handle_add_var(request, basket, 1, **kwargs)
Example #8
0
def test_multivariable_variation():
    parent = create_product("SuperComplexVarParent")
    color_var = ProductVariationVariable.objects.create(product=parent, identifier="color")
    size_var = ProductVariationVariable.objects.create(product=parent, identifier="size")

    for color in ("yellow", "blue", "brown"):
        ProductVariationVariableValue.objects.create(variable=color_var, identifier=color)

    for size in ("small", "medium", "large", "huge"):
        ProductVariationVariableValue.objects.create(variable=size_var, identifier=size)

    combinations = list(get_all_available_combinations(parent))
    assert len(combinations) == (3 * 4)
    for combo in combinations:
        assert not combo["result_product_pk"]
        # Elide a combination (yellow/small) for testing:
        if combo["variable_to_value"][color_var].identifier == "yellow" and combo["variable_to_value"][size_var].identifier == "small":
            continue
        child = create_product("xyz-%s" % combo["sku_part"])
        child.link_to_parent(parent, combo["variable_to_value"])
    assert parent.mode == ProductMode.VARIABLE_VARIATION_PARENT

    # Elided product should not yield a result
    yellow_color_value = ProductVariationVariableValue.objects.get(variable=color_var, identifier="yellow")
    small_size_value = ProductVariationVariableValue.objects.get(variable=size_var, identifier="small")
    assert not ProductVariationResult.resolve(parent, {color_var: yellow_color_value, size_var: small_size_value})
    # Anything else should
    brown_color_value = ProductVariationVariableValue.objects.get(variable=color_var, identifier="brown")
    result1 = ProductVariationResult.resolve(parent, {color_var: brown_color_value, size_var: small_size_value})
    result2 = ProductVariationResult.resolve(parent, {color_var.pk: brown_color_value.pk, size_var.pk: small_size_value.pk})
    assert result1 and result2
    assert result1.pk == result2.pk

    assert len(get_available_variation_results(parent)) == (3 * 4 - 1)
Example #9
0
def test_form_populate_initial_data(rf, admin_user):
    shop = get_default_shop()
    supplier = get_default_supplier()
    initial_discount_amount = 20
    campaign = BasketCampaign.objects.create(shop=shop)
    BasketDiscountAmount.objects.create(campaign=campaign, discount_amount=initial_discount_amount)

    # Test that correct initial value is returned for non-many-to-many field
    product_amount_initial = 10
    product_amount_condition = BasketTotalProductAmountCondition(product_count=product_amount_initial)
    product_amount_condition.save()
    campaign.conditions.add(product_amount_condition)

    products_count_initial = 5
    for i in range(products_count_initial):
        create_product(printable_gibberish(), shop=shop, supplier=supplier, default_price="20")
    products_initial = Product.objects.all()[:products_count_initial]
    assert len(products_initial) == products_count_initial

    # Test that correct initial value is returned for many-to-many field
    products_in_basket_condition = ProductsInBasketCondition.objects.create()
    products_in_basket_condition.values = products_initial
    products_in_basket_condition.save()
    campaign.conditions.add(products_in_basket_condition)

    assert len(campaign.conditions.all()) == 2
    assert campaign.effects.count() == 1

    request=apply_request_middleware(rf.get("/"), user=admin_user)
    form = BasketCampaignForm(request=request, instance=campaign)
    assert form.fields["basket_product_condition"].initial == product_amount_initial
    assert set(form.fields["basket_products_condition"].initial) == set([p.pk for p in products_initial])
    assert form.fields["discount_amount_effect"].initial == initial_discount_amount
def test_simple_variation():
    shop = get_default_shop()
    parent = create_product("SimpleVarParent")
    children = [create_product("SimpleVarChild-%d" % x) for x in range(10)]
    for child in children:
        child.link_to_parent(parent)
        sp = ShopProduct.objects.create(shop=shop, product=child, listed=True)
        assert child.is_variation_child()
        assert not sp.is_list_visible()  # Variation children are not list visible

    assert parent.mode == ProductMode.SIMPLE_VARIATION_PARENT
    assert not list(parent.get_all_available_combinations())  # Simple variations can't have these.

    # Validation tests

    dummy = create_product("InvalidSimpleVarChild")

    with pytest.raises(ValueError):
        dummy.link_to_parent(parent, variables={"size": "XL"})

    with pytest.raises(ValueError):
        parent.link_to_parent(dummy)

    with pytest.raises(ValueError):
        dummy.link_to_parent(children[0])

    # Unlinkage

    for child in children:
        child.unlink_from_parent()
        assert not child.is_variation_child()
        assert child.mode == ProductMode.NORMAL

    assert not parent.is_variation_parent()
    assert parent.variation_children.count() == 0
def test_variable_variation():
    parent = create_product("ComplexVarParent")
    sizes_and_children = [("%sL" % ("X" * x),
                           create_product("ComplexVarChild-%d" % x))
                          for x in range(4)]
    for size, child in sizes_and_children:
        child.link_to_parent(parent, variables={"size": size})
    assert parent.mode == ProductMode.VARIABLE_VARIATION_PARENT
    assert all(child.is_variation_child()
               for (size, child) in sizes_and_children)

    # Validation tests

    dummy = create_product("InvalidComplexVarChild")

    with pytest.raises(ValueError):
        dummy.link_to_parent(parent)

    with pytest.raises(ValueError):
        parent.link_to_parent(dummy)

    with pytest.raises(ValueError):
        dummy.link_to_parent(sizes_and_children[0][1])

    # Variable tests

    size_attr = parent.variation_variables.get(identifier="size")

    for size, child in sizes_and_children:
        size_val = size_attr.values.get(identifier=size)
        result_product = ProductVariationResult.resolve(
            parent, {size_attr: size_val})
        assert result_product == child
Example #12
0
def get_frontend_order_state(contact, valid_lines=True):
    """
    Get a dict structure mirroring what the frontend JavaScript would submit.
    :type contact: Contact|None
    """
    translation.activate("en")
    shop = get_default_shop()
    tax = Tax.objects.create(code="test_code", rate=decimal.Decimal("0.20"), name="Default")
    tax_class = TaxClass.objects.create(identifier="test_tax_class", name="Default")
    rule = TaxRule.objects.create(tax=tax)
    rule.tax_classes.add(tax_class)
    rule.save()
    product = create_product(
        sku=printable_gibberish(),
        supplier=get_default_supplier(),
        shop=shop
    )
    product.tax_class = tax_class
    product.save()
    if valid_lines:
        lines = [
            {"id": "x", "type": "product", "product": {"id": product.id}, "quantity": "32", "baseUnitPrice": 50},
            {"id": "y", "type": "other", "sku": "hello", "text": "A greeting", "quantity": 1, "unitPrice": "5.5"},
            {"id": "z", "type": "text", "text": "This was an order!", "quantity": 0},
        ]
    else:
        unshopped_product = create_product(sku=printable_gibberish(), supplier=get_default_supplier())
        not_visible_product = create_product(
            sku=printable_gibberish(),
            supplier=get_default_supplier(),
            shop=shop
        )
        not_visible_shop_product = not_visible_product.get_shop_instance(shop)
        not_visible_shop_product.visible = False
        not_visible_shop_product.save()
        lines = [
            {"id": "x", "type": "product"},  # no product?
            {"id": "x", "type": "product", "product": {"id": unshopped_product.id}},  # not in this shop?
            {"id": "y", "type": "product", "product": {"id": -product.id}},  # invalid product?
            {"id": "z", "type": "other", "quantity": 1, "unitPrice": "q"},  # what's that price?
            {"id": "rr", "type": "product", "quantity": 1, "product": {"id": not_visible_product.id}}  # not visible
        ]

    state = {
        "customer": {"id": contact.id if contact else None},
        "lines": lines,
        "methods": {
            "shippingMethod": {"id": get_default_shipping_method().id},
            "paymentMethod": {"id": get_default_payment_method().id},
        },
        "shop": {
            "selected": {
                "id": shop.id,
                "name": shop.name,
                "currency": shop.currency,
                "priceIncludeTaxes": shop.prices_include_tax
            }
        }
    }
    return state
def init_test(request, shop, prices):
    apply_request_middleware(request)
    parent = create_product("parent_product", shop=shop)
    children = [create_product("child-%d" % price, shop=shop, default_price=price) for price in prices]
    for child in children:
        child.link_to_parent(parent)
    return parent
def test_simple_children_formset():
    FormSet = formset_factory(SimpleVariationChildForm,
                              SimpleVariationChildFormSet,
                              extra=5,
                              can_delete=True)
    parent = create_product(printable_gibberish())
    child = create_product(printable_gibberish())

    # No links yet
    formset = FormSet(parent_product=parent)
    assert formset.initial_form_count() == 0  # No children yet

    # Save a link
    data = dict(get_form_data(formset, True), **{"form-0-child": child.pk})
    formset = FormSet(parent_product=parent, data=data)
    formset.save()
    assert parent.variation_children.filter(
        pk=child.pk).exists()  # Got link'd!

    # Remove the link
    formset = FormSet(parent_product=parent)
    assert formset.initial_form_count() == 1  # Got the child here
    data = dict(get_form_data(formset, True), **{"form-0-DELETE": "1"})
    formset = FormSet(parent_product=parent, data=data)
    formset.save()
    assert not parent.variation_children.exists()  # Got unlinked
Example #15
0
def test_price_infos(rf):
    request, shop, group = initialize_test(rf, True)

    product_one = create_product("Product_1", shop, default_price=150)
    product_two = create_product("Product_2", shop, default_price=250)

    spp = SimpleProductPrice(product=product_one,
                             shop=shop,
                             group=group,
                             price=100)
    spp.save()

    spp = SimpleProductPrice(product=product_two,
                             shop=shop,
                             group=group,
                             price=200)
    spp.save()

    product_ids = [product_one.pk, product_two.pk]

    spm = SimplePricingModule()
    pricing_context = spm.get_context_from_request(request)
    price_infos = spm.get_price_infos(pricing_context, product_ids)

    assert len(price_infos) == 2
    assert product_one.pk in price_infos
    assert product_two.pk in price_infos

    assert price_infos[product_one.pk].price == TaxfulPrice(100)
    assert price_infos[product_two.pk].price == TaxfulPrice(200)

    assert price_infos[product_one.pk].base_price == TaxfulPrice(100)
    assert price_infos[product_two.pk].base_price == TaxfulPrice(200)
Example #16
0
def test_form_populate_initial_data(rf, admin_user):
    shop = get_default_shop()
    supplier = get_default_supplier()

    campaign = BasketCampaign(discount_percentage=0.1, shop=shop)
    campaign.save()

    # Test that correct initial value is returned for non-many-to-many field
    product_amount_initial = 10
    product_amount_condition = BasketTotalProductAmountCondition(product_count=product_amount_initial)
    product_amount_condition.save()
    campaign.conditions.add(product_amount_condition)

    products_count_initial = 5
    for i in range(products_count_initial):
        create_product(printable_gibberish(), shop=shop, supplier=supplier, default_price="20")
    products_initial = Product.objects.all()[:products_count_initial]
    assert len(products_initial) == products_count_initial

    # Test that correct initial value is returned for many-to-many field
    products_in_basket_condition = ProductsInBasketCondition.objects.create()
    products_in_basket_condition.values = products_initial
    products_in_basket_condition.save()
    campaign.conditions.add(products_in_basket_condition)

    assert len(campaign.conditions.all()) == 2

    request=apply_request_middleware(rf.get("/"), user=admin_user)
    form = BasketCampaignForm(request=request, instance=campaign)
    assert form.fields["basket_product_condition"].initial == product_amount_initial
    assert set(form.fields["basket_products_condition"].initial) == set([p.pk for p in products_initial])
Example #17
0
def get_frontend_order_state(contact, valid_lines=True):
    """
    Get a dict structure mirroring what the frontend JavaScript would submit.
    :type contact: Contact|None
    """
    translation.activate("en")
    shop = get_default_shop()
    tax = Tax.objects.create(code="test_code", rate=decimal.Decimal("0.20"), name="Default")
    tax_class = TaxClass.objects.create(identifier="test_tax_class", name="Default")
    rule = TaxRule.objects.create(tax=tax)
    rule.tax_classes.add(tax_class)
    rule.save()
    product = create_product(
        sku=printable_gibberish(),
        supplier=get_default_supplier(),
        shop=shop
    )
    product.tax_class = tax_class
    product.save()
    if valid_lines:
        lines = [
            {"id": "x", "type": "product", "product": {"id": product.id}, "quantity": "32", "baseUnitPrice": 50},
            {"id": "y", "type": "other", "sku": "hello", "text": "A greeting", "quantity": 1, "unitPrice": "5.5"},
            {"id": "z", "type": "text", "text": "This was an order!", "quantity": 0},
        ]
    else:
        unshopped_product = create_product(sku=printable_gibberish(), supplier=get_default_supplier())
        not_visible_product = create_product(
            sku=printable_gibberish(),
            supplier=get_default_supplier(),
            shop=shop
        )
        not_visible_shop_product = not_visible_product.get_shop_instance(shop)
        not_visible_shop_product.visible = False
        not_visible_shop_product.save()
        lines = [
            {"id": "x", "type": "product"},  # no product?
            {"id": "x", "type": "product", "product": {"id": unshopped_product.id}},  # not in this shop?
            {"id": "y", "type": "product", "product": {"id": -product.id}},  # invalid product?
            {"id": "z", "type": "other", "quantity": 1, "unitPrice": "q"},  # what's that price?
            {"id": "rr", "type": "product", "quantity": 1, "product": {"id": not_visible_product.id}}  # not visible
        ]

    state = {
        "customer": {"id": contact.id if contact else None},
        "lines": lines,
        "methods": {
            "shippingMethod": {"id": get_default_shipping_method().id},
            "paymentMethod": {"id": get_default_payment_method().id},
        },
        "shop": {
            "selected": {
                "id": shop.id,
                "name": shop.name,
                "currency": shop.currency,
                "priceIncludeTaxes": shop.prices_include_tax
            }
        }
    }
    return state
def test_multivariable_variation():
    parent = create_product("SuperComplexVarParent")
    color_var = ProductVariationVariable.objects.create(product=parent, identifier="color")
    size_var = ProductVariationVariable.objects.create(product=parent, identifier="size")

    for color in ("yellow", "blue", "brown"):
        ProductVariationVariableValue.objects.create(variable=color_var, identifier=color)

    for size in ("small", "medium", "large", "huge"):
        ProductVariationVariableValue.objects.create(variable=size_var, identifier=size)

    combinations = list(parent.get_all_available_combinations())
    assert len(combinations) == (3 * 4)
    for combo in combinations:
        assert not combo["result_product_pk"]
        # Elide a combination (yellow/small) for testing:
        if combo["variable_to_value"][color_var].identifier == "yellow" and combo["variable_to_value"][size_var].identifier == "small":
            continue
        child = create_product("xyz-%s" % combo["sku_part"])
        child.link_to_parent(parent, combo["variable_to_value"])
    assert parent.mode == ProductMode.VARIABLE_VARIATION_PARENT

    # Elided product should not yield a result
    yellow_color_value = ProductVariationVariableValue.objects.get(variable=color_var, identifier="yellow")
    small_size_value = ProductVariationVariableValue.objects.get(variable=size_var, identifier="small")
    assert not ProductVariationResult.resolve(parent, {color_var: yellow_color_value, size_var: small_size_value})
    # Anything else should
    brown_color_value = ProductVariationVariableValue.objects.get(variable=color_var, identifier="brown")
    result1 = ProductVariationResult.resolve(parent, {color_var: brown_color_value, size_var: small_size_value})
    result2 = ProductVariationResult.resolve(parent, {color_var.pk: brown_color_value.pk, size_var.pk: small_size_value.pk})
    assert result1 and result2
    assert result1.pk == result2.pk

    assert len(parent.get_available_variation_results()) == (3 * 4 - 1)
Example #19
0
def test_price_infos(rf):
    request, shop, group = initialize_test(rf, True)
    price = shop.create_price

    product_one = create_product("Product_1", shop, default_price=150)
    product_two = create_product("Product_2", shop, default_price=250)

    spp = CgpPrice(product=product_one,
                   shop=shop,
                   group=group,
                   price_value=100)
    spp.save()

    spp = CgpPrice(product=product_two,
                   shop=shop,
                   group=group,
                   price_value=200)
    spp.save()

    product_ids = [product_one.pk, product_two.pk]

    spm = get_pricing_module()
    assert isinstance(spm, CustomerGroupPricingModule)
    pricing_context = spm.get_context_from_request(request)
    price_infos = spm.get_price_infos(pricing_context, product_ids)

    assert len(price_infos) == 2
    assert product_one.pk in price_infos
    assert product_two.pk in price_infos

    assert price_infos[product_one.pk].price == price(100)
    assert price_infos[product_two.pk].price == price(200)

    assert price_infos[product_one.pk].base_price == price(100)
    assert price_infos[product_two.pk].base_price == price(200)
def test_variable_variation():
    parent = create_product("ComplexVarParent")
    sizes_and_children = [("%sL" % ("X" * x), create_product("ComplexVarChild-%d" % x)) for x in range(4)]
    for size, child in sizes_and_children:
        child.link_to_parent(parent, variables={"size": size})
    assert parent.mode == ProductMode.VARIABLE_VARIATION_PARENT
    assert all(child.is_variation_child() for (size, child) in sizes_and_children)

    # Validation tests

    dummy = create_product("InvalidComplexVarChild")

    with pytest.raises(ValueError):
        dummy.link_to_parent(parent)

    with pytest.raises(ValueError):
        parent.link_to_parent(dummy)

    with pytest.raises(ValueError):
        dummy.link_to_parent(sizes_and_children[0][1])

    # Variable tests

    size_attr = parent.variation_variables.get(identifier="size")

    for size, child in sizes_and_children:
        size_val = size_attr.values.get(identifier=size)
        result_product = ProductVariationResult.resolve(parent, {size_attr: size_val})
        assert result_product == child
Example #21
0
def test_price_infos_are_discounted(rf):
    request = initialize_test(rf, True)

    price = request.shop.create_price

    product_one = create_product("Product_1", request.shop, default_price=150)
    product_two = create_product("Product_2", request.shop, default_price=250)

    spp = DiscountedProductPrice(product=product_one, shop=request.shop, price_value=100)
    spp.save()

    spp = DiscountedProductPrice(product=product_two, shop=request.shop, price_value=200)
    spp.save()

    product_ids = [product_one.pk, product_two.pk]

    dpm = DiscountPricingModule()
    pricing_context = dpm.get_context_from_request(request)
    price_infos = dpm.get_price_infos(pricing_context, product_ids)

    assert len(price_infos) == 2
    assert product_one.pk in price_infos
    assert product_two.pk in price_infos

    first_price_info = price_infos[product_one.pk]
    second_price_info = price_infos[product_two.pk]

    assert first_price_info.price == price(100)
    assert first_price_info.base_price == price(150)
    assert first_price_info.is_discounted

    assert second_price_info.price == price(200)
    assert second_price_info.base_price == price(250)
    assert second_price_info.is_discounted
Example #22
0
def test_protected_fields():
    activate("en")
    shop = Shop.objects.create(
        name="testshop",
        identifier="testshop",
        status=ShopStatus.ENABLED,
        public_name="test shop",
        domain="derp",
        currency="EUR"
    )
    assert shop.name == "testshop"
    assert shop.currency == "EUR"
    shop_form = ShopBaseForm(instance=shop, languages=settings.LANGUAGES)
    assert not shop_form._get_protected_fields()  # No protected fields just yet, right?
    data = get_form_data(shop_form, prepared=True)
    shop_form = ShopBaseForm(data=data, instance=shop, languages=settings.LANGUAGES)
    _test_cleanliness(shop_form)
    shop_form.save()

    # Now let's make it protected!
    create_product(printable_gibberish(), shop=shop, supplier=get_default_supplier())
    order = create_random_order(customer=create_random_person(), shop=shop)
    assert order.shop == shop

    # And try again...
    data["currency"] = "XBT"  # Bitcoins!
    shop_form = ShopBaseForm(data=data, instance=shop, languages=settings.LANGUAGES)
    assert shop_form._get_protected_fields()  # So protected!
    _test_cleanliness(shop_form)
    shop = shop_form.save()
    assert shop.currency == "EUR"  # But the shop form ignored the change . . .
def test_best_selling_products_with_multiple_orders():
    context = get_jinja_context()
    supplier = get_default_supplier()
    shop = get_default_shop()
    n_products = 2
    price = 10

    product_1 = create_product("test-sku-1", supplier=supplier, shop=shop)
    product_2 = create_product("test-sku-2", supplier=supplier, shop=shop)
    create_order_with_product(product_1, supplier, quantity=1, taxless_base_unit_price=price, shop=shop)
    create_order_with_product(product_2, supplier, quantity=1, taxless_base_unit_price=price, shop=shop)
    cache.clear()
    # Two initial products sold
    assert product_1 in general.get_best_selling_products(context, n_products=n_products)
    assert product_2 in general.get_best_selling_products(context, n_products=n_products)

    product_3 = create_product("test-sku-3", supplier=supplier, shop=shop)
    create_order_with_product(product_3, supplier, quantity=2, taxless_base_unit_price=price, shop=shop)
    cache.clear()
    # Third product sold in greater quantity
    assert product_3 in general.get_best_selling_products(context, n_products=n_products)

    create_order_with_product(product_1, supplier, quantity=4, taxless_base_unit_price=price, shop=shop)
    create_order_with_product(product_2, supplier, quantity=4, taxless_base_unit_price=price, shop=shop)
    cache.clear()
    # Third product outsold by first two products
    assert product_3 not in general.get_best_selling_products(context, n_products=n_products)
Example #24
0
def test_limited_methods():
    """
    Test that products can declare that they limit available shipping methods.
    """
    unique_shipping_method = get_shipping_method(name="unique", price=0)
    shop = get_default_shop()
    common_product = create_product(sku="SH_COMMON", shop=shop)  # A product that does not limit shipping methods
    unique_product = create_product(sku="SH_UNIQUE", shop=shop)  # A product that only supports unique_shipping_method
    unique_shop_product = unique_product.get_shop_instance(shop)
    unique_shop_product.limit_shipping_methods = True
    unique_shop_product.shipping_methods.add(unique_shipping_method)
    unique_shop_product.save()
    impossible_product = create_product(sku="SH_IMP", shop=shop)  # A product that can't be shipped at all
    imp_shop_product = impossible_product.get_shop_instance(shop)
    imp_shop_product.limit_shipping_methods = True
    imp_shop_product.save()
    for product_ids, method_ids in [
        ((common_product.pk, unique_product.pk), (unique_shipping_method.pk,)),
        ((common_product.pk,), ShippingMethod.objects.values_list("pk", flat=True)),
        ((unique_product.pk,), (unique_shipping_method.pk,)),
        ((unique_product.pk, impossible_product.pk,), ()),
        ((common_product.pk, impossible_product.pk,), ()),
    ]:
        product_ids = set(product_ids)
        assert ShippingMethod.objects.available_ids(shop=shop, products=product_ids) == set(method_ids)
Example #25
0
def test_admin_form(rf, admin_user):
    supplier = get_simple_supplier()
    shop = get_default_shop()
    product = create_product("simple-test-product", shop, supplier)
    request = rf.get("/")
    request.user = admin_user
    frm = SimpleSupplierForm(product=product, request=request)
    # Form contains 1 product even if the product is not stocked
    assert len(frm.products) == 1
    assert not frm.products[0].is_stocked()

    product.stock_behavior = StockBehavior.STOCKED  # Make product stocked
    product.save()

    # Now since product is stocked it should be in the form
    frm = SimpleSupplierForm(product=product, request=request)
    assert len(frm.products) == 1

    # Add stocked children for product
    child_product = create_product("child-test-product", shop, supplier)
    child_product.stock_behavior = StockBehavior.STOCKED
    child_product.save()
    child_product.link_to_parent(product)

    # Admin form should now contain only child products for product
    frm = SimpleSupplierForm(product=product, request=request)
    assert len(frm.products) == 1
    assert frm.products[0] == child_product
Example #26
0
def test_price_infos_are_discounted(rf):
    request = initialize_test(rf, True)

    price = request.shop.create_price

    product_one = create_product("Product_1", request.shop, default_price=150)
    product_two = create_product("Product_2", request.shop, default_price=250)

    spp = DiscountedProductPrice(product=product_one, shop=request.shop, price_value=100)
    spp.save()

    spp = DiscountedProductPrice(product=product_two, shop=request.shop, price_value=200)
    spp.save()

    product_ids = [product_one.pk, product_two.pk]

    dpm = get_pricing_module()
    pricing_context = dpm.get_context_from_request(request)
    price_infos = dpm.get_price_infos(pricing_context, product_ids)

    assert len(price_infos) == 2
    assert product_one.pk in price_infos
    assert product_two.pk in price_infos

    first_price_info = price_infos[product_one.pk]
    second_price_info = price_infos[product_two.pk]

    assert first_price_info.price == price(100)
    assert first_price_info.base_price == price(150)
    assert first_price_info.is_discounted

    assert second_price_info.price == price(200)
    assert second_price_info.base_price == price(250)
    assert second_price_info.is_discounted
Example #27
0
def test_admin_form(rf, admin_user):
    supplier = get_simple_supplier()
    shop = get_default_shop()
    product = create_product("simple-test-product", shop, supplier)
    request = rf.get("/")
    request.user = admin_user
    frm = SimpleSupplierForm(product=product, request=request)
    # Form contains 1 product even if the product is not stocked
    assert len(frm.products) == 1
    assert not frm.products[0].is_stocked()

    product.stock_behavior = StockBehavior.STOCKED  # Make product stocked
    product.save()

    # Now since product is stocked it should be in the form
    frm = SimpleSupplierForm(product=product, request=request)
    assert len(frm.products) == 1

    # Add stocked children for product
    child_product = create_product("child-test-product", shop, supplier)
    child_product.stock_behavior = StockBehavior.STOCKED
    child_product.save()
    child_product.link_to_parent(product)

    # Admin form should now contain only child products for product
    frm = SimpleSupplierForm(product=product, request=request)
    assert len(frm.products) == 1
    assert frm.products[0] == child_product
def initialize_test(rf):
    shop = get_default_shop()
    request = rf.get("/")
    request.shop = shop
    apply_request_middleware(request)
    product1 = create_product("test-product1", shop=shop, default_price=120)
    product2 = create_product("test-product2", shop=shop, default_price=180)
    return (request, [product1, product2], shop.create_price)
def initialize_test(rf):
    shop = get_default_shop()
    request = rf.get("/")
    request.shop = shop
    apply_request_middleware(request)
    product1 = create_product("test-product1", shop=shop, default_price=120)
    product2 = create_product("test-product2", shop=shop, default_price=180)
    return (request, [product1, product2], shop.create_price)
Example #30
0
def test_basket_free_product_coupon(rf):
    request, shop, group = initialize_test(rf, False)
    price = shop.create_price

    basket = get_basket(request)
    supplier = get_default_supplier()

    single_product_price = "50"
    discount_amount_value = "10"

    # create basket rule that requires 2 products in basket
    product = create_product(printable_gibberish(),
                             shop=shop,
                             supplier=supplier,
                             default_price=single_product_price)
    basket.add_product(supplier=supplier,
                       shop=shop,
                       product=product,
                       quantity=1)
    basket.add_product(supplier=supplier,
                       shop=shop,
                       product=product,
                       quantity=1)
    basket.save()

    second_product = create_product(printable_gibberish(),
                                    shop=shop,
                                    supplier=supplier,
                                    default_price=single_product_price)

    rule = BasketTotalProductAmountCondition.objects.create(value="2")
    coupon = Coupon.objects.create(code="TEST", active=True)

    campaign = BasketCampaign.objects.create(active=True,
                                             shop=shop,
                                             name="test",
                                             public_name="test",
                                             coupon=coupon)
    campaign.conditions.add(rule)

    effect = FreeProductLine.objects.create(campaign=campaign)
    effect.products.add(second_product)

    basket.add_code(coupon.code)

    basket.uncache()
    final_lines = basket.get_final_lines()

    assert len(final_lines) == 2

    line_types = [l.type for l in final_lines]
    assert OrderLineType.DISCOUNT not in line_types

    for line in basket.get_final_lines():
        assert line.type == OrderLineType.PRODUCT

        if line.product != product:
            assert line.product == second_product
Example #31
0
def test_variable_variation_form():
    var1 = printable_gibberish()
    var2 = printable_gibberish()
    parent = create_product(printable_gibberish())
    for a in range(4):
        for b in range(3):
            child = create_product(printable_gibberish())
            child.link_to_parent(parent, variables={var1: a, var2: b})
    assert parent.variation_children.count() == 4 * 3

    form = VariableVariationChildrenForm(parent_product=parent)
    assert len(form.fields) == 12
Example #32
0
def test_package_product_page(client):
    shop = get_default_shop()
    parent = create_product("test-sku-1", shop=shop)
    child = create_product("test-sku-2", shop=shop)
    parent.make_package({child: 2})
    assert parent.is_package_parent()

    response = client.get(
        reverse('shoop:product', kwargs={
            'pk': parent.pk,
            'slug': parent.slug
        }))
    assert b'no such element' not in response.content, 'All items are not rendered correctly'
def test_best_selling_products_with_multiple_orders():
    context = get_jinja_context()
    supplier = get_default_supplier()
    shop = get_default_shop()
    n_products = 2
    price = 10

    product_1 = create_product("test-sku-1", supplier=supplier, shop=shop)
    product_2 = create_product("test-sku-2", supplier=supplier, shop=shop)
    create_order_with_product(product_1,
                              supplier,
                              quantity=1,
                              taxless_base_unit_price=price,
                              shop=shop)
    create_order_with_product(product_2,
                              supplier,
                              quantity=1,
                              taxless_base_unit_price=price,
                              shop=shop)
    cache.clear()
    # Two initial products sold
    assert product_1 in general.get_best_selling_products(
        context, n_products=n_products)
    assert product_2 in general.get_best_selling_products(
        context, n_products=n_products)

    product_3 = create_product("test-sku-3", supplier=supplier, shop=shop)
    create_order_with_product(product_3,
                              supplier,
                              quantity=2,
                              taxless_base_unit_price=price,
                              shop=shop)
    cache.clear()
    # Third product sold in greater quantity
    assert product_3 in general.get_best_selling_products(
        context, n_products=n_products)

    create_order_with_product(product_1,
                              supplier,
                              quantity=4,
                              taxless_base_unit_price=price,
                              shop=shop)
    create_order_with_product(product_2,
                              supplier,
                              quantity=4,
                              taxless_base_unit_price=price,
                              shop=shop)
    cache.clear()
    # Third product outsold by first two products
    assert product_3 not in general.get_best_selling_products(
        context, n_products=n_products)
def get_package_product():
    """
    :rtype: shoop.core.models.Product
    """
    shop = get_default_shop()
    supplier = get_default_supplier()
    package_product = create_product("PackageParent", shop=shop, supplier=supplier)
    assert not package_product.get_package_child_to_quantity_map()
    children = [create_product("PackageChild-%d" % x, shop=shop, supplier=supplier) for x in range(4)]
    package_def = {child: 1 + i for (i, child) in enumerate(children)}
    package_product.make_package(package_def)
    assert package_product.is_package_parent()
    package_product.save()
    return package_product
Example #35
0
def test_variation():
    request = get_request_with_basket()
    basket = request.basket
    shop = get_default_shop()
    supplier = get_default_supplier()
    parent = create_product("BuVarParent", shop=shop, supplier=supplier)
    child = create_product("BuVarChild", shop=shop, supplier=supplier)
    child.link_to_parent(parent, variables={"test": "very"})
    attr = parent.variation_variables.get(identifier="test")
    val = attr.values.get(identifier="very")
    basket_commands.handle_add_var(request, basket, 1, **{"var_%s" % attr.id: val.id})
    assert basket.get_product_ids_and_quantities()[child.pk] == 1
    with pytest.raises(ValidationError):
        basket_commands.handle_add_var(request, basket, 1, **{"var_%s" % attr.id: (val.id + 1)})
Example #36
0
def test_cross_sell_plugin_renders():
    """
    Test that the plugin renders a product
    """
    shop = get_default_shop()
    product = create_product("test-sku", shop=shop, stock_behavior=StockBehavior.UNSTOCKED)
    computed = create_product("test-computed-sku", shop=shop, stock_behavior=StockBehavior.UNSTOCKED)
    type = ProductCrossSellType.COMPUTED

    ProductCrossSell.objects.create(product1=product, product2=computed, type=type)
    assert ProductCrossSell.objects.filter(product1=product, type=type).count() == 1

    context = get_jinja_context(product=product)
    rendered  = ProductCrossSellsPlugin({"type": type}).render(context)
    assert computed.sku in rendered
Example #37
0
def test_package_product_page(client):
    shop = get_default_shop()
    parent = create_product("test-sku-1", shop=shop)
    child = create_product("test-sku-2", shop=shop)
    parent.make_package({child: 2})
    assert parent.is_package_parent()

    response = client.get(
        reverse('shoop:product', kwargs={
            'pk': parent.pk,
            'slug': parent.slug
            }
        )
    )
    assert b'no such element' not in response.content, 'All items are not rendered correctly'
def _get_order_with_coupon(request, initial_status, condition_product_count=1):
    shop = request.shop
    basket = get_basket(request)
    supplier = get_default_supplier()
    product = create_product(printable_gibberish(), shop=shop, supplier=supplier, default_price="50")
    basket.add_product(supplier=supplier, shop=shop, product=product, quantity=1)

    dc = Coupon.objects.create(code="TEST", active=True)
    campaign = BasketCampaign.objects.create(
        shop=shop,
        name="test",
        public_name="test",
        coupon=dc,
        discount_amount_value=shop.create_price("20"),
        active=True
    )
    rule = BasketTotalProductAmountCondition.objects.create(value=1)
    campaign.conditions.add(rule)
    campaign.save()
    basket.add_code(dc.code)
    basket.save()

    basket.status = initial_status
    creator = OrderCreator(request)
    order = creator.create_order(basket)
    assert order.lines.count() == 2
    assert OrderLineType.DISCOUNT in [l.type for l in order.lines.all()]
    return order
def _get_frontend_order_state(shop, contact):
    tax = Tax.objects.create(code="test_code", rate=decimal.Decimal("0.20"), name="Default")
    tax_class = TaxClass.objects.create(identifier="test_tax_class", name="Default")
    rule = TaxRule.objects.create(tax=tax)
    rule.tax_classes.add(tax_class)
    rule.save()
    product = create_product(
        sku=printable_gibberish(),
        supplier=get_default_supplier(),
        shop=shop
    )
    product.tax_class = tax_class
    product.save()
    lines = [
        {"id": "x", "type": "product", "product": {"id": product.id}, "quantity": "32", "baseUnitPrice": 50}
    ]

    state = {
        "customer": {"id": contact.id if contact else None},
        "lines": lines,
        "methods": {
            "shippingMethod": {"id": get_shipping_method(shop=shop).id},
            "paymentMethod": {"id": get_payment_method(shop=shop).id},
        },
        "shop": {
            "selected": {
                "id": shop.id,
                "name": shop.safe_translation_getter("name"),
                "currency": shop.currency,
                "priceIncludeTaxes": shop.prices_include_tax
            }
        }
    }
    return state
Example #40
0
def test_start_end_dates(rf):
    activate("en")
    original_price = "180"
    discounted_price = "160"
    request, shop, group = initialize_test(rf, False)
    cat = Category.objects.create(name="test")
    rule1, rule2 = create_condition_and_filter(cat, request)

    campaign = CatalogCampaign.objects.create(shop=shop,
                                              name="test",
                                              discount_amount_value="20",
                                              active=True)
    campaign.conditions.add(rule1)
    campaign.save()
    price = shop.create_price

    product = create_product("Just-A-Product-Too",
                             shop,
                             default_price=original_price)

    today = now()

    # starts in future
    campaign.start_datetime = (today + datetime.timedelta(days=2))
    campaign.save()
    assert not campaign.is_available()
    assert product.get_price_info(request,
                                  quantity=1).price == price(original_price)

    # has already started
    campaign.start_datetime = (today - datetime.timedelta(days=2))
    campaign.save()
    assert product.get_price_info(request,
                                  quantity=1).price == price(discounted_price)

    # already ended
    campaign.end_datetime = (today - datetime.timedelta(days=1))
    campaign.save()
    assert not campaign.is_available()
    assert product.get_price_info(request,
                                  quantity=1).price == price(original_price)

    # not ended yet
    campaign.end_datetime = (today + datetime.timedelta(days=1))
    campaign.save()
    assert product.get_price_info(request,
                                  quantity=1).price == price(discounted_price)

    # no start datetime
    campaign.start_datetime = None
    campaign.save()
    assert product.get_price_info(request,
                                  quantity=1).price == price(discounted_price)

    # no start datetime but ended
    campaign.end_datetime = (today - datetime.timedelta(days=1))
    campaign.save()
    assert not campaign.is_available()
    assert product.get_price_info(request,
                                  quantity=1).price == price(original_price)
Example #41
0
def create_basket_and_campaign(request, conditions, product_price_value,
                               campaign_discount_value):
    product = create_product("Some crazy product",
                             request.shop,
                             get_default_supplier(),
                             default_price=product_price_value)
    basket = get_basket(request)
    basket.customer = request.customer
    supplier = get_default_supplier()
    basket.add_product(supplier=supplier,
                       shop=request.shop,
                       product=product,
                       quantity=1)

    original_line_count = len(basket.get_final_lines())
    assert original_line_count == 1
    assert basket.product_count == 1
    original_price = basket.total_price

    campaign = BasketCampaign.objects.create(shop=request.shop,
                                             name="test",
                                             public_name="test",
                                             active=True)
    BasketDiscountAmount.objects.create(
        campaign=campaign, discount_amount=campaign_discount_value)

    for condition in conditions:
        campaign.conditions.add(condition)
    assert campaign.is_available()

    return basket, original_line_count, original_price
Example #42
0
def test_module(address, expected_taxes):
    """
    Test the DefaultTaxModule.
    """
    # Create a product
    shop = get_shop(prices_include_tax=False, currency='USD')
    product = create_product('PROD', shop=shop, default_price=1000)
    price = product.get_shop_instance(shop).default_price

    # Put the tax rules into database
    for ruledef in shuffled(TAX_RULE_DEFS):
        rule = ruledef.get_tax_rule()
        rule.tax.save()
        rule.tax = rule.tax  # refresh the id
        rule.save()
        rule.tax_classes.add(product.tax_class)
    assert TaxRule.objects.count() == len(TAX_RULE_DEFS)

    with override_settings(SHOOP_TAX_MODULE='default_tax'):
        module = get_tax_module()
        assert isinstance(module, DefaultTaxModule)

        context = TaxingContext(location=address)
        taxed_price = module.get_taxed_price_for(context, product, price)
        expected_codes = set(sum([x.split() for x in expected_taxes], []))
        assert set(x.tax.code for x in taxed_price.taxes) == expected_codes
        expected_tax = Money(TAX_AMOUNTS[expected_taxes], 'USD')
        assert taxed_price.taxful.amount == price.amount + expected_tax

    # Clean-up the rules
    TaxRule.objects.all().delete()
Example #43
0
def test_ajax_select_view_with_products(rf):
    activate("en")
    view = MultiselectAjaxView.as_view()
    results = _get_search_results(rf, view, "shoop.Product", "some str")
    assert len(results) == 0

    product_name_en = "The Product"
    product = create_product("the product", **{"name": product_name_en})

    product_name_fi = "product"
    product.set_current_language("fi")
    # Making sure we are not getting duplicates from translations
    product.name = "product"  # It seems that finnish translation overlaps with english name
    product.save()

    view = MultiselectAjaxView.as_view()
    results = _get_search_results(rf, view, "shoop.Product", "some str")
    assert len(results) == 0

    results = _get_search_results(rf, view, "shoop.Product", "product")
    assert len(results) == 1
    assert results[0].get("id") == product.id
    assert results[0].get("name") == product_name_en

    activate("fi")
    results = _get_search_results(rf, view, "shoop.Product", "product")
    assert len(results) == 1
    assert results[0].get("id") == product.id
    assert results[0].get("name") == product_name_fi
def test_percentage_campaign(rf):
    request, shop, group = initialize_test(rf, False)
    price = shop.create_price

    basket = get_basket(request)
    supplier = get_default_supplier()
    # create a basket rule that requires atleast value of 200
    rule = BasketTotalAmountCondition.objects.create(value="200")

    product_price = "200"

    discount_percentage = "0.1"

    expected_discounted_price = price(product_price) - (price(product_price) * Decimal(discount_percentage))

    product = create_product(printable_gibberish(), shop=shop, supplier=supplier, default_price=product_price)
    basket.add_product(supplier=supplier, shop=shop, product=product, quantity=1)

    campaign = BasketCampaign.objects.create(
        shop=shop, public_name="test", name="test", discount_percentage=discount_percentage, active=True
    )
    campaign.conditions.add(rule)
    campaign.save()

    assert len(basket.get_final_lines()) == 2
    assert basket.product_count == 1
    assert basket.total_price == expected_discounted_price
def test_only_cheapest_price_is_selected(rf):
    request, shop, group = initialize_test(rf, False)
    price = shop.create_price

    basket = get_basket(request)
    supplier = get_default_supplier()
    # create a basket rule that requires atleast value of 200
    rule = BasketTotalAmountCondition.objects.create(value="200")

    product_price = "200"

    discount1 = "10"
    discount2 = "20"  # should be selected
    product = create_product(printable_gibberish(), shop=shop, supplier=supplier, default_price=product_price)
    basket.add_product(supplier=supplier, shop=shop, product=product, quantity=1)

    campaign = BasketCampaign.objects.create(
        shop=shop, public_name="test", name="test", discount_amount_value=discount1, active=True
    )
    campaign.conditions.add(rule)
    campaign.save()

    campaign = BasketCampaign.objects.create(
        shop=shop, public_name="test", name="test", discount_amount_value=discount2, active=True
    )
    campaign.conditions.add(rule)
    campaign.save()

    assert len(basket.get_final_lines()) == 2
    line_types = [l.type for l in basket.get_final_lines()]
    assert OrderLineType.DISCOUNT in line_types

    for line in basket.get_final_lines():
        if line.type == OrderLineType.DISCOUNT:
            assert line.discount_amount == price(discount2)
Example #46
0
def test_ajax_select_view_with_products(rf):
    activate("en")
    view = MultiselectAjaxView.as_view()
    results = _get_search_results(rf, view, "shoop.Product", "some str")
    assert len(results) == 0

    product_name_en = "The Product"
    product = create_product("the product", **{"name": product_name_en})

    product_name_fi = "product"
    product.set_current_language("fi")
    # Making sure we are not getting duplicates from translations
    product.name = "product"  # It seems that finnish translation overlaps with english name
    product.save()

    view = MultiselectAjaxView.as_view()
    results = _get_search_results(rf, view, "shoop.Product", "some str")
    assert len(results) == 0

    results = _get_search_results(rf, view, "shoop.Product", "product")
    assert len(results) == 1
    assert results[0].get("id") == product.id
    assert results[0].get("name") == product_name_en

    activate("fi")
    results = _get_search_results(rf, view, "shoop.Product", "product")
    assert len(results) == 1
    assert results[0].get("id") == product.id
    assert results[0].get("name") == product_name_fi
Example #47
0
def test_price_cannot_be_under_zero(rf):

    activate("en")
    discount_amount = "200"
    original_price = "199.20"

    request, shop, group = initialize_test(rf, False)
    cat = Category.objects.create(name="test")
    rule1, rule2 = create_condition_and_filter(cat, request)
    campaign = CatalogCampaign.objects.create(
        shop=shop,
        name="test",
        discount_amount_value=discount_amount,
        active=True)
    campaign.conditions.add(rule1)
    campaign.filters.add(rule2)
    campaign.save()

    price = shop.create_price

    product = create_product("Just-A-Product-Too",
                             shop,
                             default_price=original_price)
    shop_product = product.get_shop_instance(shop)
    shop_product.categories.add(cat)
    shop_product.save()

    assert product.get_price_info(request, quantity=1).price == price("0")
Example #48
0
def test_coupon_amount_limit():
    coupon = Coupon.objects.create(code="TEST", active=True)
    get_default_campaign(coupon)

    contact = create_random_person()
    shop = get_default_shop()
    product = create_product("test",
                             shop=shop,
                             supplier=get_default_supplier(),
                             default_price="12")
    order = create_random_order(customer=contact)

    for x in range(50):
        coupon.use(order)

    assert coupon.usages.count() == 50
    coupon.increase_usage_limit_by(5)
    coupon.save()

    assert coupon.usage_limit == 55
    assert coupon.can_use_code(contact)

    for x in range(5):
        coupon.use(order)

    assert coupon.usages.count() == 55

    assert not Coupon.is_usable(coupon.code, order.customer)
    assert coupon.usages.count() == 55  # no change, limit met
Example #49
0
def test_extending_shipment_form_valid_hook(rf, admin_user):
    shop = get_default_shop()
    supplier = get_default_supplier()
    product = create_product(sku="test-sku", shop=shop, supplier=supplier, default_price=3.33)
    quantity = 1
    order = create_order_with_product(product, supplier, quantity=quantity, taxless_base_unit_price=1, shop=shop)

    extend_form_class = "shoop_tests.admin.test_shipment_creator.ShipmentFormModifierTest"
    with override_provides(FORM_MODIFIER_PROVIDER_KEY, [extend_form_class]):
        phone_number = "+358911"
        data = {"q_%s" % product.pk: 1, "supplier": supplier.pk, "phone": phone_number}
        request = apply_request_middleware(rf.post("/", data=data), user=admin_user)
        view = OrderCreateShipmentView.as_view()
        response = view(request, pk=order.pk)
        assert response.status_code == 302

        # Order should now have shipment, but let's re fetch it first
        order = Order.objects.get(pk=order.pk)
        assert order.shipments.count() == 1

        shipment = order.shipments.first()
        assert order.shipping_data.get(shipment.identifier).get("phone") == phone_number
        assert shipment.supplier_id == supplier.id
        assert shipment.products.count() == 1
        assert shipment.products.first().product_id == product.id
def test_cross_sell_plugin_type():
    """
    Test that template helper returns correct number of cross sells when shop contains multiple
    relation types
    """
    shop = get_default_shop()
    supplier = get_default_supplier()
    product = create_product("test-sku",
                             shop=shop,
                             supplier=supplier,
                             stock_behavior=StockBehavior.UNSTOCKED)
    context = get_jinja_context(product=product)
    type_counts = ((ProductCrossSellType.RELATED,
                    1), (ProductCrossSellType.RECOMMENDED, 2),
                   (ProductCrossSellType.BOUGHT_WITH, 3))

    # Create cross sell products and relations in different quantities
    for type, count in type_counts:
        _create_cross_sell_products(product, shop, supplier, type, count)
        assert ProductCrossSell.objects.filter(product1=product,
                                               type=type).count() == count

    # Make sure quantities returned by plugin match
    for type, count in type_counts:
        assert len(
            list(
                product_helpers.get_product_cross_sells(
                    context, product, type, count))) == count
Example #51
0
def test_variation():
    request = get_request_with_basket()
    basket = request.basket
    shop = get_default_shop()
    supplier = get_default_supplier()
    parent = create_product("BuVarParent", shop=shop, supplier=supplier)
    child = create_product("BuVarChild", shop=shop, supplier=supplier)
    child.link_to_parent(parent, variables={"test": "very"})
    attr = parent.variation_variables.get(identifier="test")
    val = attr.values.get(identifier="very")
    basket_commands.handle_add_var(request, basket, 1,
                                   **{"var_%s" % attr.id: val.id})
    assert basket.get_product_ids_and_quantities()[child.pk] == 1
    with pytest.raises(ValidationError):
        basket_commands.handle_add_var(request, basket, 1,
                                       **{"var_%s" % attr.id: (val.id + 1)})
Example #52
0
def test_category_filter(rf):
    request, shop, group = initialize_test(rf, False)

    cat = get_default_category()
    cat_filter = CategoryFilter.objects.create()
    cat_filter.categories.add(cat)
    cat_filter.save()

    assert cat_filter.values.first() == cat
    category = Category.objects.create(
        parent=None,
        identifier="testcat",
        name="catcat",
    )
    cat_filter.values = [cat, category]
    cat_filter.save()

    assert cat_filter.values.count() == 2

    product = create_product("Just-A-Product-Too", shop, default_price="200")
    shop_product = product.get_shop_instance(shop)
    shop_product.categories.add(cat)
    shop_product.save()

    assert cat_filter.filter_queryset(ShopProduct.objects.all()).exists()  # filter matches
Example #53
0
def _get_order_with_coupon(request, initial_status, condition_product_count=1):
    shop = request.shop
    basket = get_basket(request)
    supplier = get_default_supplier()
    product = create_product(printable_gibberish(),
                             shop=shop,
                             supplier=supplier,
                             default_price="50")
    basket.add_product(supplier=supplier,
                       shop=shop,
                       product=product,
                       quantity=1)

    dc = Coupon.objects.create(code="TEST", active=True)
    campaign = BasketCampaign.objects.create(shop=shop,
                                             name="test",
                                             public_name="test",
                                             coupon=dc,
                                             active=True)

    BasketDiscountAmount.objects.create(
        discount_amount=shop.create_price("20"), campaign=campaign)

    rule = BasketTotalProductAmountCondition.objects.create(value=1)
    campaign.conditions.add(rule)
    campaign.save()
    basket.add_code(dc.code)
    basket.save()

    basket.status = initial_status
    creator = OrderCreator(request)
    order = creator.create_order(basket)
    assert order.lines.count() == 2
    assert OrderLineType.DISCOUNT in [l.type for l in order.lines.all()]
    return order
Example #54
0
def test_coupon_amount_limit():
    coupon = Coupon.objects.create(code="TEST", active=True)
    get_default_campaign(coupon)

    contact = create_random_person()
    shop = get_default_shop()
    product = create_product("test", shop=shop, supplier=get_default_supplier(), default_price="12")
    order = create_random_order(customer=contact)

    for x in range(50):
       coupon.use(order)

    assert coupon.usages.count() == 50
    coupon.increase_usage_limit_by(5)
    coupon.save()

    assert coupon.usage_limit == 55
    assert coupon.can_use_code(contact)

    for x in range(5):
        coupon.use(order)

    assert coupon.usages.count() == 55

    assert not Coupon.is_usable(coupon.code, order.customer)
    assert coupon.usages.count() == 55  # no change, limit met
def test_product_caching_object():
    shop_product = get_default_shop_product()
    product = shop_product.product
    another_product = create_product("PCOTestProduct")

    pco = ProductCachingObject()
    pco.product = product
    assert pco.product is product
    assert pco.product_id == product.pk
    assert ProductCachingObject().product != pco.product  # Assert PCOs are separate
    assert pco._product_cache == pco.product  # This private property is courtesy of ModelCachingDescriptor

    pco = ProductCachingObject()
    pco.product_id = product.pk
    assert pco.product == product
    assert pco.product_id == product.pk

    # Not creating a new PCO here
    pco.product = another_product
    assert pco.product == another_product
    assert pco.product_id == another_product.pk

    # Nor here
    pco.product_id = product.pk
    assert pco.product == product
    assert pco.product_id == product.pk