Esempio n. 1
0
def seed_source(user, shop=None):
    source_shop = shop or get_default_shop()
    source = BasketishOrderSource(source_shop)
    billing_address = get_address()
    shipping_address = get_address(name="Shippy Doge")
    source.status = get_initial_order_status()
    source.billing_address = billing_address
    source.shipping_address = shipping_address
    source.customer = get_person_contact(user)
    source.payment_method = get_payment_method(shop)
    source.shipping_method = get_shipping_method(shop)
    assert source.payment_method_id == get_payment_method(shop).id
    assert source.shipping_method_id == get_shipping_method(shop).id
    return source
Esempio n. 2
0
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)
    basket.shipping_method = get_shipping_method(shop=shop)

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

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

    assert len(basket.get_final_lines()) == 3

    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)
Esempio n. 3
0
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 at least 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)
    basket.shipping_method = get_shipping_method(shop=shop)

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

    BasketDiscountPercentage.objects.create(campaign=campaign, discount_percentage=discount_percentage)

    assert len(basket.get_final_lines()) == 3
    assert basket.product_count == 1
    assert basket.total_price == expected_discounted_price
Esempio n. 4
0
def _get_source(user, shipping_country, billing_country):
    prices_include_taxes = True
    shop = get_shop(prices_include_taxes)
    payment_method = get_payment_method(shop)
    shipping_method = get_shipping_method(shop)
    source = _seed_source(shop, user, shipping_country, billing_country)
    source.payment_method = payment_method
    source.shipping_method = shipping_method
    assert source.payment_method_id == payment_method.id
    assert source.shipping_method_id == shipping_method.id

    supplier = get_default_supplier()
    product = create_product(
        sku="test-%s--%s" % (prices_include_taxes, 10),
        shop=source.shop,
        supplier=supplier,
        default_price=10
    )
    source.add_line(
        type=OrderLineType.PRODUCT,
        product=product,
        supplier=supplier,
        quantity=1,
        base_unit_price=source.create_price(10),
    )
    assert payment_method == source.payment_method
    assert shipping_method == source.shipping_method
    return source
Esempio n. 5
0
def test_source_lines_with_multiple_fixed_costs():
    """
    Costs with description creates new line always and costs without
    description is combined into one line.
    """
    translation.activate("en")
    starting_price_value = 5
    sm = get_shipping_method(name="Multiple costs", price=starting_price_value)
    sm.behavior_components.clear()

    source = BasketishOrderSource(get_default_shop())
    source.shipping_method = sm

    lines = list(sm.get_lines(source))
    assert len(lines) == 1
    assert get_total_price_value(lines) == Decimal("0")

    sm.behavior_components.add(
        FixedCostBehaviorComponent.objects.create(price_value=10))
    lines = list(sm.get_lines(source))
    assert len(lines) == 1
    assert get_total_price_value(lines) == Decimal("10")

    sm.behavior_components.add(
        FixedCostBehaviorComponent.objects.create(price_value=15,
                                                  description="extra"))
    lines = list(sm.get_lines(source))
    assert len(lines) == 2
    assert get_total_price_value(lines) == Decimal("25")

    sm.behavior_components.add(
        FixedCostBehaviorComponent.objects.create(price_value=1))
    lines = list(sm.get_lines(source))
    assert len(lines) == 2
    assert get_total_price_value(lines) == Decimal("26")
Esempio n. 6
0
def test_translations_of_method_and_component():
    sm = get_shipping_method(name="Unique shipping")
    sm.set_current_language('en')
    sm.name = "Shipping"
    sm.set_current_language('fi')
    sm.name = "Toimitus"
    sm.save()

    cost = FixedCostBehaviorComponent.objects.language('fi').create(
        price_value=10, description="kymppi")
    cost.set_current_language('en')
    cost.description = "ten bucks"
    cost.save()
    sm.behavior_components.add(cost)

    source = BasketishOrderSource(get_default_shop())
    source.shipping_method = sm

    translation.activate('fi')
    shipping_lines = [
        line for line in source.get_final_lines()
        if line.type == OrderLineType.SHIPPING
    ]
    assert len(shipping_lines) == 1
    assert shipping_lines[0].text == 'Toimitus: kymppi'

    translation.activate('en')
    source.uncache()
    shipping_lines = [
        line for line in source.get_final_lines()
        if line.type == OrderLineType.SHIPPING
    ]
    assert len(shipping_lines) == 1
    assert shipping_lines[0].text == 'Shipping: ten bucks'
