def test_custom_payment_processor_cash_service(choice_identifier, expected_payment_status): shop = get_default_shop() product = get_default_product() supplier = get_default_supplier() processor = CustomPaymentProcessor.objects.create() payment_method = PaymentMethod.objects.create( shop=shop, payment_processor=processor, choice_identifier=choice_identifier, tax_class=get_default_tax_class()) order = create_order_with_product( product=product, supplier=supplier, quantity=1, taxless_base_unit_price=Decimal('5.55'), shop=shop) order.taxful_total_price = TaxfulPrice(Decimal('5.55'), u'EUR') order.payment_method = payment_method order.save() assert order.payment_status == PaymentStatus.NOT_PAID processor.process_payment_return_request(choice_identifier, order, None) assert order.payment_status == expected_payment_status processor.process_payment_return_request(choice_identifier, order, None) assert order.payment_status == expected_payment_status
def test_order_package_children_taxes(): """ Test OrderCreator creates package parent links for child lines. """ tax_class = get_default_tax_class() tax = Tax.objects.create(rate='0.25', name="Da Tax") TaxRule.objects.create(tax=tax).tax_classes.add(tax_class) source = get_order_source_with_a_package() assert source.get_lines()[0].tax_class == tax_class order = OrderCreator().create_order(source) lines_and_taxes = [] for line in order.lines.all(): lines_and_taxes.append(prettify_order_line(line)) for line_tax in line.taxes.all(): lines_and_taxes.append(' %s' % (line_tax,)) assert lines_and_taxes == [ '#0 10 x PackageParent', ' Da Tax: 20.000000000 EUR on 80.000000000 EUR', '#1 10 x PackageChild-0, child of #0', '#2 20 x PackageChild-1, child of #0', '#3 30 x PackageChild-2, child of #0', '#4 40 x PackageChild-3, child of #0', ]
def test_order_package_children_taxes(): """ Test OrderCreator creates package parent links for child lines. """ tax_class = get_default_tax_class() tax = Tax.objects.create(rate='0.25', name="Da Tax") TaxRule.objects.create(tax=tax).tax_classes.add(tax_class) source = get_order_source_with_a_package() assert source.get_lines()[0].tax_class == tax_class order = OrderCreator().create_order(source) lines_and_taxes = [] for line in order.lines.all(): lines_and_taxes.append(prettify_order_line(line)) for line_tax in line.taxes.all(): lines_and_taxes.append(' %s' % (line_tax, )) assert lines_and_taxes == [ '#0 10 x PackageParent', ' Da Tax: 20.000000000 EUR on 80.000000000 EUR', '#1 10 x PackageChild-0, child of #0', '#2 20 x PackageChild-1, child of #0', '#3 30 x PackageChild-2, child of #0', '#4 40 x PackageChild-3, child of #0', ]
def test_method_creation(rf, admin_user, view, model, service_provider_attr, get_provider): """ To make things little bit more simple let's use only english as an language. """ with override_settings(LANGUAGES=[("en", "en")]): view = view.as_view() service_provider_field = "base-%s" % service_provider_attr data = { service_provider_field: get_provider().id, "base-choice_identifier": "manual", "base-name__en": "Custom method", "base-shop": get_default_shop().id, "base-tax_class": get_default_tax_class().id, "base-enabled": True, } # Default provider CustomCarrier/CustomPaymentProcessor should be set in form init methods_before = model.objects.count() url = "/?provider=%s" % get_provider().id request = apply_request_middleware(rf.post(url, data=data), user=admin_user) response = view(request, pk=None) if hasattr(response, "render"): response.render() assert response.status_code in [200, 302] assert model.objects.count() == (methods_before + 1)
def test_weight_limits(): sm = ShippingMethod(tax_class=get_default_tax_class()) sm.module_data = {"min_weight": "100", "max_weight": "500"} source = BasketishOrderSource(get_default_shop()) assert any(ve.code == "min_weight" for ve in sm.get_validation_errors(source)) source.add_line(type=OrderLineType.PRODUCT, weight=600) assert any(ve.code == "max_weight" for ve in sm.get_validation_errors(source))
def test_limited_methods(): """ Test that products can declare that they limit available shipping methods. """ unique_shipping_method = ShippingMethod(tax_class=get_default_tax_class(), module_data={"price": 0}) unique_shipping_method.save() 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 test_method_creation(rf, admin_user, view, model, service_provider_attr, get_provider): """ To make things little bit more simple let's use only english as an language. """ with override_settings(LANGUAGES=[("en", "en")]): view = view.as_view() service_provider_field = "base-%s" % service_provider_attr data = { service_provider_field: get_provider().id, "base-choice_identifier": "manual", "base-name__en": "Custom method", "base-shop": get_default_shop().id, "base-tax_class": get_default_tax_class().id, "base-enabled": True, } # Default provider CustomCarrier/CustomPaymentProcessor should be set in form init methods_before = model.objects.count() url = "/?provider=%s" % get_provider().id request = apply_request_middleware(rf.post(url, data=data), user=admin_user) response = view(request, pk=None) if hasattr(response, "render"): response.render() assert response.status_code in [200, 302] assert model.objects.count() == (methods_before + 1)
def test_process_payment_return_request(rf): """ Order payment with default payment method with ``CustomPaymentProcessor`` should be deferred. Payment can't be processed if method doesn't have provider or provider is not enabled or payment method is not enabled. """ pm = PaymentMethod.objects.create( shop=get_default_shop(), name="Test method", enabled=False, tax_class=get_default_tax_class()) order = create_empty_order() order.payment_method = pm order.save() assert order.payment_status == PaymentStatus.NOT_PAID with pytest.raises(ValueError): # Can't process payment with unusable method order.payment_method.process_payment_return_request(order, rf.get("/")) assert order.payment_status == PaymentStatus.NOT_PAID pm.payment_processor = get_custom_payment_processor() pm.payment_processor.enabled = False pm.save() with pytest.raises(ValueError): # Can't process payment with unusable method order.payment_method.process_payment_return_request(order, rf.get("/")) assert order.payment_status == PaymentStatus.NOT_PAID pm.payment_processor.enabled = True pm.save() with pytest.raises(ValueError): # Can't process payment with unusable method order.payment_method.process_payment_return_request(order, rf.get("/")) assert order.payment_status == PaymentStatus.NOT_PAID pm.enabled = True pm.save() order.payment_method.process_payment_return_request(order, rf.get("/")) assert order.payment_status == PaymentStatus.DEFERRED
def test_weight_limits(): sm = ShippingMethod(tax_class=get_default_tax_class()) sm.module_data = {"min_weight": "100", "max_weight": "500"} source = BasketishOrderSource(get_default_shop()) assert any(ve.code == "min_weight" for ve in sm.get_validation_errors(source)) source.add_line(type=OrderLineType.PRODUCT, weight=600) assert any(ve.code == "max_weight" for ve in sm.get_validation_errors(source))
def get_expensive_sweden_shipping_method(): sm = ShippingMethod( identifier=ExpensiveSwedenShippingModule.identifier, module_identifier=ExpensiveSwedenShippingModule.identifier, tax_class=get_default_tax_class(), ) sm.module_data = {"min_weight": "0.11000000", "max_weight": "3.00000000", "price_waiver_product_minimum": "370"} sm.save() return sm
def test_service_methods_with_long_name(rf): """ Make sure that service methods with long names (up to the max length of shipping or payment method names) don't cause exceptions when creating an order. """ MAX_LENGTH = 100 long_name = "X" * MAX_LENGTH assert len(long_name) == MAX_LENGTH sm = ShippingMethod.objects.language("en").create( shop=get_default_shop(), name=long_name, enabled=True, tax_class=get_default_tax_class()) pm = PaymentMethod.objects.language("en").create( shop=get_default_shop(), name=long_name, enabled=True, tax_class=get_default_tax_class()) order = create_empty_order() order.shipping_method = sm order.payment_method = pm order.full_clean() order.save()
def _get_payment_method_with_phase(): processor = PaymentWithCheckoutPhase.objects.create( identifier="processor_with_phase", enabled=True) assert isinstance(processor, PaymentWithCheckoutPhase) return processor.create_service(None, identifier="payment_with_phase", shop=get_default_shop(), name="Test method with phase", enabled=True, tax_class=get_default_tax_class())
def _get_shipping_method_with_phase(): carrier = CarrierWithCheckoutPhase.objects.create( identifier="carrier_with_phase", enabled=True) assert isinstance(carrier, CarrierWithCheckoutPhase) return carrier.create_service(None, identifier="carrier_with_phase", shop=get_default_shop(), name="Test method with phase", enabled=True, tax_class=get_default_tax_class())
def test_methods(admin_user, country): contact = get_person_contact(admin_user) source = BasketishOrderSource( lines=[ SourceLine( type=OrderLineType.PRODUCT, product=get_default_product(), supplier=get_default_supplier(), quantity=1, unit_price=TaxlessPrice(10), weight=Decimal("0.2"), ) ] ) billing_address = get_address() shipping_address = get_address(name="Shippy Doge", country=country) source.shop = get_default_shop() source.billing_address = billing_address source.shipping_address = shipping_address source.customer = contact with override_provides_for_expensive_sweden_shipping_method(): source.shipping_method = get_expensive_sweden_shipping_method() source.payment_method = PaymentMethod.objects.create( identifier="neat", module_data={"price": 4}, tax_class=get_default_tax_class() ) assert source.shipping_method_id assert source.payment_method_id errors = list(source.get_validation_errors()) if ( country == "FI" ): # "Expenseefe-a Svedee Sheepping" will not allow shipping to Finland, let's see if that holds true assert any([ve.code == "we_no_speak_finnish" for ve in errors]) return # Shouldn't try the rest if we got an error here else: assert not errors final_lines = list(source.get_final_lines()) assert any(line.type == OrderLineType.SHIPPING for line in final_lines) # TODO: (TAX) for some reason SourceLine.taxless_total_price property has been removed # I think it should be implemented back like in OrderLine / janne for line in final_lines: if line.type == OrderLineType.SHIPPING: if country == "SE": # We _are_ using Expenseefe-a Svedee Sheepping after all. assert line.taxless_total_price == TaxlessPrice("5.00") else: assert line.taxless_total_price == TaxlessPrice("4.00") assert line.text == u"Expenseefe-a Svedee Sheepping" if line.type == OrderLineType.PAYMENT: assert line.taxless_total_price == TaxlessPrice("4")
def _get_payment_method_with_phase(): processor = PaymentWithCheckoutPhase.objects.create( identifier="processor_with_phase", enabled=True) assert isinstance(processor, PaymentWithCheckoutPhase) return processor.create_service( None, identifier="payment_with_phase", shop=get_default_shop(), name="Test method with phase", enabled=True, tax_class=get_default_tax_class())
def _get_shipping_method_with_phase(): carrier = CarrierWithCheckoutPhase.objects.create( identifier="carrier_with_phase", enabled=True) assert isinstance(carrier, CarrierWithCheckoutPhase) return carrier.create_service( None, identifier="carrier_with_phase", shop=get_default_shop(), name="Test method with phase", enabled=True, tax_class=get_default_tax_class())
def get_expensive_sweden_shipping_method(): sm = ShippingMethod( identifier=ExpensiveSwedenShippingModule.identifier, module_identifier=ExpensiveSwedenShippingModule.identifier, tax_class=get_default_tax_class()) sm.module_data = { "min_weight": "0.11000000", "max_weight": "3.00000000", "price_waiver_product_minimum": "370" } sm.save() return sm
def test_weight_limits(): carrier = CustomCarrier.objects.create() sm = carrier.create_service( None, shop=get_default_shop(), enabled=True, tax_class=get_default_tax_class()) sm.behavior_components.add( WeightLimitsBehaviorComponent.objects.create( min_weight=100, max_weight=500)) source = BasketishOrderSource(get_default_shop()) assert any(ve.code == "min_weight" for ve in sm.get_unavailability_reasons(source)) source.add_line(type=OrderLineType.PRODUCT, weight=600) assert any(ve.code == "max_weight" for ve in sm.get_unavailability_reasons(source))
def get_expensive_sweden_shipping_method(): carrier = CustomCarrier.objects.create(name="Sveede Sheep") sm = carrier.create_service( None, shop=get_default_shop(), enabled=True, tax_class=get_default_tax_class(), name="Expenseefe-a Svedee Sheepping") sm.behavior_components.add( ExpensiveSwedenBehaviorComponent.objects.create(), WeightLimitsBehaviorComponent.objects.create( min_weight="0.11", max_weight="3"), ) return sm
def test_waiver(): sm = ShippingMethod( name="Waivey", tax_class=get_default_tax_class(), module_data={"price_waiver_product_minimum": "370", "price": "100"}, ) source = BasketishOrderSource() assert not source.prices_include_tax() assert sm.get_effective_name(source) == u"Waivey" assert sm.get_effective_price(source) == TaxlessPrice(100) source.lines = [ SourceLine(type=OrderLineType.PRODUCT, product=get_default_product(), unit_price=TaxlessPrice(400), quantity=1) ] assert sm.get_effective_price(source) == TaxlessPrice(0)
def test_methods(admin_user, country): contact = get_person_contact(admin_user) source = BasketishOrderSource(lines=[ SourceLine(type=OrderLineType.PRODUCT, product=get_default_product(), supplier=get_default_supplier(), quantity=1, unit_price=TaxlessPrice(10), weight=Decimal("0.2")) ]) billing_address = get_address() shipping_address = get_address(name="Shippy Doge", country=country) source.shop = get_default_shop() source.billing_address = billing_address source.shipping_address = shipping_address source.customer = contact with override_provides_for_expensive_sweden_shipping_method(): source.shipping_method = get_expensive_sweden_shipping_method() source.payment_method = PaymentMethod.objects.create( identifier="neat", module_data={"price": 4}, tax_class=get_default_tax_class()) assert source.shipping_method_id assert source.payment_method_id errors = list(source.get_validation_errors()) if country == "FI": # "Expenseefe-a Svedee Sheepping" will not allow shipping to Finland, let's see if that holds true assert any([ve.code == "we_no_speak_finnish" for ve in errors]) return # Shouldn't try the rest if we got an error here else: assert not errors final_lines = list(source.get_final_lines()) assert any(line.type == OrderLineType.SHIPPING for line in final_lines) # TODO: (TAX) for some reason SourceLine.taxless_total_price property has been removed # I think it should be implemented back like in OrderLine / janne for line in final_lines: if line.type == OrderLineType.SHIPPING: if country == "SE": # We _are_ using Expenseefe-a Svedee Sheepping after all. assert line.taxless_total_price == TaxlessPrice("5.00") else: assert line.taxless_total_price == TaxlessPrice("4.00") assert line.text == u"Expenseefe-a Svedee Sheepping" if line.type == OrderLineType.PAYMENT: assert line.taxless_total_price == TaxlessPrice("4")
def test_waiver(): sm = ShippingMethod(name="Waivey", tax_class=get_default_tax_class(), module_data={ "price_waiver_product_minimum": "370", "price": "100" }) source = BasketishOrderSource(get_default_shop()) assert sm.get_effective_name(source) == u"Waivey" assert sm.get_effective_price_info(source).price == source.shop.create_price(100) source.add_line( type=OrderLineType.PRODUCT, product=get_default_product(), base_unit_price=source.shop.create_price(400), quantity=1 ) assert sm.get_effective_price_info(source).price == source.shop.create_price(0)
def test_tax_edit_view_works_at_all(rf, admin_user): get_default_shop() # We need a shop to exists request = apply_request_middleware(rf.get("/")) request.user = admin_user default_tax_class = get_default_tax_class() with replace_modules([TaxModule]): with admin_only_urls(): view_func = TaxClassEditView.as_view() response = view_func(request, pk=default_tax_class.pk) response.render() assert (default_tax_class.name in force_text(response.content)) response = view_func(request, pk=None) # "new mode" response.render() assert response.content
def test_tax_edit_view_works_at_all(rf, admin_user): get_default_shop() # We need a shop to exists request = apply_request_middleware(rf.get("/")) request.user = admin_user default_tax_class = get_default_tax_class() with replace_modules([TaxModule]): with admin_only_urls(): view_func = TaxClassEditView.as_view() response = view_func(request, pk=default_tax_class.pk) response.render() assert (default_tax_class.name in force_text(response.content)) response = view_func(request, pk=None) # "new mode" response.render() assert response.content
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_waiver(): sm = ShippingMethod(name="Waivey", tax_class=get_default_tax_class(), module_data={ "price_waiver_product_minimum": "370", "price": "100" }) source = BasketishOrderSource(get_default_shop()) assert sm.get_effective_name(source) == u"Waivey" assert sm.get_effective_price_info( source).price == source.shop.create_price(100) source.add_line(type=OrderLineType.PRODUCT, product=get_default_product(), base_unit_price=source.shop.create_price(400), quantity=1) assert sm.get_effective_price_info( source).price == source.shop.create_price(0)
def test_waiver(): sm = ShippingMethod(name="Waivey", tax_class=get_default_tax_class(), module_data={ "price_waiver_product_minimum": "370", "price": "100" }) source = BasketishOrderSource() assert not source.prices_include_tax() assert sm.get_effective_name(source) == u"Waivey" assert sm.get_effective_price(source) == TaxlessPrice(100) source.lines = [ SourceLine(type=OrderLineType.PRODUCT, product=get_default_product(), unit_price=TaxlessPrice(400), quantity=1) ] assert sm.get_effective_price(source) == TaxlessPrice(0)
def test_limited_methods(): """ Test that products can declare that they limit available shipping methods. """ unique_shipping_method = ShippingMethod(tax_class=get_default_tax_class(), module_data={"price": 0}) unique_shipping_method.save() 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 test_order_flow_with_payment_phase(): create_default_order_statuses() n_orders_pre = Order.objects.count() populate_if_required() c = SmartClient() _populate_client_basket(c) # Create methods shipping_method = get_default_shipping_method() processor = PaymentWithCheckoutPhase.objects.create(identifier="processor_with_phase", enabled=True) assert isinstance(processor, PaymentWithCheckoutPhase) payment_method = processor.create_service( None, identifier="payment_with_phase", shop=get_default_shop(), name="Test method with phase", enabled=True, tax_class=get_default_tax_class(), ) # Resolve paths addresses_path = reverse("shoop:checkout", kwargs={"phase": "addresses"}) methods_path = reverse("shoop:checkout", kwargs={"phase": "methods"}) payment_path = reverse("shoop:checkout", kwargs={"phase": "payment"}) confirm_path = reverse("shoop:checkout", kwargs={"phase": "confirm"}) # Phase: Addresses addresses_soup = c.soup(addresses_path) inputs = fill_address_inputs(addresses_soup, with_company=False) response = c.post(addresses_path, data=inputs) assert response.status_code == 302, "Address phase should redirect forth" assert response.url.endswith(methods_path) # Phase: Methods assert Order.objects.filter(payment_method=payment_method).count() == 0 response = c.post(methods_path, data={"payment_method": payment_method.pk, "shipping_method": shipping_method.pk}) assert response.status_code == 302, "Methods phase should redirect forth" assert response.url.endswith(confirm_path) response = c.get(confirm_path) assert response.status_code == 302, "Confirm should first redirect forth" assert response.url.endswith(payment_path) # Phase: Payment c.soup(payment_path) response = c.post(payment_path, data={"will_pay": False}) assert response.status_code == 200, "Invalid payment form should return error" response = c.post(payment_path, data={"will_pay": True}) assert response.status_code == 302, "Valid payment form should redirect forth" assert response.url.endswith(confirm_path) # Phase: Confirm confirm_soup = c.soup(confirm_path) response = c.post(confirm_path, data=extract_form_fields(confirm_soup)) assert response.status_code == 302, "Confirm should redirect forth" # response.url should point to payment, checked below # Check resulting order and its contents n_orders_post = Order.objects.count() assert n_orders_post > n_orders_pre, "order was created" order = Order.objects.filter(payment_method=payment_method).first() assert order.payment_data.get("promised_to_pay") assert order.payment_status == PaymentStatus.NOT_PAID # Resolve order specific paths (payment and complete) process_payment_path = reverse("shoop:order_process_payment", kwargs={"pk": order.pk, "key": order.key}) process_payment_return_path = reverse( "shoop:order_process_payment_return", kwargs={"pk": order.pk, "key": order.key} ) order_complete_path = reverse("shoop:order_complete", kwargs={"pk": order.pk, "key": order.key}) # Check confirm redirection to payment page assert response.url.endswith(process_payment_path), "Confirm should have redirected to payment page" # Visit payment page response = c.get(process_payment_path) assert response.status_code == 302, "Payment page should redirect forth" assert response.url.endswith(process_payment_return_path) # Check payment return response = c.get(process_payment_return_path) assert response.status_code == 302, "Payment return should redirect forth" assert response.url.endswith(order_complete_path) # Check payment status has changed to DEFERRED order = Order.objects.get(pk=order.pk) # reload assert order.payment_status == PaymentStatus.DEFERRED
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 = 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_order_flow_with_payment_phase(): create_default_order_statuses() n_orders_pre = Order.objects.count() populate_if_required() c = SmartClient() _populate_client_basket(c) # Create methods shipping_method = get_default_shipping_method() processor = PaymentWithCheckoutPhase.objects.create( identifier="processor_with_phase", enabled=True) assert isinstance(processor, PaymentWithCheckoutPhase) payment_method = processor.create_service( None, identifier="payment_with_phase", shop=get_default_shop(), name="Test method with phase", enabled=True, tax_class=get_default_tax_class()) # Resolve paths addresses_path = reverse("shoop:checkout", kwargs={"phase": "addresses"}) methods_path = reverse("shoop:checkout", kwargs={"phase": "methods"}) payment_path = reverse("shoop:checkout", kwargs={"phase": "payment"}) confirm_path = reverse("shoop:checkout", kwargs={"phase": "confirm"}) # Phase: Addresses addresses_soup = c.soup(addresses_path) inputs = fill_address_inputs(addresses_soup, with_company=False) response = c.post(addresses_path, data=inputs) assert response.status_code == 302, "Address phase should redirect forth" assert response.url.endswith(methods_path) # Phase: Methods assert Order.objects.filter(payment_method=payment_method).count() == 0 response = c.post(methods_path, data={ "payment_method": payment_method.pk, "shipping_method": shipping_method.pk }) assert response.status_code == 302, "Methods phase should redirect forth" assert response.url.endswith(confirm_path) response = c.get(confirm_path) assert response.status_code == 302, "Confirm should first redirect forth" assert response.url.endswith(payment_path) # Phase: Payment c.soup(payment_path) response = c.post(payment_path, data={"will_pay": False}) assert response.status_code == 200, "Invalid payment form should return error" response = c.post(payment_path, data={"will_pay": True}) assert response.status_code == 302, "Valid payment form should redirect forth" assert response.url.endswith(confirm_path) # Phase: Confirm confirm_soup = c.soup(confirm_path) response = c.post(confirm_path, data=extract_form_fields(confirm_soup)) assert response.status_code == 302, "Confirm should redirect forth" # response.url should point to payment, checked below # Check resulting order and its contents n_orders_post = Order.objects.count() assert n_orders_post > n_orders_pre, "order was created" order = Order.objects.filter(payment_method=payment_method).first() assert order.payment_data.get("promised_to_pay") assert order.payment_status == PaymentStatus.NOT_PAID # Resolve order specific paths (payment and complete) process_payment_path = reverse("shoop:order_process_payment", kwargs={ "pk": order.pk, "key": order.key }) process_payment_return_path = reverse("shoop:order_process_payment_return", kwargs={ "pk": order.pk, "key": order.key }) order_complete_path = reverse("shoop:order_complete", kwargs={ "pk": order.pk, "key": order.key }) # Check confirm redirection to payment page assert response.url.endswith(process_payment_path), ( "Confirm should have redirected to payment page") # Visit payment page response = c.get(process_payment_path) assert response.status_code == 302, "Payment page should redirect forth" assert response.url.endswith(process_payment_return_path) # Check payment return response = c.get(process_payment_return_path) assert response.status_code == 302, "Payment return should redirect forth" assert response.url.endswith(order_complete_path) # Check payment status has changed to DEFERRED order = Order.objects.get(pk=order.pk) # reload assert order.payment_status == PaymentStatus.DEFERRED