def test_order_creator_source_data(rf, admin_user): get_initial_order_status() # Needed for the API contact = create_random_person(locale="en_US", minimum_name_comp_len=5) request = get_frontend_request_for_command(get_frontend_order_state(contact), "source_data", admin_user) response =OrderEditView.as_view()(request) data = json.loads(response.content.decode("utf8")) assert len(data.get("orderLines")) == 5
def test_company_contact_creation(rf, admin_user): get_initial_order_status() contact = create_random_company() test_tax_number = "1234567-1" contact.tax_number = test_tax_number contact.save() contact.default_billing_address.tax_number = test_tax_number contact.default_billing_address.save() state = get_frontend_order_state(contact=contact) state["customer"] = { "id": None, "name": None, "billingAddress": encode_address(contact.default_billing_address), "shipToBillingAddress": True, "saveAddress": True, "isCompany": True } order = get_order_from_state(state, admin_user) assert order.lines.count() == 5 assert order.customer.id != contact.id assert order.customer.name == contact.name assert order.customer.tax_number == test_tax_number assert order.billing_address.tax_number == contact.default_billing_address.tax_number assert order.billing_address.street == contact.default_billing_address.street assert order.billing_address.street == order.shipping_address.street
def test_order_creator_invalid_base_data(rf, admin_user): get_initial_order_status() # Needed for the API state = get_frontend_order_state(contact=None) # Remove some critical data... state["customer"]["id"] = None state["shop"]["selected"]["id"] = None request = get_frontend_request_for_command(state, "finalize", admin_user) response =OrderEditView.as_view()(request) assert_contains(response, "errorMessage", status_code=400)
def test_order_creator_invalid_line_data(rf, admin_user): get_initial_order_status() # Needed for the API contact = create_random_person(locale="en_US", minimum_name_comp_len=5) state = get_frontend_order_state(contact=contact, valid_lines=False) request = get_frontend_request_for_command(state, "finalize", admin_user) response = OrderEditView.as_view()(request) # Let's see that we get a cornucopia of trouble: assert_contains(response, "does not exist", status_code=400) assert_contains(response, "does not have a product", status_code=400) assert_contains(response, "The price", status_code=400) assert_contains(response, "The quantity", status_code=400)
def test_order_received_admin(rf, admin_user): get_test_script("test script", "order_received") template_data = STEP_DATA[0]["actions"][0]["template_data"] for lang in ["en", "fi"]: get_initial_order_status() # Needed for the API n_outbox_pre = len(mail.outbox) contact = create_random_person(locale=lang, minimum_name_comp_len=5) get_order_from_state(get_frontend_order_state(contact), admin_user) assert (len(mail.outbox) == n_outbox_pre + 1), "Sending email failed" latest_mail = mail.outbox[-1] assert latest_mail.subject == template_data[lang]["subject"], "Subject doesn't match" assert latest_mail.body == template_data[lang]["body"], "Body doesn't match"
def test_order_creator_valid(rf, admin_user): get_initial_order_status() # Needed for the API contact = create_random_person(locale="en_US", minimum_name_comp_len=5) order = get_order_from_state(get_frontend_order_state(contact), admin_user) assert order.lines.count() == 5 # 3 submitted, two for the shipping and payment method assert order.creator == admin_user assert order.customer == contact # Check that product line have right taxes for line in order.lines.all(): if line.type == OrderLineType.PRODUCT: assert [line_tax.tax.code for line_tax in line.taxes.all()] == ["test_code"] assert line.taxful_price.amount > line.taxless_price.amount
def test_editing_existing_order(rf, admin_user): modifier = UserFactory() get_initial_order_status() # Needed for the API contact = create_random_person(locale="en_US", minimum_name_comp_len=5) state = get_frontend_order_state(contact=contact) shop = get_default_shop() order = create_empty_order(shop=shop) order.payment_data = {"payment_data": True} order.shipping_data = {"shipping_data": True} order.extra_data = {"external_id": "123"} order.save() assert order.lines.count() == 0 assert order.pk is not None assert order.modified_by == order.creator request = get_frontend_request_for_command(state, "finalize", modifier) response = OrderEditView.as_view()(request, pk=order.pk) assert_contains(response, "orderIdentifier") # this checks for status codes as a side effect data = json.loads(response.content.decode("utf8")) edited_order = Order.objects.get(pk=order.pk) # Re fetch the initial order # Check that identifiers has not changed assert edited_order.identifier == data["orderIdentifier"] == order.identifier assert edited_order.pk == order.pk # Check that the product content is updated based on state assert edited_order.lines.count() == 5 assert edited_order.customer == contact # Check that product line have right taxes for line in edited_order.lines.all(): if line.type == OrderLineType.PRODUCT: assert [line_tax.tax.code for line_tax in line.taxes.all()] == ["test_code"] assert line.taxful_price.amount > line.taxless_price.amount # Make sure order modification information is correct assert edited_order.modified_by != order.modified_by assert edited_order.modified_by == modifier assert edited_order.modified_on > order.modified_on # Make sure all non handled attributes is preserved from original order assert edited_order.creator == order.creator assert edited_order.ip_address == order.ip_address assert edited_order.orderer == order.orderer assert edited_order.customer_comment == order.customer_comment assert edited_order.marketing_permission == order.marketing_permission assert edited_order.order_date == order.order_date assert edited_order.status == order.status assert edited_order.payment_data == order.payment_data assert edited_order.shipping_data == order.shipping_data assert edited_order.extra_data == order.extra_data
def seed_source(user, shop): source = BasketishOrderSource(shop) source.status = get_initial_order_status() source.customer = get_person_contact(user) source.payment_method = get_default_payment_method() source.shipping_method = get_default_shipping_method() return source
def get_order_and_source(admin_user, product): # create original source to tamper with source = BasketishOrderSource(get_default_shop()) source.status = get_initial_order_status() source.billing_address = MutableAddress.objects.create(name="Original Billing") source.shipping_address = MutableAddress.objects.create(name="Original Shipping") source.customer = get_person_contact(admin_user) source.payment_method = get_default_payment_method() source.shipping_method = get_default_shipping_method() source.add_line( type=OrderLineType.PRODUCT, product=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, ) assert len(source.get_lines()) == 2 source.creator = admin_user creator = OrderCreator() order = creator.create_order(source) return order, source
def create_simple_order(request, creator, customer): billing_address = get_address().to_immutable() shipping_address = get_address(name="Shippy Doge").to_immutable() shipping_address.save() shop = request.shop order = Order( creator=creator, customer=customer, shop=shop, payment_method=get_default_payment_method(), shipping_method=get_default_shipping_method(), billing_address=billing_address, shipping_address=shipping_address, order_date=now(), status=get_initial_order_status(), currency=shop.currency, prices_include_tax=shop.prices_include_tax, ) order.full_clean() order.save() order.cache_prices() order.check_all_verified() order.save() return order
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_creator_view(browser, admin_user, live_server): shop = get_default_shop() pm = get_default_payment_method() sm = get_default_shipping_method() get_initial_order_status() supplier = get_default_supplier() person = create_random_person() product0 = create_product("test-sku0", shop=shop, default_price=10, supplier=supplier) product1 = create_product("test-sku1", shop=shop, default_price=10, supplier=supplier) initialize_admin_browser_test(browser, live_server) _visit_order_creator_view(browser, live_server) _test_customer_data(browser, person) _test_add_lines(browser) _test_quick_add_lines(browser) _test_methods(browser) _test_confirm(browser)
def _seed_source(shop, user): source = BasketishOrderSource(shop) billing_address = get_address() shipping_address = get_address(name="Test street") source.status = get_initial_order_status() source.billing_address = billing_address source.shipping_address = shipping_address source.customer = get_person_contact(user) return source
def test_order_creator_addresses(rf, admin_user): get_initial_order_status() # Needed for the API contact = create_random_person(locale="en_US", minimum_name_comp_len=5) state = get_frontend_order_state(contact=contact) # company with no tax number state["customer"]["isCompany"] = True request = get_frontend_request_for_command(state, "finalize", admin_user) response =OrderEditView.as_view()(request) assert_contains(response, "Tax number is not set", status_code=400) # company with tax number, should work state["customer"]["billingAddress"]["tax_number"] = "123" state["customer"]["shippingAddress"]["tax_number"] = "123" order = get_order_from_state(state, admin_user) assert order.lines.count() == 5 # person with no shipping address state["customer"]["isCompany"] = False state["customer"]["shippingAddress"] = {} request = get_frontend_request_for_command(state, "finalize", admin_user) response =OrderEditView.as_view()(request) assert_contains(response, "This field is required", status_code=400) # ship to billing, should work now state["customer"]["shipToBillingAddress"] = True order = get_order_from_state(state, admin_user) assert order.lines.count() == 5 # change name and make sure contact address is NOT updated original_name = contact.default_billing_address.name state["customer"]["billingAddress"]["name"] = "foobar" state["customer"]["saveAddress"] = False order = get_order_from_state(state, admin_user) contact.refresh_from_db() assert contact.default_billing_address.name == original_name # change name with saveAddress set, contact address should update original_name = contact.default_billing_address.name state["customer"]["billingAddress"]["name"] = "foobar" state["customer"]["saveAddress"] = True order = get_order_from_state(state, admin_user) contact.refresh_from_db() assert contact.default_billing_address.name == "foobar"
def test_person_contact_creation(rf, admin_user): get_initial_order_status() # Needed for the API contact = create_random_person(locale="en_US", minimum_name_comp_len=5) state = get_frontend_order_state(contact=contact) state["customer"] = { "id": None, "name": None, "billingAddress": encode_address(contact.default_billing_address), "shipToBillingAddress": True, "saveAddress": True, "isCompany": False } order = get_order_from_state(state, admin_user) assert order.lines.count() == 5 assert order.customer.id != contact.id assert order.customer.name == contact.name assert order.billing_address.name == contact.default_billing_address.name assert order.billing_address.street == contact.default_billing_address.street assert order.billing_address.street == order.shipping_address.street
def test_admin_cash_order(rf, admin_user, price, target, mode): activate("en") get_initial_order_status() # Needed for the API shop = get_default_shop() contact = create_random_person(locale="en_US", minimum_name_comp_len=5) processor = CustomPaymentProcessor.objects.create(rounding_mode=mode) cash_method = PaymentMethod.objects.create( shop=shop, payment_processor=processor, choice_identifier="cash", tax_class=get_default_tax_class(), name="Cash") state = get_frontend_order_state(contact, cash_method, price) order = get_order_from_state(state, admin_user) assert order.payment_method == cash_method assert order.lines.count() == 5 # 2 submitted, two for the shipping and payment method, and a rounding line assert order.creator == admin_user assert order.customer == contact assert order.taxful_total_price == shop.create_price(target)
def _init_test_for_product_with_basket(rf, default_price): request, product = _init_test_for_product_without_basket(rf, default_price) shop = factories.get_default_shop() supplier = factories.get_default_supplier() basket = get_basket(request) basket.status = factories.get_initial_order_status() basket.add_product(supplier=supplier, shop=shop, product=product, quantity=1) basket.shipping_method = factories.get_shipping_method(shop=shop) basket.payment_method = factories.get_payment_method(shop=shop) assert basket.shop == request.shop assert basket.customer == request.customer return request, product, basket
def test_order_creator_view(browser, admin_user, live_server, settings): shop = get_default_shop() pm = get_default_payment_method() sm = get_default_shipping_method() get_initial_order_status() supplier = get_default_supplier() person = create_random_person() product0 = create_product("test-sku0", shop=shop, default_price=10, supplier=supplier) product1 = create_product("test-sku1", shop=shop, default_price=10, supplier=supplier) object_created.connect(_add_custom_order_created_message, sender=Order, dispatch_uid="object_created_signal_test") initialize_admin_browser_test(browser, live_server, settings) browser.driver.maximize_window() _visit_order_creator_view(browser, live_server) _test_language_change(browser) _test_customer_data(browser, person) _test_regions(browser, person) _test_add_lines(browser) _test_quick_add_lines(browser) _test_methods(browser) _test_confirm(browser) assert Order.objects.first().log_entries.filter(identifier=OBJECT_CREATED_LOG_IDENTIFIER).count() == 1 object_created.disconnect(sender=Order, dispatch_uid="object_created_signal_test")
def seed_source(user): source = BasketishOrderSource(get_default_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_default_payment_method() source.shipping_method = get_default_shipping_method() assert source.payment_method_id == get_default_payment_method().id assert source.shipping_method_id == get_default_shipping_method().id return source
def test_order_address_immutability_unsaved_address(save): billing_address = get_address() if save: billing_address.save() order = Order( shop=get_default_shop(), billing_address=billing_address.to_immutable(), order_date=now(), status=get_initial_order_status() ) order.save() order.billing_address.name = "Mute Doge" with pytest.raises(ValidationError): order.billing_address.save()
def test_order_creator_parent_linkage(): """ Test OrderCreator creates parent links from OrderSource. """ source = BasketishOrderSource(get_default_shop()) source.status = get_initial_order_status() source.add_line(line_id="LINE1", type=OrderLineType.OTHER, quantity=1, sku="parent", text="Parent line") source.add_line( line_id="LINE1.1", parent_line_id="LINE1", type=OrderLineType.OTHER, quantity=1, sku="child1.1", text="Child line 1.1", ) source.add_line( line_id="LINE1.2", parent_line_id="LINE1", type=OrderLineType.OTHER, quantity=1, sku="child1.2", text="Child line 1.2", ) source.add_line( line_id="LINE1.2.1", parent_line_id="LINE1.2", type=OrderLineType.OTHER, quantity=1, sku="child1.2.1", text="Child line 1.2.1", ) source.add_line( line_id="LINE1.3", parent_line_id="LINE1", type=OrderLineType.OTHER, quantity=1, sku="child1.3", text="Child line 1.3", ) order = OrderCreator().create_order(source) lines = [prettify_order_line(line) for line in order.lines.all()] assert lines == [ "#0 1 x parent", "#1 1 x child1.1, child of #0", "#2 1 x child1.2, child of #0", "#3 1 x child1.2.1, child of #2", "#4 1 x child1.3, child of #0", ]
def _create_order(request, customer, coupon, product, expected_product_price): creator = OrderCreator(request) shop = request.shop request.basket = None request.customer = customer basket = get_basket(request) basket.status = factories.get_initial_order_status() basket.add_product(supplier=factories.get_default_supplier(), shop=shop, product=product, quantity=1) basket.shipping_method = factories.get_shipping_method(shop=shop) basket.payment_method = factories.get_payment_method(shop=shop) basket.add_code(coupon) assert basket.shop == request.shop assert basket.customer == request.customer assert product.get_price_info(request).price == expected_product_price creator.create_order(basket)
def get_order_source_with_a_package(): package_product = get_package_product() source = BasketishOrderSource(get_default_shop()) source.add_line( type=OrderLineType.PRODUCT, product=package_product, supplier=get_default_supplier(), quantity=10, base_unit_price=source.create_price(10), sku=package_product.sku, text=package_product.name, ) source.status = get_initial_order_status() return source
def _get_custom_order(regular_user, **kwargs): prices_include_tax = kwargs.pop("prices_include_tax", False) include_basket_campaign = kwargs.pop("include_basket_campaign", False) include_catalog_campaign = kwargs.pop("include_catalog_campaign", False) shop = get_shop(prices_include_tax=prices_include_tax) supplier = get_simple_supplier() if include_basket_campaign: _add_basket_campaign(shop) if include_catalog_campaign: _add_catalog_campaign(shop) _add_taxes() contact = get_person_contact(regular_user) source = BasketishOrderSource(shop) source.status = get_initial_order_status() source.customer = contact ctx = get_pricing_module().get_context_from_data(shop, contact) for product_data in _get_product_data(): quantity = product_data.pop("quantity") product = create_product( sku=product_data.pop("sku"), shop=shop, supplier=supplier, stock_behavior=StockBehavior.STOCKED, tax_class=get_default_tax_class(), **product_data) shop_product = product.get_shop_instance(shop) shop_product.categories.add(get_default_category()) shop_product.save() supplier.adjust_stock(product.id, INITIAL_PRODUCT_QUANTITY) pi = product.get_price_info(ctx) source.add_line( type=OrderLineType.PRODUCT, product=product, supplier=supplier, quantity=quantity, base_unit_price=pi.base_unit_price, discount_amount=pi.discount_amount ) oc = OrderCreator() order = oc.create_order(source) return order
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) 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=2) campaign.conditions.add(rule) campaign.save() assert len(basket.get_final_lines()) == 3 # no discount was applied because coupon is required basket.add_code(dc.code) assert len(basket.get_final_lines()) == 4 # 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_order_creator_parent_linkage(): """ Test OrderCreator creates parent links from OrderSource. """ source = BasketishOrderSource(get_default_shop()) source.status = get_initial_order_status() source.add_line( line_id='LINE1', type=OrderLineType.OTHER, quantity=1, sku='parent', text='Parent line', ) source.add_line( line_id='LINE1.1', parent_line_id='LINE1', type=OrderLineType.OTHER, quantity=1, sku='child1.1', text='Child line 1.1', ) source.add_line( line_id='LINE1.2', parent_line_id='LINE1', type=OrderLineType.OTHER, quantity=1, sku='child1.2', text='Child line 1.2', ) source.add_line( line_id='LINE1.2.1', parent_line_id='LINE1.2', type=OrderLineType.OTHER, quantity=1, sku='child1.2.1', text='Child line 1.2.1', ) source.add_line( line_id='LINE1.3', parent_line_id='LINE1', type=OrderLineType.OTHER, quantity=1, sku='child1.3', text='Child line 1.3', ) order = OrderCreator().create_order(source) lines = [prettify_order_line(line) for line in order.lines.all()] assert lines == [ '#0 1 x parent', '#1 1 x child1.1, child of #0', '#2 1 x child1.2, child of #0', '#3 1 x child1.2.1, child of #2', '#4 1 x child1.3, child of #0', ]
def seed_source(shipping_method=None, produce_price=10): source = BasketishOrderSource(get_default_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 = create_random_person() source.payment_method = get_default_payment_method() source.shipping_method = shipping_method if shipping_method else get_default_shipping_method() source.add_line( type=OrderLineType.PRODUCT, product=get_default_product(), supplier=get_default_supplier(), quantity=1, base_unit_price=source.create_price(produce_price), ) return source
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
def _get_order(prices_include_tax=False, include_basket_campaign=False, include_catalog_campaign=False): shop = get_shop(prices_include_tax=prices_include_tax) supplier = get_simple_supplier() if include_basket_campaign: _add_basket_campaign(shop) if include_catalog_campaign: _add_catalog_campaign(shop) _add_taxes() source = BasketishOrderSource(shop) source.status = get_initial_order_status() ctx = get_pricing_module().get_context_from_data(shop, AnonymousContact()) for product_data in _get_product_data(): quantity = product_data.pop("quantity") product = create_product( sku=product_data.pop("sku"), shop=shop, supplier=supplier, stock_behavior=StockBehavior.STOCKED, tax_class=get_default_tax_class(), **product_data) shop_product = product.get_shop_instance(shop) shop_product.categories.add(get_default_category()) shop_product.save() supplier.adjust_stock(product.id, INITIAL_PRODUCT_QUANTITY) pi = product.get_price_info(ctx) source.add_line( type=OrderLineType.PRODUCT, product=product, supplier=supplier, quantity=quantity, base_unit_price=pi.base_unit_price, discount_amount=pi.discount_amount ) oc = OrderCreator() order = oc.create_order(source) order.create_payment(Money("1", "EUR")) assert not order.has_refunds() assert order.can_create_refund() assert order.shipping_status == ShippingStatus.NOT_SHIPPED assert order.payment_status == PaymentStatus.PARTIALLY_PAID return order
def seed_source(user, extra_addr=True): source = BasketishOrderSource(get_default_shop()) billing_address = get_address() shipping_address = get_address(name="Shippy Doge") if extra_addr: billing_address.extra = ExtraMutableAddress.from_data(EXTRA_MUTABLE_ADDRESS_1) if extra_addr: shipping_address.extra = ExtraMutableAddress.from_data(EXTRA_MUTABLE_ADDRESS_2) 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_default_payment_method() source.shipping_method = get_default_shipping_method() assert source.payment_method_id == get_default_payment_method().id assert source.shipping_method_id == get_default_shipping_method().id return source
def get_order_and_source(admin_user, product, language, language_fallback): # create original source to tamper with contact = get_person_contact(admin_user) contact.language = language contact.save() assert contact.language == language # contact language is naive source = BasketishOrderSource(get_default_shop()) source.status = get_initial_order_status() source.billing_address = MutableAddress.objects.create(name="Original Billing") source.shipping_address = MutableAddress.objects.create(name="Original Shipping") source.customer = contact source.payment_method = get_default_payment_method() source.shipping_method = get_default_shipping_method() source.add_line( type=OrderLineType.PRODUCT, product=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, ) assert len(source.get_lines()) == 2 source.creator = admin_user assert not source._language # is None because it was not directly assigned assert source.language == language_fallback creator = OrderCreator() order = creator.create_order(source) assert order.language == source.language return order, source
def seed_source(shipping_method=None, produce_price=10, shop=None): if not shop: shop = get_default_shop() source = BasketishOrderSource(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 = create_random_person() source.payment_method = get_payment_method(shop=shop) source.shipping_method = shipping_method if shipping_method else get_default_shipping_method( ) source.add_line( type=OrderLineType.PRODUCT, product=get_default_product(), supplier=get_default_supplier(shop), quantity=1, base_unit_price=source.create_price(produce_price), ) return source
def test_order_edit_with_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) 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() == 4 assert OrderLineType.DISCOUNT in [l.type for l in edited_order.lines.all()] assert edited_order.coupon_usages.count() == 1
def _get_order(prices_include_tax=False, include_basket_campaign=False, include_catalog_campaign=False): shop = get_shop(prices_include_tax=prices_include_tax) supplier = get_simple_supplier() if include_basket_campaign: _add_basket_campaign(shop) if include_catalog_campaign: _add_catalog_campaign(shop) _add_taxes() source = BasketishOrderSource(shop) source.status = get_initial_order_status() ctx = get_pricing_module().get_context_from_data(shop, AnonymousContact()) for product_data in _get_product_data(): quantity = product_data.pop("quantity") product = create_product( sku=product_data.pop("sku"), shop=shop, supplier=supplier, stock_behavior=StockBehavior.STOCKED, tax_class=get_default_tax_class(), **product_data) shop_product = product.get_shop_instance(shop) shop_product.categories.add(get_default_category()) shop_product.save() supplier.adjust_stock(product.id, INITIAL_PRODUCT_QUANTITY) pi = product.get_price_info(ctx) source.add_line( type=OrderLineType.PRODUCT, product=product, supplier=supplier, quantity=quantity, base_unit_price=pi.base_unit_price, discount_amount=pi.discount_amount ) oc = OrderCreator() order = oc.create_order(source) return order
def test_percentage_campaign_full_discount(rf, include_tax): request, shop, group = initialize_test(rf, include_tax) create_default_order_statuses() tax = get_tax("sales-tax", "Sales Tax", Decimal(0.2)) # 20% create_default_tax_rule(tax) basket = get_basket(request) supplier = get_default_supplier(shop) product = create_product(printable_gibberish(), shop=shop, supplier=supplier, default_price=200) basket.add_product(supplier=supplier, shop=shop, product=product, quantity=1) basket.shipping_method = get_shipping_method(shop=shop) basket.status = get_initial_order_status() campaign = BasketCampaign.objects.create(shop=shop, public_name="test", name="test", active=True) # 100% of discount BasketDiscountPercentage.objects.create(campaign=campaign, discount_percentage=Decimal(1)) assert len(basket.get_final_lines()) == 3 assert basket.product_count == 1 assert basket.total_price.value == Decimal() order_creator = OrderCreator() order = order_creator.create_order(basket) order.create_payment(order.taxful_total_price) assert order.taxful_total_price.value == Decimal()
def test_broken_order(admin_user): """""" quantities = [44, 23, 65] expected = sum(quantities) * 50 expected_based_on = expected / 1.5 # Shuup is calculating taxes per line so there will be some "errors" expected_based_on = ensure_decimal_places( Decimal("%s" % (expected_based_on + 0.01))) shop = get_default_shop() supplier = get_default_supplier() product1 = create_product("simple-test-product1", shop, supplier, 50) product2 = create_product("simple-test-product2", shop, supplier, 50) product3 = create_product("simple-test-product3", shop, supplier, 50) tax = get_default_tax() source = BasketishOrderSource(get_default_shop()) billing_address = get_address(country="US") shipping_address = get_address(name="Test street", country="US") source.status = get_initial_order_status() source.billing_address = billing_address source.shipping_address = shipping_address source.customer = create_random_person() source.payment_method = get_default_payment_method() source.shipping_method = get_default_shipping_method() source.add_line( type=OrderLineType.PRODUCT, product=product1, supplier=get_default_supplier(), quantity=quantities[0], base_unit_price=source.create_price(50), ) source.add_line( type=OrderLineType.PRODUCT, product=product2, supplier=get_default_supplier(), quantity=quantities[1], base_unit_price=source.create_price(50), ) source.add_line( type=OrderLineType.PRODUCT, product=product3, supplier=get_default_supplier(), quantity=quantities[2], base_unit_price=source.create_price(50), ) currency = "EUR" summary = source.get_tax_summary() assert len(summary) == 1 summary = summary[0] assert summary.taxful == Money(expected, "EUR") assert summary.based_on == Money(expected_based_on, "EUR") # originally non-rounded value assert bankers_round(source.get_total_tax_amount()) == summary.tax_amount assert source.taxless_total_price.value == expected_based_on assert summary.taxful.value == source.taxful_total_price.value assert summary.tax_amount == Money( bankers_round(source.taxful_total_price.value - source.taxless_total_price.value), currency) assert summary.taxful == summary.raw_based_on + summary.tax_amount assert summary.tax_rate == tax.rate assert summary.taxful.value == ( summary.based_on + summary.tax_amount).value - Decimal("%s" % 0.01) # create order from basket creator = OrderCreator() order = creator.create_order(source) assert order.taxless_total_price.value == expected_based_on # originally non-rounded value assert bankers_round(order.get_total_tax_amount()) == summary.tax_amount
def create_order(request, creator, customer, product): billing_address = get_address().to_immutable() shipping_address = get_address(name="Shippy Doge").to_immutable() shipping_address.save() shop = request.shop order = Order( creator=creator, customer=customer, shop=shop, payment_method=get_default_payment_method(), shipping_method=get_default_shipping_method(), billing_address=billing_address, shipping_address=shipping_address, order_date=now(), status=get_initial_order_status(), currency=shop.currency, prices_include_tax=shop.prices_include_tax, ) order.full_clean() order.save() supplier = get_default_supplier() product_order_line = OrderLine(order=order) update_order_line_from_product(pricing_context=request, order_line=product_order_line, product=product, quantity=5, supplier=supplier) assert product_order_line.text == product.safe_translation_getter("name") product_order_line.base_unit_price = shop.create_price(100) assert product_order_line.price.value > 0 product_order_line.save() line_tax = get_line_taxes_for(product_order_line)[0] order_line_tax = OrderLineTax.from_tax( tax=line_tax.tax, base_amount=line_tax.base_amount, order_line=product_order_line, ) order_line_tax.save( ) # Save order_line_tax before linking to order_line.tax product_order_line.taxes.add(order_line_tax) discount_order_line = OrderLine(order=order, quantity=1, type=OrderLineType.OTHER) discount_order_line.discount_amount = shop.create_price(30) assert discount_order_line.discount_amount.value == 30 assert discount_order_line.price.value == -30 assert discount_order_line.base_unit_price.value == 0 discount_order_line.save() order.cache_prices() order.check_all_verified() order.save() assert not order.can_set_complete() base = 5 * shop.create_price(100).amount discount = shop.create_price(30).amount tax_value = line_tax.amount if not order.prices_include_tax: assert order.taxless_total_price.amount == base - discount assert order.taxful_total_price.amount == base + tax_value - discount else: assert_almost_equal(order.taxless_total_price.amount, base - tax_value - discount) assert_almost_equal(order.taxful_total_price.amount, base - discount) assert not order.is_fully_shipped() shipment = order.create_shipment_of_all_products(supplier=supplier) assert order.is_fully_shipped() assert shipment.total_products == 5, "All products were shipped" assert shipment.weight == product.gross_weight * 5 / 1000, "Gravity works" assert not order.get_unshipped_products( ), "Nothing was left in the warehouse" assert order.can_set_complete() order.create_payment(order.taxful_total_price) assert order.is_paid() assert Order.objects.paid().filter( pk=order.pk).exists(), "It was paid! Honestly!" assert order.has_products()
def test_order_partial_refund_with_taxes(include_tax): tax_rate = Decimal(0.2) # 20% product_price = 100 discount_amount = 30 random_line_price = 5 refunded_amount = 15 shop = factories.get_shop(include_tax) source = OrderSource(shop) source.status = factories.get_initial_order_status() supplier = factories.get_default_supplier() create_default_order_statuses() tax = factories.get_tax("sales-tax", "Sales Tax", tax_rate) factories.create_default_tax_rule(tax) product = factories.create_product("sku", shop=shop, supplier=supplier, default_price=product_price) line = source.add_line( line_id="product-line", type=OrderLineType.PRODUCT, product=product, supplier=supplier, quantity=1, shop=shop, base_unit_price=source.create_price(product_price), ) discount_line = source.add_line( line_id="discount-line", type=OrderLineType.DISCOUNT, supplier=supplier, quantity=1, base_unit_price=source.create_price(0), discount_amount=source.create_price(discount_amount), parent_line_id=line.line_id) raw_total_price = Decimal(product_price - discount_amount) total_taxful = bround(source.taxful_total_price.value) total_taxless = bround(source.taxless_total_price.value) if include_tax: assert total_taxful == bround(raw_total_price) assert total_taxless == bround(raw_total_price / (1 + tax_rate)) else: assert total_taxful == bround(raw_total_price * (1 + tax_rate)) assert total_taxless == bround(raw_total_price) creator = OrderCreator() order = creator.create_order(source) assert order.taxful_total_price.value == total_taxful assert order.taxless_total_price.value == total_taxless order.create_payment(order.taxful_total_price) assert order.is_paid() refund_data = [ dict( amount=Money(refunded_amount, shop.currency), quantity=1, line=order.lines.products().first(), ) ] order.create_refund(refund_data) total_taxful = bround(order.taxful_total_price.value) total_taxless = bround(order.taxless_total_price.value) taxless_refunded_amount = (refunded_amount / (1 + tax_rate)) if include_tax: raw_total_price = Decimal(product_price - discount_amount - refunded_amount) assert total_taxful == bround(raw_total_price) assert total_taxless == bround(raw_total_price / (1 + tax_rate)) else: # the refunded amount it considered a taxful price internally raw_total_price = Decimal(product_price - discount_amount) assert total_taxful == bround((raw_total_price * (1 + tax_rate)) - refunded_amount) assert total_taxless == bround(raw_total_price - taxless_refunded_amount) refund_line = order.lines.refunds().filter( type=OrderLineType.REFUND).first() if include_tax: assert refund_line.taxful_price.value == -bround(refunded_amount) assert refund_line.taxless_price.value == -bround( taxless_refunded_amount) else: assert refund_line.taxful_price.value == -bround(refunded_amount) assert refund_line.taxless_price.value == -bround( taxless_refunded_amount)
def test_order_full_refund_with_taxes(include_tax): tax_rate = Decimal(0.2) # 20% product_price = 100 discount_amount = 30 random_line_price = 5 shop = factories.get_shop(include_tax) source = OrderSource(shop) source.status = factories.get_initial_order_status() supplier = factories.get_default_supplier() create_default_order_statuses() tax = factories.get_tax("sales-tax", "Sales Tax", tax_rate) factories.create_default_tax_rule(tax) product = factories.create_product("sku", shop=shop, supplier=supplier, default_price=product_price) line = source.add_line( line_id="product-line", type=OrderLineType.PRODUCT, product=product, supplier=supplier, quantity=1, shop=shop, base_unit_price=source.create_price(product_price), ) discount_line = source.add_line( line_id="discount-line", type=OrderLineType.DISCOUNT, supplier=supplier, quantity=1, base_unit_price=source.create_price(0), discount_amount=source.create_price(discount_amount), parent_line_id=line.line_id) raw_total_price = Decimal(product_price - discount_amount) total_taxful = bround(source.taxful_total_price.value) total_taxless = bround(source.taxless_total_price.value) if include_tax: assert total_taxful == bround(raw_total_price) assert total_taxless == bround(raw_total_price / (1 + tax_rate)) else: assert total_taxful == bround(raw_total_price * (1 + tax_rate)) assert total_taxless == bround(raw_total_price) # Lines without quantity shouldn't affect refunds other_line = source.add_line( text="This random line for textual information", line_id="other-line", type=OrderLineType.OTHER, quantity=0) # Lines with quantity again should be able to be refunded normally. other_line_with_quantity = source.add_line( line_id="other_line_with_quantity", type=OrderLineType.OTHER, text="Special service $5/h", quantity=1, base_unit_price=source.create_price(random_line_price)) raw_total_price = Decimal(product_price - discount_amount + random_line_price) total_taxful = bround(source.taxful_total_price.value) total_taxless = bround(source.taxless_total_price.value) if include_tax: assert total_taxful == bround(raw_total_price) assert total_taxless == bround(raw_total_price / (1 + tax_rate)) else: assert total_taxful == bround(raw_total_price * (1 + tax_rate)) assert total_taxless == bround(raw_total_price) creator = OrderCreator() order = creator.create_order(source) assert order.taxful_total_price.value == total_taxful assert order.taxless_total_price.value == total_taxless order.create_payment(order.taxful_total_price) assert order.is_paid() order.create_full_refund() assert order.taxful_total_price_value == 0 for parent_order_line in order.lines.filter(parent_line__isnull=True): if parent_order_line.quantity == 0: assert not parent_order_line.child_lines.exists() else: refund_line = parent_order_line.child_lines.filter( type=OrderLineType.REFUND).first() assert refund_line assert parent_order_line.taxful_price.value == -refund_line.taxful_price.value assert parent_order_line.taxless_price.value == -refund_line.taxless_price.value assert parent_order_line.price.value == -refund_line.price.value