Esempio n. 7
0
def test_productfilter_works(rf):
    request, shop, group = initialize_test(rf, False)
    price = shop.create_price
    product_price = "100"
    discount_percentage = "0.30"

    supplier = get_default_supplier()
    product = create_product(printable_gibberish(), shop=shop, supplier=supplier, default_price=product_price)
    shop_product = product.get_shop_instance(shop)

    # create catalog campaign
    catalog_filter = ProductFilter.objects.create()
    catalog_filter.products.add(product)

    assert catalog_filter.matches(shop_product)

    catalog_campaign = CatalogCampaign.objects.create(shop=shop, active=True, name="test")
    catalog_campaign.filters.add(catalog_filter)
    cdp = ProductDiscountPercentage.objects.create(campaign=catalog_campaign, discount_percentage=discount_percentage)

    # add product to basket
    basket = get_basket(request)
    basket.add_product(supplier=supplier, shop=shop, product=product, quantity=1)
    basket.shipping_method = get_shipping_method(shop=shop)
    basket.save()

    expected_total = price(product_price) - (Decimal(discount_percentage) * price(product_price))
    assert basket.total_price == expected_total
Esempio n. 8
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)
    basket.shipping_method = get_shipping_method(shop=request.shop)

    original_line_count = len(basket.get_final_lines())
    assert original_line_count == 2
    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
Esempio n. 9
0
def _get_source(user, prices_include_taxes, total_price_value):
    shop = get_shop(prices_include_taxes)
    payment_method = get_payment_method(shop)
    shipping_method = get_shipping_method(shop)
    source = _seed_source(shop, user)
    source.payment_method = payment_method
    source.shipping_method = shipping_method
    assert source.payment_method_id == payment_method.id
    assert source.shipping_method_id == shipping_method.id

    supplier = get_default_supplier()
    product = create_product(sku="test-%s--%s" %
                             (prices_include_taxes, total_price_value),
                             shop=source.shop,
                             supplier=supplier,
                             default_price=total_price_value)
    source.add_line(
        type=OrderLineType.PRODUCT,
        product=product,
        supplier=supplier,
        quantity=1,
        base_unit_price=source.create_price(total_price_value),
    )
    if prices_include_taxes:
        assert source.taxful_total_price.value == total_price_value
    else:
        assert source.taxless_total_price.value == total_price_value
    assert payment_method == source.payment_method
    assert shipping_method == source.shipping_method
    return source, shipping_method
Esempio n. 10
0
def _init_basket_coupon_test(rf, code="TEST"):
    status = get_initial_order_status()
    request, shop, group = initialize_test(rf, False)
    basket = get_basket(request)
    supplier = get_default_supplier()
    for x in range(2):
        product = create_product(printable_gibberish(),
                                 shop,
                                 supplier=supplier,
                                 default_price="50")
        basket.add_product(supplier=supplier,
                           shop=shop,
                           product=product,
                           quantity=1)
    basket.shipping_method = get_shipping_method(
        shop=shop)  # For shippable products
    dc = Coupon.objects.create(code=code, 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=2)
    campaign.conditions.add(rule)
    campaign.save()
    return basket, dc, request, status
Esempio n. 11
0
def test_basket_free_product_coupon(rf):
    request, shop, _ = initialize_test(rf, False)

    basket = get_basket(request)
    supplier = get_default_supplier()

    single_product_price = "50"

    # 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.shipping_method = get_shipping_method(shop=shop)
    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) == 3

    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 in [OrderLineType.PRODUCT, OrderLineType.SHIPPING]
        if line.type == OrderLineType.SHIPPING:
            continue

        if line.product != product:
            assert line.product == second_product
