def test_campaign_all_rules_must_match1(rf): activate("en") discount_amount = "20.53" original_price = "199.20" request, shop, group = initialize_test(rf, False) cat = Category.objects.create(name="test") rule1 = ContactGroupCondition.objects.create() rule1.contact_groups = request.customer.groups.all() rule1.save() rule2 = CategoryFilter.objects.create() rule2.categories.add(cat) rule2.save() campaign = CatalogCampaign.objects.create(shop=shop, name="test", active=True) campaign.conditions.add(rule1) campaign.filters.add(rule2) campaign.save() ProductDiscountAmount.objects.create(campaign=campaign, discount_amount=discount_amount) product = create_product("Just-A-Product-Too", shop, default_price=original_price) price = shop.create_price # price should not be discounted because the request.category is faulty assert product.get_price_info(request, quantity=1).price == price(original_price) shop_product = product.get_shop_instance(shop) shop_product.categories.add(cat) shop_product.save() # now the category is set, so both rules match, disconut should be given assert product.get_price_info(request, quantity=1).price == (price(original_price) - price(discount_amount))
def test_campaign_creation(rf): activate("en") request, shop, group = initialize_test(rf, False) cat = Category.objects.create(name="test") condition = ContactGroupCondition.objects.create() condition.contact_groups = request.customer.groups.all() condition.save() assert condition.values.first() == request.customer.groups.first() condition.values = request.customer.groups.all() condition.save() assert condition.values.first() == request.customer.groups.first() category_filter = CategoryFilter.objects.create() category_filter.categories.add(cat) category_filter.save() campaign = CatalogCampaign.objects.create(shop=shop, name="test", discount_amount_value=20, active=True) campaign.conditions.add(condition) campaign.filters.add(category_filter) campaign.save()
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)
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()]
def test_coupon_uniqueness(rf): request, shop, group = initialize_test(rf, False) first_campaign = BasketCampaign.objects.create(active=True, shop=shop, name="test", public_name="test", discount_percentage="0.1", coupon=None) second_campaign = BasketCampaign.objects.create(active=True, shop=shop, name="test1", public_name="test1", discount_percentage="0.1", coupon=None) coupon = Coupon.objects.create(active=True, code="test_code") first_campaign.coupon = coupon first_campaign.save() first_form = BasketCampaignForm(instance=first_campaign, request=request) assert len(first_form.fields["coupon"].choices) == 2 # coupon + empty second_form = BasketCampaignForm(instance=second_campaign, request=request) assert len(second_form.fields["coupon"].choices) == 1 # only empty # Can't set coupon for second campaign since coupon is unique with pytest.raises(IntegrityError): second_campaign.coupon = coupon second_campaign.save()
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
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.save() assert basket.product_count == 1 campaign = BasketCampaign.objects.create( shop=shop, public_name="test", name="test", discount_amount_value=discount_amount_value, active=True) campaign.conditions.add(basket_rule1) campaign.save() assert len(basket.get_final_lines()) == 1 # 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()) == 2 # 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()]
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")
def test_campaign_with_non_active_coupon(rf): initial_status = get_initial_order_status() request, shop, group = initialize_test(rf, include_tax=False) order = _get_order_with_coupon(request, initial_status) coupon = order.coupon_usages.first().coupon coupon.active = False coupon.save() modifier = UserFactory() contact = create_random_person(locale="en_US", minimum_name_comp_len=5) assert order.customer != contact state = _get_frontend_order_state(shop, contact) assert order.shop.id == state["shop"]["selected"]["id"] request = get_frontend_request_for_command(state, "finalize", modifier) response = OrderEditView.as_view()(request, pk=order.pk) assert_contains(response, "orderIdentifier") data = json.loads(response.content.decode("utf8")) edited_order = Order.objects.get(pk=order.pk) assert edited_order.identifier == data[ "orderIdentifier"] == order.identifier assert edited_order.pk == order.pk assert edited_order.lines.count() == 3 assert OrderLineType.DISCOUNT not in [ l.type for l in edited_order.lines.all() ] assert edited_order.coupon_usages.count() == 0
def test_percentage_campaigns(rf): activate("en") discount_percentage = "0.14" original_price = "123.47" request, shop, group = initialize_test(rf, False) cat = Category.objects.create(name="test") rule1 = ContactGroupCondition.objects.create() rule1.contact_groups = request.customer.groups.all() rule1.save() rule2 = CategoryFilter.objects.create() rule2.categories.add(cat) rule2.save() campaign = CatalogCampaign.objects.create(shop=shop, name="test", active=True) campaign.conditions.add(rule1) campaign.filters.add(rule2) campaign.save() cdp = ProductDiscountPercentage.objects.create(campaign=campaign, discount_percentage=discount_percentage) product = create_product("Just-A-Product-Too", shop, default_price=original_price) price = shop.create_price # price should not be discounted because the request.category is faulty assert product.get_price_info(request, quantity=1).price == price(original_price) shop_product = product.get_shop_instance(shop) shop_product.categories.add(cat) shop_product.save() # now the category is set, so both rules match, discount should be given discounted_price = price(original_price) - (price(original_price) * Decimal(cdp.value)) assert product.get_price_info(request, quantity=1).price == discounted_price
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", active=True) campaign.conditions.add(rule1) campaign.filters.add(rule2) campaign.save() ProductDiscountAmount.objects.create(campaign=campaign, discount_amount=discount_amount) 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")
def test_coupon_uniqueness(rf): request, shop, group = initialize_test(rf, False) first_campaign = BasketCampaign.objects.create( active=True, shop=shop, name="test", public_name="test", discount_percentage="0.1", coupon=None) second_campaign = BasketCampaign.objects.create( active=True, shop=shop, name="test1", public_name="test1", discount_percentage="0.1", coupon=None) coupon = Coupon.objects.create(active=True, code="test_code") first_campaign.coupon = coupon first_campaign.save() first_form = BasketCampaignForm(instance=first_campaign, request=request) assert len(first_form.fields["coupon"].choices) == 2 # coupon + empty second_form = BasketCampaignForm(instance=second_campaign, request=request) assert len(second_form.fields["coupon"].choices) == 1 # only empty # Can't set coupon for second campaign since coupon is unique with pytest.raises(IntegrityError): second_campaign.coupon = coupon second_campaign.save()
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
def test_minimum_price_is_forced(rf): activate("en") discount_amount = "20.53" original_price = "199.20" allowed_minimum_price = "190.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", active=True) campaign.conditions.add(rule1) campaign.filters.add(rule2) campaign.save() ProductDiscountAmount.objects.create(campaign=campaign, discount_amount=discount_amount) 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.minimum_price = price(allowed_minimum_price) shop_product.save() # price should not be discounted because the request.category is faulty assert product.get_price_info(request, quantity=1).price == price(original_price) shop_product.categories.add(cat) shop_product.save() # now the category is set, so both rules match, discount should be given assert product.get_price_info(request, quantity=1).price == shop_product.minimum_price
def test_campaign_with_non_active_coupon(rf): initial_status = get_initial_order_status() request, shop, group = initialize_test(rf, include_tax=False) order = _get_order_with_coupon(request, initial_status) coupon = order.coupon_usages.first().coupon coupon.active = False coupon.save() modifier = UserFactory() contact = create_random_person(locale="en_US", minimum_name_comp_len=5) assert order.customer != contact state = _get_frontend_order_state(shop, contact) assert order.shop.id == state["shop"]["selected"]["id"] request = get_frontend_request_for_command(state, "finalize", modifier) response = OrderEditView.as_view()(request, pk=order.pk) assert_contains(response, "orderIdentifier") data = json.loads(response.content.decode("utf8")) edited_order = Order.objects.get(pk=order.pk) assert edited_order.identifier == data["orderIdentifier"] == order.identifier assert edited_order.pk == order.pk assert edited_order.lines.count() == 3 assert OrderLineType.DISCOUNT not in [l.type for l in edited_order.lines.all()] assert edited_order.coupon_usages.count() == 0
def test_order_creation_adds_usage(rf, admin_user): request, shop, group = initialize_test(rf, False) source = seed_source(admin_user) source.add_line( type=OrderLineType.PRODUCT, product=get_default_product(), supplier=get_default_supplier(), quantity=1, base_unit_price=source.create_price(10), ) source.add_line( type=OrderLineType.OTHER, quantity=1, base_unit_price=source.create_price(10), require_verification=True ) # add coupon coupon = Coupon.objects.create(active=True, code="asdf") campaign = BasketCampaign.objects.create( active=True, shop=shop, name="test", public_name="test", discount_percentage="0.1", coupon=coupon ) source.add_code(coupon.code) request = apply_request_middleware(rf.get("/")) creator = OrderCreator(request) order = creator.create_order(source) assert CouponUsage.objects.count() == 1
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_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)
def test_order_creation_adds_usage(rf, admin_user): request, shop, group = initialize_test(rf, False) source = seed_source(admin_user) source.add_line( type=OrderLineType.PRODUCT, product=get_default_product(), supplier=get_default_supplier(), quantity=1, base_unit_price=source.create_price(10), ) source.add_line( type=OrderLineType.OTHER, quantity=1, base_unit_price=source.create_price(10), require_verification=True, ) # add coupon coupon = Coupon.objects.create(active=True, code="asdf") BasketCampaign.objects.create(active=True, shop=shop, name="test", public_name="test", discount_percentage="0.1", coupon=coupon) source.add_code(coupon.code) creator = OrderCreator() creator.create_order(source) assert CouponUsage.objects.count() == 1
def test_only_best_price_affects(rf): activate("en") discount_amount = "20.53" original_price = "199.20" best_discount_amount = "40.00" 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() rule3, rule4 = create_condition_and_filter(cat, request) campaign = CatalogCampaign.objects.create(shop=shop, name="test", discount_amount_value=best_discount_amount, active=True) campaign.conditions.add(rule3) campaign.filters.add(rule4) campaign.save() product = create_product("Just-A-Product-Too", shop, default_price=original_price) price = shop.create_price # price should not be discounted because the request.category is faulty assert product.get_price_info(request, quantity=1).price == price(original_price) shop_product = product.get_shop_instance(shop) shop_product.categories.add(cat) shop_product.save() # now the category is set, so both rules match, discount should be given assert product.get_price_info(request, quantity=1).price == (price(original_price) - price(best_discount_amount))
def test_campaign_save_validation(rf): # Discount percentage, or Discount amount in shop currency request, shop, group = initialize_test(rf, False) with pytest.raises(ValidationError): campaign = CatalogCampaign.objects.create(shop=shop, name="test", discount_amount_value="20", discount_percentage="0.20") with pytest.raises(ValidationError): campaign = CatalogCampaign.objects.create(shop=shop, name="test")
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
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) 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_condition_doesnt_match(rf): activate("en") request, shop, group = initialize_test(rf, False) condition = ContactGroupCondition.objects.create() condition.contact_groups = [get_default_customer_group()] condition.save() request.customer = None assert not condition.matches(request)
def test_condition_doesnt_match(rf): activate("en") request, shop, group = initialize_test(rf, False) condition = ContactGroupCondition.objects.create() condition.contact_groups = [get_default_customer_group()] condition.save() request.customer = None assert not condition.matches(request)
def test_campaign_with_coupons(rf): 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) 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=2) campaign.conditions.add(rule) campaign.save() assert len(basket.get_final_lines() ) == 2 # no discount was applied because coupon is required basket.add_code(dc.code) assert len(basket.get_final_lines() ) == 3 # now basket has codes so they will be applied too assert OrderLineType.DISCOUNT in [l.type for l in basket.get_final_lines()] # Ensure codes persist between requests, so do what the middleware would, i.e. basket.save() # and then reload the basket: del request.basket basket = get_basket(request) assert basket.codes == [dc.code] assert len(basket.get_final_lines() ) == 3 # now basket has codes so they will be applied too assert OrderLineType.DISCOUNT in [l.type for l in basket.get_final_lines()] basket.status = status creator = OrderCreator(request) order = creator.create_order(basket) assert CouponUsage.objects.filter(order=order).count() == 1 assert CouponUsage.objects.filter(order=order, coupon__code=dc.code).count() == 1
def test_availability(rf): activate("en") 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=False) campaign.conditions.add(rule1) campaign.save() assert not campaign.is_available()
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) discount_amount = 20 campaign = CatalogCampaign.objects.create(shop=shop, name="test", active=True) campaign.conditions.add(rule1) campaign.save() ProductDiscountAmount.objects.create(discount_amount=discount_amount, campaign=campaign) 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)
def test_campaign_save_validation(rf): # Discount percentage, or Discount amount in shop currency request, shop, group = initialize_test(rf, False) with pytest.raises(ValidationError): campaign = CatalogCampaign.objects.create(shop=shop, name="test", discount_amount_value="20", discount_percentage="0.20") with pytest.raises(ValidationError): campaign = CatalogCampaign.objects.create(shop=shop, name="test")
def test_availability(rf): activate("en") 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=False) campaign.conditions.add(rule1) campaign.save() assert not campaign.is_available()
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.save() assert basket.product_count == 1 campaign = BasketCampaign.objects.create( shop=shop, public_name="test", name="test", discount_amount_value=discount_amount_value, active=True) campaign.conditions.add(basket_rule1) campaign.save() assert len(basket.get_final_lines()) == 1 # 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()) == 2 # 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()]
def test_basket_total_amount_condition(rf): request, shop, group = initialize_test(rf, False) basket = get_basket(request) supplier = get_default_supplier() product = create_product("Just-A-Product-Too", shop, default_price="200") basket.add_product(supplier=supplier, shop=shop, product=product, quantity=1) condition = BasketTotalAmountCondition.objects.create() condition.value = 1 condition.save() assert condition.value == 1 assert condition.matches(basket, [])
def test_basket_total_value_condition(rf): request, shop, group = initialize_test(rf, False) basket = get_basket(request) supplier = get_default_supplier() product = create_product("Just-A-Product-Too", shop, default_price="200") basket.add_product(supplier=supplier, shop=shop, product=product, quantity=1) condition = BasketTotalProductAmountCondition.objects.create() condition.value = 1 condition.save() assert condition.value == 1 assert condition.matches(basket, []) assert "basket has at least the product count entered here" in force_text(condition.description)
def test_basket_total_amount_condition(rf): request, shop, group = initialize_test(rf, False) price = shop.create_price basket = get_basket(request) supplier = get_default_supplier() product = create_product("Just-A-Product-Too", shop, default_price="200") basket.add_product(supplier=supplier, shop=shop, product=product, quantity=1) condition = BasketTotalAmountCondition.objects.create() condition.value = 1 condition.save() assert condition.value == 1 assert condition.matches(basket, [])
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) 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()) == 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)
def test_basket_total_value_condition(rf): request, shop, group = initialize_test(rf, False) price = shop.create_price basket = get_basket(request) supplier = get_default_supplier() product = create_product("Just-A-Product-Too", shop, default_price="200") basket.add_product(supplier=supplier, shop=shop, product=product, quantity=1) condition = BasketTotalProductAmountCondition.objects.create() condition.value = 1 condition.save() assert condition.value == 1 assert condition.matches(basket, []) assert "basket has atleast the product count entered here" in force_text(condition.description)
def test_product_in_basket_condition(rf): request, shop, group = initialize_test(rf, False) basket = get_basket(request) supplier = get_default_supplier() product = create_product("Just-A-Product-Too", shop, default_price="200") basket.add_product(supplier=supplier, shop=shop, product=product, quantity=1) condition = ProductsInBasketCondition.objects.create() condition.values = [product] condition.save() assert condition.values.first() == product assert condition.matches(basket, [])
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 atleast value of 200 rule = BasketTotalAmountCondition.objects.create(value="200") single_product_price = "50" discount_amount_value = "10" unique_shipping_method = ShippingMethod(tax_class=get_default_tax_class(), module_data={"price": 50}) unique_shipping_method.save() 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()]
def test_only_best_price_affects(rf): activate("en") discount_amount = "20.53" original_price = "199.20" best_discount_amount = "40.00" 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() rule3, rule4 = create_condition_and_filter(cat, request) campaign = CatalogCampaign.objects.create( shop=shop, name="test", discount_amount_value=best_discount_amount, active=True) campaign.conditions.add(rule3) campaign.filters.add(rule4) campaign.save() product = create_product("Just-A-Product-Too", shop, default_price=original_price) price = shop.create_price # price should not be discounted because the request.category is faulty assert product.get_price_info(request, quantity=1).price == price(original_price) shop_product = product.get_shop_instance(shop) shop_product.categories.add(cat) shop_product.save() # now the category is set, so both rules match, disconut should be given assert product.get_price_info( request, quantity=1).price == (price(original_price) - price(best_discount_amount))
def test_condition_affects_price(rf): activate("en") request, shop, group = initialize_test(rf, False) cat = Category.objects.create(name="test") contact_condition = ContactGroupCondition.objects.create() contact_condition.contact_groups = request.customer.groups.all() contact_condition.save() campaign = CatalogCampaign.objects.create(shop=shop, name="test", discount_amount_value=20, active=True) campaign.conditions.add(contact_condition) campaign.save() price = shop.create_price product = create_product("Just-A-Product-Too", shop, default_price=199) assert product.get_price_info(request, quantity=1).price == price(179)
def test_product_in_basket_condition(rf): request, shop, group = initialize_test(rf, False) price = shop.create_price basket = get_basket(request) supplier = get_default_supplier() product = create_product("Just-A-Product-Too", shop, default_price="200") basket.add_product(supplier=supplier, shop=shop, product=product, quantity=1) condition = ProductsInBasketCondition.objects.create() condition.values = [product] condition.save() assert condition.values.first() == product assert condition.matches(basket, [])
def test_product_filter(rf): request, shop, group = initialize_test(rf, False) product = create_product("Just-A-Product-Too", shop, default_price="200") product_filter = ProductFilter.objects.create() product_filter.products.add(product) product_filter.save() assert product_filter.values.first() == product product2 = create_product("asdfasf", shop, default_price="20") product_filter.values = [product, product2] product_filter.save() assert product_filter.values.count() == 2 assert product_filter.filter_queryset(ShopProduct.objects.all()).exists() # filter matches
def test_campaign_with_coupons(rf): 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) 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=2) campaign.conditions.add(rule) campaign.save() assert len(basket.get_final_lines()) == 2 # no discount was applied because coupon is required basket.add_code(dc.code) assert len(basket.get_final_lines()) == 3 # now basket has codes so they will be applied too assert OrderLineType.DISCOUNT in [l.type for l in basket.get_final_lines()] # Ensure codes persist between requests, so do what the middleware would, i.e. basket.save() # and then reload the basket: del request.basket basket = get_basket(request) assert basket.codes == [dc.code] assert len(basket.get_final_lines()) == 3 # now basket has codes so they will be applied too assert OrderLineType.DISCOUNT in [l.type for l in basket.get_final_lines()] basket.status = status creator = OrderCreator(request) order = creator.create_order(basket) assert CouponUsage.objects.filter(order=order).count() == 1 assert CouponUsage.objects.filter(order=order, coupon__code=dc.code).count() == 1
def test_filter_affects_price(rf): activate("en") request, shop, group = initialize_test(rf, False) cat = Category.objects.create(name="test") category_filter = CategoryFilter.objects.create() category_filter.categories.add(cat) category_filter.save() campaign = CatalogCampaign.objects.create(shop=shop, name="test", discount_amount_value=20, active=True) campaign.filters.add(category_filter) campaign.save() price = shop.create_price product = create_product("Just-A-Product-Too", shop, default_price=199) 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(179)
def test_product_filter(rf): request, shop, group = initialize_test(rf, False) product = create_product("Just-A-Product-Too", shop, default_price="200") product_filter = ProductFilter.objects.create() product_filter.products.add(product) product_filter.save() assert product_filter.values.first() == product product2 = create_product("asdfasf", shop, default_price="20") product_filter.values = [product, product2] product_filter.save() assert product_filter.values.count() == 2 assert product_filter.filter_queryset( ShopProduct.objects.all()).exists() # filter matches
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
def test_product_type_filter(rf): request, shop, group = initialize_test(rf, False) product = create_product("Just-A-Product-Too", shop, default_price="200") product_type_filter = ProductTypeFilter.objects.create() product_type_filter.product_types.add(product.type) product_type_filter.save() assert product_type_filter.values.first() == product.type product2 = create_product("asdfasf", shop, default_price="20") product_type_filter.values = [product.type, product2.type] product_type_filter.save() assert product_type_filter.values.count() == 1 # both have same product type so only 1 value here assert product_type_filter.filter_queryset(ShopProduct.objects.all()).exists() # filter matches assert product_type_filter.name.lower() in force_text(product_type_filter.description)
def test_condition_affects_price(rf): activate("en") request, shop, group = initialize_test(rf, False) cat = Category.objects.create(name="test") contact_condition = ContactGroupCondition.objects.create() contact_condition.contact_groups = request.customer.groups.all() contact_condition.save() campaign = CatalogCampaign.objects.create(shop=shop, name="test", discount_amount_value=20, active=True) campaign.conditions.add(contact_condition) campaign.save() price = shop.create_price product = create_product("Just-A-Product-Too", shop, default_price=199) assert product.get_price_info(request, quantity=1).price == price(179)
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) 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_campaign_all_rules_must_match1(rf): activate("en") discount_amount = "20.53" original_price = "199.20" request, shop, group = initialize_test(rf, False) cat = Category.objects.create(name="test") rule1 = ContactGroupCondition.objects.create() rule1.contact_groups = request.customer.groups.all() rule1.save() rule2 = CategoryFilter.objects.create() rule2.categories.add(cat) rule2.save() 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() product = create_product("Just-A-Product-Too", shop, default_price=original_price) price = shop.create_price # price should not be discounted because the request.category is faulty assert product.get_price_info(request, quantity=1).price == price(original_price) shop_product = product.get_shop_instance(shop) shop_product.categories.add(cat) shop_product.save() # now the category is set, so both rules match, disconut should be given assert product.get_price_info(request, quantity=1).price == (price(original_price) - price(discount_amount))
def test_percentage_campaigns(rf): activate("en") discount_percentage = "0.14" original_price = "123.47" request, shop, group = initialize_test(rf, False) cat = Category.objects.create(name="test") rule1 = ContactGroupCondition.objects.create() rule1.contact_groups = request.customer.groups.all() rule1.save() rule2 = CategoryFilter.objects.create() rule2.categories.add(cat) rule2.save() campaign = CatalogCampaign.objects.create( shop=shop, name="test", discount_percentage=discount_percentage, active=True) campaign.conditions.add(rule1) campaign.filters.add(rule2) campaign.save() product = create_product("Just-A-Product-Too", shop, default_price=original_price) price = shop.create_price # price should not be discounted because the request.category is faulty assert product.get_price_info(request, quantity=1).price == price(original_price) shop_product = product.get_shop_instance(shop) shop_product.categories.add(cat) shop_product.save() # now the category is set, so both rules match, discount should be given discounted_price = price(original_price) - ( price(original_price) * Decimal(campaign.discount_percentage)) assert product.get_price_info(request, quantity=1).price == discounted_price
def test_campaign_creation(rf): activate("en") request, shop, group = initialize_test(rf, False) cat = Category.objects.create(name="test") condition = ContactGroupCondition.objects.create() condition.contact_groups = request.customer.groups.all() condition.save() assert condition.values.first() == request.customer.groups.first() condition.values = request.customer.groups.all() condition.save() assert condition.values.first() == request.customer.groups.first() category_filter = CategoryFilter.objects.create() category_filter.categories.add(cat) category_filter.save() campaign = CatalogCampaign.objects.create(shop=shop, name="test", discount_amount_value=20, active=True) campaign.conditions.add(condition) campaign.filters.add(category_filter) campaign.save()
def test_filter_affects_price(rf): activate("en") request, shop, group = initialize_test(rf, False) cat = Category.objects.create(name="test") category_filter = CategoryFilter.objects.create() category_filter.categories.add(cat) category_filter.save() campaign = CatalogCampaign.objects.create(shop=shop, name="test", discount_amount_value=20, active=True) campaign.filters.add(category_filter) campaign.save() price = shop.create_price product = create_product("Just-A-Product-Too", shop, default_price=199) 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(179)
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) 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()) == 2 assert basket.product_count == 1 assert basket.total_price == expected_discounted_price
def test_product_type_filter(rf): request, shop, group = initialize_test(rf, False) product = create_product("Just-A-Product-Too", shop, default_price="200") product_type_filter = ProductTypeFilter.objects.create() product_type_filter.product_types.add(product.type) product_type_filter.save() assert product_type_filter.values.first() == product.type product2 = create_product("asdfasf", shop, default_price="20") product_type_filter.values = [product.type, product2.type] product_type_filter.save() assert product_type_filter.values.count( ) == 1 # both have same product type so only 1 value here assert product_type_filter.filter_queryset( ShopProduct.objects.all()).exists() # filter matches assert product_type_filter.name.lower() in force_text( product_type_filter.description)
def test_admin_order_with_campaign(rf, admin_user): request, shop, group = initialize_test(rf, False) customer = request.customer cat = Category.objects.create(name="test") rule1, rule2 = create_condition_and_filter(cat, request) campaign = CatalogCampaign.objects.create(shop=shop, name="test", active=True) campaign.conditions.add(rule1) ProductDiscountAmount.objects.create(campaign=campaign, discount_amount="10") product = create_product("Just-A-Product-Too", shop, default_price=20) shop_product = product.get_shop_instance(shop) shop_product.categories.add(cat) request = apply_request_middleware(rf.get("/", { "command": "product_data", "shop_id": shop.id, "customer_id": customer.id, "id": product.id, "quantity": 1 }), user=admin_user) response = OrderEditView.as_view()(request) data = json.loads(response.content.decode("utf8")) assert decimal.Decimal(data['unitPrice']['value']) == shop.create_price(10).value