Esempio n. 12
0
def test_product_category_discount_percentage_greater_then_products(
        rf, include_tax):
    # Buy X amount of Y get Z discount from Y
    request, shop, _ = initialize_test(rf, include_tax)

    basket = get_basket(request)
    supplier = get_default_supplier()

    single_product_price = "50"
    discount_percentage = Decimal(1.9)  # 190%
    quantity = 2

    # the expected discount amount should not be greater than the products
    expected_discount_amount = basket.create_price(
        single_product_price) * quantity

    category = CategoryFactory()

    # create basket rule that requires 2 products in basket
    product = create_product(printable_gibberish(),
                             shop=shop,
                             supplier=supplier,
                             default_price=single_product_price)
    ShopProduct.objects.get(shop=shop,
                            product=product).categories.add(category)
    basket.add_product(supplier=supplier,
                       shop=shop,
                       product=product,
                       quantity=quantity)
    basket.shipping_method = get_shipping_method(shop=shop)
    basket.save()

    rule = ProductsInBasketCondition.objects.create(quantity=2)
    rule.products.add(product)
    rule.save()

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

    DiscountFromCategoryProducts.objects.create(
        campaign=campaign,
        discount_percentage=discount_percentage,
        category=category)
    assert rule.matches(basket, [])
    basket.uncache()

    final_lines = basket.get_final_lines()

    assert len(final_lines
               ) == 2  # no new lines since the effect touches original lines

    original_price = basket.create_price(single_product_price) * quantity
    line = final_lines[0]
    assert line.discount_amount == expected_discount_amount
    assert basket.total_price == original_price - expected_discount_amount
Esempio n. 13
0
def test_productdiscountamount_with_minimum_price(rf, per_line_discount):
    # Buy X amount of Y get Z discount from Y
    request, shop, _ = initialize_test(rf, False)

    basket = get_basket(request)
    supplier = get_default_supplier()

    single_product_price = Decimal("50")
    single_product_min_price = Decimal("40")
    discount_amount_value = Decimal("200")  # will exceed the minimum price
    quantity = 2

    # create basket rule that requires 2 products in basket
    product = create_product(printable_gibberish(),
                             shop=shop,
                             supplier=supplier,
                             default_price=single_product_price)
    shop_product = ShopProduct.objects.get(product=product, shop=shop)
    shop_product.minimum_price_value = single_product_min_price
    shop_product.save()

    basket.add_product(supplier=supplier,
                       shop=shop,
                       product=product,
                       quantity=quantity)
    basket.shipping_method = get_shipping_method(shop=shop)
    basket.save()

    rule = ProductsInBasketCondition.objects.create(quantity=2)
    rule.products.add(product)
    rule.save()

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

    effect = DiscountFromProduct.objects.create(
        campaign=campaign,
        discount_amount=discount_amount_value,
        per_line_discount=per_line_discount)
    effect.products.add(product)

    assert rule.matches(basket, [])
    basket.uncache()

    # the discount amount should not exceed the minimum price. as the configued discount
    # will exceed, it should limit the discount amount
    final_lines = basket.get_final_lines()
    expected_discount_amount = basket.create_price(
        (single_product_price - single_product_min_price) * quantity)
    original_price = basket.create_price(single_product_price) * quantity
    line = final_lines[0]
    assert line.discount_amount == expected_discount_amount
    assert basket.total_price == original_price - expected_discount_amount
Esempio n. 14
0
def test_waiver():
    sm = get_shipping_method(name="Waivey", price=100, waive_at=370)
    source = BasketishOrderSource(get_default_shop())
    assert sm.get_effective_name(source) == u"Waivey"
    assert sm.get_total_cost(source).price == source.create_price(100)
    source.add_line(type=OrderLineType.PRODUCT,
                    product=get_default_product(),
                    base_unit_price=source.create_price(400),
                    quantity=1)
    assert sm.get_total_cost(source).price == source.create_price(0)
Esempio n. 15
0
def test_basket(rf):
    StoredBasket.objects.all().delete()
    quantities = [3, 12, 44, 23, 65]
    shop = get_default_shop()
    get_default_payment_method(
    )  # Can't create baskets without payment methods
    supplier = get_default_supplier()
    products_and_quantities = []
    for quantity in quantities:
        product = create_product(printable_gibberish(),
                                 shop=shop,
                                 supplier=supplier,
                                 default_price=50)
        products_and_quantities.append((product, quantity))

    for product, q in products_and_quantities:
        request = rf.get("/")
        request.session = {}
        request.shop = shop
        apply_request_middleware(request)
        basket = get_basket(request)
        assert basket == request.basket
        assert basket.product_count == 0
        line = basket.add_product(supplier=supplier,
                                  shop=shop,
                                  product=product,
                                  quantity=q)
        basket.shipping_method = get_shipping_method(
            shop=shop)  # For shippable product
        assert line.quantity == q
        assert basket.get_lines()
        assert basket.get_product_ids_and_quantities().get(product.pk) == q
        assert basket.product_count == q
        basket.save()
        delattr(request, "basket")
        basket = get_basket(request)
        assert basket.get_product_ids_and_quantities().get(product.pk) == q

        product_ids = set(StoredBasket.objects.last().products.values_list(
            "id", flat=True))
        assert product_ids == set([product.pk])

    stats = StoredBasket.objects.all().aggregate(
        n=Sum("product_count"),
        tfs=Sum("taxful_total_price_value"),
        tls=Sum("taxless_total_price_value"),
    )
    assert stats["n"] == sum(quantities)
    if shop.prices_include_tax:
        assert stats["tfs"] == sum(quantities) * 50
    else:
        assert stats["tls"] == sum(quantities) * 50
    basket.finalize()
Esempio n. 16
0
def test_fixed_cost_with_waiving_costs():
    sm = get_shipping_method(name="Fixed and waiving", price=5)

    sm.behavior_components.add(*[
        WaivingCostBehaviorComponent.objects.create(price_value=p,
                                                    waive_limit_value=w)
        for (p, w) in [(3, 5), (7, 10), (10, 30)]
    ])

    source = BasketishOrderSource(get_default_shop())
    source.shipping_method = sm

    def pricestr(pi):
        assert pi.price.unit_matches_with(source.create_price(0))
        return "%.0f EUR (%.0f EUR)" % (pi.price.value, pi.base_price.value)

    assert pricestr(sm.get_total_cost(source)) == "25 EUR (25 EUR)"
    assert source.total_price.value == 25

    source.add_line(type=OrderLineType.PRODUCT,
                    product=get_default_product(),
                    base_unit_price=source.create_price(2),
                    quantity=1)
    assert pricestr(sm.get_total_cost(source)) == "25 EUR (25 EUR)"
    assert source.total_price.value == 27

    source.add_line(type=OrderLineType.PRODUCT,
                    product=get_default_product(),
                    base_unit_price=source.create_price(3),
                    quantity=1)
    assert pricestr(sm.get_total_cost(source)) == "22 EUR (25 EUR)"
    assert source.total_price.value == 27

    source.add_line(type=OrderLineType.PRODUCT,
                    product=get_default_product(),
                    base_unit_price=source.create_price(10),
                    quantity=1)
    assert pricestr(sm.get_total_cost(source)) == "15 EUR (25 EUR)"
    assert source.total_price.value == 30

    source.add_line(type=OrderLineType.PRODUCT,
                    product=get_default_product(),
                    base_unit_price=source.create_price(10),
                    quantity=1)
    assert pricestr(sm.get_total_cost(source)) == "15 EUR (25 EUR)"
    assert source.total_price.value == 40

    source.add_line(type=OrderLineType.PRODUCT,
                    product=get_default_product(),
                    base_unit_price=source.create_price(10),
                    quantity=1)
    assert pricestr(sm.get_total_cost(source)) == "5 EUR (25 EUR)"
    assert source.total_price.value == 40
def test_category_products_effect_with_amount(rf):
    request, shop, group = initialize_test(rf, False)

    basket = get_basket(request)
    category = get_default_category()
    supplier = get_default_supplier()

    single_product_price = "50"
    discount_amount_value = "10"
    quantity = 5

    product = create_product("The product",
                             shop=shop,
                             supplier=supplier,
                             default_price=single_product_price)
    shop_product = product.get_shop_instance(shop)
    shop_product.categories.add(category)

    basket.add_product(supplier=supplier,
                       shop=shop,
                       product=product,
                       quantity=quantity)
    basket.shipping_method = get_shipping_method(shop=shop)
    basket.save()

    rule = CategoryProductsBasketCondition.objects.create(
        operator=ComparisonOperator.EQUALS, quantity=quantity)
    rule.categories.add(category)

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

    DiscountFromCategoryProducts.objects.create(
        campaign=campaign,
        category=category,
        discount_amount=discount_amount_value)

    assert rule.matches(basket, [])
    basket.uncache()
    final_lines = basket.get_final_lines()

    assert len(final_lines
               ) == 2  # no new lines since the effect touches original lines
    expected_discount_amount = quantity * basket.create_price(
        discount_amount_value)
    original_price = basket.create_price(single_product_price) * quantity
    line = final_lines[0]
    assert line.discount_amount == expected_discount_amount
    assert basket.total_price == original_price - expected_discount_amount
Esempio n. 18
0
def create_service(shop, line, tax_classes):
    assert line.quantity == 1 and line.discount == 0
    if line.is_payment:
        meth = get_payment_method(shop=shop,
                                  price=line.price,
                                  name=line.payment_name)
    elif line.is_shipping:
        meth = get_shipping_method(shop=shop,
                                   price=line.price,
                                   name=line.shipping_name)
    meth.tax_class = tax_classes[line.tax_name]
    meth.save()
    return meth
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,
            "billingAddress": _encode_address(contact.default_billing_address)
            if contact else {},
            "shippingAddress": _encode_address(
                contact.default_shipping_address) if contact else {},
        },
        "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
Esempio n. 20
0
def test_basket_category_discount(rf):
    """
    Test that discounting based on product category works.
    """

    request, shop, group = initialize_test(rf, False)
    price = shop.create_price

    basket = get_basket(request)
    supplier = get_default_supplier()

    category = CategoryFactory()

    discount_amount_value = 6
    single_product_price = 10

    def create_category_product(category):
        product = create_product(printable_gibberish(), shop, supplier, single_product_price)
        product.primary_category = category

        sp = ShopProduct.objects.get(product=product, shop=shop)
        sp.primary_category = category
        sp.categories.add(category)

        return product

    basket_condition = CategoryProductsBasketCondition.objects.create(quantity=2)
    basket_condition.categories.add(category)

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

    DiscountFromCategoryProducts.objects.create(
        campaign=campaign, discount_amount=discount_amount_value, category=category
    )
    basket.save()

    products = [create_category_product(category) for i in range(2)]
    for product in products:
        basket.add_product(supplier=supplier, shop=shop, product=product, quantity=1)
        basket.shipping_method = get_shipping_method(shop=shop)
    basket.save()

    assert basket.product_count == 2
    assert basket_condition.matches(basket=basket, lines=basket.get_lines())
    assert campaign.rules_match(basket, basket.get_lines())
    assert basket.total_price == price(single_product_price * 2) - price(discount_amount_value * 2)
Esempio n. 21
0
def test_productdiscountamount(rf):
    # Buy X amount of Y get Z discount from Y
    request, shop, _ = initialize_test(rf, False)

    basket = get_basket(request)
    supplier = get_default_supplier()

    single_product_price = "50"
    discount_amount_value = "10"
    quantity = 2

    # 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=quantity)
    basket.shipping_method = get_shipping_method(shop=shop)
    basket.save()

    rule = ProductsInBasketCondition.objects.create(quantity=2)
    rule.products.add(product)
    rule.save()

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

    effect = DiscountFromProduct.objects.create(
        campaign=campaign, discount_amount=discount_amount_value)
    effect.products.add(product)

    assert rule.matches(basket, [])
    basket.uncache()

    final_lines = basket.get_final_lines()

    assert len(final_lines
               ) == 2  # no new lines since the effect touches original lines
    expected_discount_amount = basket.create_price(discount_amount_value)
    original_price = basket.create_price(single_product_price) * quantity
    line = final_lines[0]
    assert line.discount_amount == expected_discount_amount
    assert basket.total_price == original_price - expected_discount_amount
Esempio n. 22
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", active=True)
    campaign.conditions.add(rule)
    campaign.save()

    BasketDiscountAmount.objects.create(discount_amount=discount_amount_value, campaign=campaign)

    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()]
Esempio n. 23
0
def test_basket_campaign_module_case1(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
    basket_rule1 = BasketTotalProductAmountCondition.objects.create(value="2")

    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.shipping_method = get_shipping_method(shop=shop)
    basket.save()

    assert basket.product_count == 1

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

    assert len(basket.get_final_lines()) == 2  # case 1
    assert basket.total_price == price(single_product_price)  # case 1

    basket.add_product(supplier=supplier, shop=shop, product=product, quantity=1)
    basket.save()

    assert len(basket.get_final_lines()) == 3  # case 1
    assert basket.product_count == 2
    assert basket.total_price == (price(single_product_price) * basket.product_count - price(discount_amount_value))
    assert OrderLineType.DISCOUNT in [l.type for l in basket.get_final_lines()]

    # Make sure disabling campaign disables it conditions
    assert campaign.conditions.filter(active=True).exists()
    campaign.active = False
    campaign.save()
    assert not campaign.conditions.filter(active=True).exists()
Esempio n. 24
0
def test_multiple_campaigns_match_with_coupon(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"
    product = create_product(printable_gibberish(), shop=shop, supplier=supplier, default_price=product_price)
    basket.add_product(supplier=supplier, shop=shop, product=product, quantity=1)
    basket.shipping_method = get_shipping_method(shop=shop)

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

    BasketDiscountAmount.objects.create(discount_amount=discount1, campaign=campaign)

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

    BasketDiscountAmount.objects.create(discount_amount=discount2, campaign=campaign2)

    basket.add_product(supplier=supplier, shop=shop, product=product, quantity=1)

    resp = handle_add_campaign_code(request, basket, dc.code)
    assert resp.get("ok")

    discount_lines_values = [line.discount_amount for line in basket.get_final_lines()]
    assert price(discount1) in discount_lines_values
    assert price(discount2) in discount_lines_values
    assert basket.total_price == (price(product_price) * basket.product_count - price(discount1) - price(discount2))
def test_category_product_in_basket_condition(rf):
    request, shop, group = initialize_test(rf, False)
    basket = get_basket(request)
    supplier = get_default_supplier()
    category = get_default_category()
    product = create_product("The Product",
                             shop=shop,
                             default_price="200",
                             supplier=supplier)
    basket.add_product(supplier=supplier,
                       shop=shop,
                       product=product,
                       quantity=1)
    basket.shipping_method = get_shipping_method(shop=shop)

    shop_product = product.get_shop_instance(shop)
    assert category not in shop_product.categories.all()

    condition = CategoryProductsBasketCondition.objects.create(
        operator=ComparisonOperator.EQUALS, quantity=1)
    condition.categories.add(category)

    # No match the product does not have the category
    assert not condition.matches(basket, [])

    shop_product.categories.add(category)
    assert condition.matches(basket, [])

    basket.add_product(supplier=supplier,
                       shop=shop,
                       product=product,
                       quantity=1)
    assert not condition.matches(basket, [])

    condition.operator = ComparisonOperator.GTE
    condition.save()

    assert condition.matches(basket, [])

    condition.excluded_categories.add(category)
    assert not condition.matches(basket, [])
Esempio n. 26
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)
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)
    basket.shipping_method = get_shipping_method(
        shop=shop)  # For shippable products

    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() == 3
    assert OrderLineType.DISCOUNT in [l.type for l in order.lines.all()]
    return order
Esempio n. 28
0
def test_multiple_campaigns_cheapest_price(rf):
    request, shop, group = initialize_test(rf, False)
    price = shop.create_price
    product_price = "100"
    discount_percentage = "0.30"
    discount_amount_value = "10"
    total_discount_amount = "50"

    expected_total = price(product_price) - (Decimal(discount_percentage) * price(product_price))
    matching_expected_total = price(product_price) - price(total_discount_amount)

    category = get_default_category()
    supplier = get_default_supplier()
    product = create_product(printable_gibberish(), shop=shop, supplier=supplier, default_price=product_price)
    shop_product = product.get_shop_instance(shop)
    shop_product.categories.add(category)

    # create catalog campaign
    catalog_filter = ProductFilter.objects.create()
    catalog_filter.products.add(product)
    catalog_campaign = CatalogCampaign.objects.create(shop=shop, active=True, name="test")
    catalog_campaign.filters.add(catalog_filter)

    cdp = ProductDiscountPercentage.objects.create(campaign=catalog_campaign, discount_percentage=discount_percentage)

    # create basket campaign
    condition = CategoryProductsBasketCondition.objects.create(operator=ComparisonOperator.EQUALS, quantity=1)
    condition.categories.add(category)
    basket_campaign = BasketCampaign.objects.create(shop=shop, public_name="test", name="test", active=True)
    basket_campaign.conditions.add(condition)

    effect = DiscountFromProduct.objects.create(campaign=basket_campaign, discount_amount=discount_amount_value)
    effect.products.add(product)

    # add product to basket
    basket = get_basket(request)
    basket.add_product(supplier=supplier, shop=shop, product=product, quantity=1)
    basket.shipping_method = get_shipping_method(shop=shop)
    final_lines = basket.get_final_lines()
    assert len(final_lines) == 2
    assert basket.total_price == expected_total

    effect.discount_amount = total_discount_amount
    effect.save()
    basket.uncache()
    catalog_campaign.save()  # save to bump caches
    basket_campaign.save()  # save to bump caches

    assert basket.total_price == matching_expected_total  # discount is now bigger than the original

    effect.delete()  # remove effect
    basket.uncache()
    catalog_campaign.save()  # save to bump caches
    basket_campaign.save()  # save to bump caches

    assert BasketLineEffect.objects.count() == 0

    assert basket.total_price == expected_total
    # add new effect
    effect = DiscountFromCategoryProducts.objects.create(category=category, campaign=basket_campaign, discount_amount=discount_amount_value)
    assert basket.total_price == expected_total

    effect.discount_amount = total_discount_amount
    effect.save()
    basket.uncache()
    catalog_campaign.save()  # save to bump caches
    basket_campaign.save()  # save to bump caches
    assert basket.total_price == matching_expected_total  # discount is now bigger than the original
Esempio n. 29
0
def test_discount_no_limits(rf, include_tax):
    # check whether is it possible to earn money buying from us
    # adding lots of effects
    request, shop, _ = initialize_test(rf, include_tax)

    basket = get_basket(request)
    supplier = get_default_supplier()

    single_product_price = Decimal(50)
    quantity = 4
    discount_amount = (single_product_price * quantity * 2)
    discount_percentage = Decimal(1.9)  # 190%

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

    # the expected discount amount should not be greater than the products
    expected_discount_amount = basket.create_price(
        single_product_price) * quantity

    category = CategoryFactory()

    # create basket rule that requires 2 products in basket
    product = create_product(printable_gibberish(),
                             shop=shop,
                             supplier=supplier,
                             default_price=single_product_price)
    ShopProduct.objects.get(shop=shop,
                            product=product).categories.add(category)
    basket.add_product(supplier=supplier,
                       shop=shop,
                       product=product,
                       quantity=quantity)
    basket.shipping_method = get_shipping_method(shop=shop)
    basket.save()

    rule = ProductsInBasketCondition.objects.create(quantity=2)
    rule.products.add(product)
    rule.save()

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

    # effect 1 - categories from products
    DiscountFromCategoryProducts.objects.create(
        campaign=campaign,
        discount_percentage=discount_percentage,
        category=category)

    # effect 2 - discount from products
    effect2 = DiscountFromProduct.objects.create(
        campaign=campaign, discount_amount=discount_amount)
    effect2.products.add(product)

    # effect 3 - basket discount
    BasketDiscountAmount.objects.create(campaign=campaign,
                                        discount_amount=discount_amount)

    # effect 4 - basket discount percetage
    BasketDiscountPercentage.objects.create(
        campaign=campaign, discount_percentage=discount_percentage)

    basket.uncache()

    final_lines = basket.get_final_lines()
    assert len(final_lines) == 3

    original_price = basket.create_price(single_product_price) * quantity
    line = final_lines[0]
    assert line.discount_amount == expected_discount_amount
    assert basket.total_price == original_price - expected_discount_amount

    # effect free - aaaww yes, it's free
    effect_free = FreeProductLine.objects.create(campaign=campaign, quantity=1)
    effect_free.products.add(second_product)

    basket.uncache()

    final_lines = basket.get_final_lines()
    assert len(final_lines) == 4
    line = final_lines[0]
    assert line.discount_amount == expected_discount_amount
    assert basket.total_price == original_price - expected_discount_amount

    # CatalogCampaign
    catalog_campaign = CatalogCampaign.objects.create(active=True,
                                                      shop=shop,
                                                      name="test2",
                                                      public_name="test")
    product_filter = ProductFilter.objects.create()
    product_filter.products.add(product)
    catalog_campaign.filters.add(product_filter)

    # effect 5 - ProductDiscountAmount
    ProductDiscountAmount.objects.create(campaign=catalog_campaign,
                                         discount_amount=discount_amount)

    # effct 6 - ProductDiscountPercentage
    ProductDiscountPercentage.objects.create(
        campaign=catalog_campaign, discount_percentage=discount_percentage)

    basket.uncache()

    final_lines = basket.get_final_lines()
    assert len(final_lines) == 4
    line = final_lines[0]
    assert line.discount_amount == expected_discount_amount
    assert basket.total_price == original_price - expected_discount_amount
Esempio n. 30
0
def test_undiscounted_effects(rf, include_tax):
    request, shop, _ = initialize_test(rf, include_tax)

    basket = get_basket(request)
    supplier = get_default_supplier()

    single_product_price = Decimal(50)
    discounted_product_quantity = 4
    normal_priced_product_quantity = 2
    discount_percentage = Decimal(0.2)  # 20%
    discount_amount = basket.create_price(single_product_price *
                                          normal_priced_product_quantity *
                                          discount_percentage)

    category = CategoryFactory()

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

    ShopProduct.objects.get(
        shop=shop, product=discounted_product).categories.add(category)
    ShopProduct.objects.get(shop=shop,
                            product=second_product).categories.add(category)
    basket.add_product(supplier=supplier,
                       shop=shop,
                       product=discounted_product,
                       quantity=discounted_product_quantity)
    basket.add_product(supplier=supplier,
                       shop=shop,
                       product=second_product,
                       quantity=normal_priced_product_quantity)
    basket.shipping_method = get_shipping_method(shop=shop)
    basket.save()

    # Store basket price before any campaigns exists
    original_price = basket.total_price

    # CatalogCampaign
    catalog_campaign = CatalogCampaign.objects.create(active=True,
                                                      shop=shop,
                                                      name="test",
                                                      public_name="test")
    # Limit catalog campaign to "discounted_product"
    product_filter = ProductFilter.objects.create()
    product_filter.products.add(discounted_product)
    catalog_campaign.filters.add(product_filter)

    # BasketCampaign
    campaign = BasketCampaign.objects.create(active=True,
                                             shop=shop,
                                             name="test2",
                                             public_name="test2")

    final_lines = basket.get_final_lines()
    assert len(final_lines) == 3

    # Discount based on undiscounted product values
    DiscountPercentageFromUndiscounted.objects.create(
        campaign=campaign, discount_percentage=discount_percentage)

    basket.uncache()
    final_lines = basket.get_final_lines()
    assert len(final_lines) == 4

    discounted_basket_price = original_price - discount_amount
    assert basket.total_price.as_rounded(
    ) == discounted_basket_price.as_rounded()