def test_get_by_identifier(admin_user): shop = get_default_shop() for i in range(1, 10): order = create_empty_order(shop=shop) order.save() order = create_empty_order(shop=shop) order.save() client = _get_client(admin_user) response = client.get("/api/wshop/order/", data={"identifier": order.identifier}) assert response.status_code == status.HTTP_200_OK order_data = json.loads(response.content.decode("utf-8")) assert order_data[0].get("id") == order.id assert order_data[0].get("identifier") == order.identifier
def test_complex_order_tax(include_taxes): tax = get_default_tax() quantities = [44, 23, 65] product = get_default_product() supplier = get_default_supplier() shop = get_default_shop() shop.prices_include_tax = include_taxes shop.save() order = create_empty_order(shop=shop) order.full_clean() order.save() pricing_context = get_pricing_module().get_context_from_data( shop=shop, customer=order.customer or AnonymousContact(), ) total_price = Decimal("0") price = Decimal("50") for quantity in quantities: total_price += quantity * price add_product_to_order(order, supplier, product, quantity, price, tax.rate, pricing_context) order.cache_prices() order.save() currency = "EUR" summary = order.get_tax_summary()[0] assert summary.tax_rate == tax.rate assert summary.based_on == Money(total_price, currency) assert summary.tax_amount == Money(total_price * tax.rate, currency) assert summary.taxful == summary.based_on + summary.tax_amount assert order.get_total_tax_amount() == Money(total_price * tax.rate, currency)
def test_refno_generation(method): for attempt in range(10): with override_settings(WSHOP_REFERENCE_NUMBER_METHOD=method): order = create_empty_order() order.save() assert order.reference_number with pytest.raises(ValueError): get_reference_number(order)
def test_complete_order(admin_user): shop = get_default_shop() order = create_empty_order(shop=shop) order.save() client = _get_client(admin_user) response = client.post("/api/wshop/order/%s/complete/" % order.pk) assert response.status_code == 200 response = client.post("/api/wshop/order/%s/complete/" % order.pk) assert response.status_code == 400
def test_get_by_status(admin_user): create_default_order_statuses() shop = get_default_shop() cancelled_status = OrderStatus.objects.get_default_canceled() for i in range(1, 10): order = create_empty_order(shop=shop) order.status = cancelled_status order.save() order = create_empty_order(shop=shop) order.save() client = _get_client(admin_user) response = client.get("/api/wshop/order/", data={"status": order.status.id}) assert response.status_code == status.HTTP_200_OK order_data = json.loads(response.content.decode("utf-8")) assert len(order_data) == 1 assert order_data[0].get("id") == order.id assert order_data[0].get("identifier") == order.identifier response = client.get("/api/wshop/order/", data={"status": cancelled_status.id}) assert response.status_code == status.HTTP_200_OK order_data = json.loads(response.content.decode("utf-8")) assert len(order_data) == 9 assert order.can_set_complete() old_status = order.status order.status = OrderStatus.objects.get_default_complete() order.save() assert old_status != order.status response = client.get("/api/wshop/order/", data={"status": old_status.id}) assert response.status_code == status.HTTP_200_OK order_data = json.loads(response.content.decode("utf-8")) assert len(order_data) == 0 response = client.get("/api/wshop/order/", data={"status": order.status.id}) assert response.status_code == status.HTTP_200_OK order_data = json.loads(response.content.decode("utf-8")) assert len(order_data) == 1
def test_get_by_id(admin_user): shop = get_default_shop() order = create_empty_order(shop=shop) order.save() client = _get_client(admin_user) response = client.get("/api/wshop/order/%s/" % order.id) assert response.status_code == status.HTTP_200_OK order_data = json.loads(response.content.decode("utf-8")) assert order_data.get("id") == order.id
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 test_orders_list_view(browser, admin_user, live_server, settings): shop = get_default_shop() for i in range(0, 10): order = create_empty_order(shop=shop) order.save() # Set last one canceled Order.objects.last().set_canceled() initialize_admin_browser_test(browser, live_server, settings) _visit_orders_list_view(browser, live_server) _test_status_filter(browser) # Will set three orders from end canceled
def test_custom_ident_generation(): methods = ( custom_ident_gen, "%s.%s" % (__name__, custom_ident_gen.__name__) ) for method in methods: with override_settings(WSHOP_ORDER_IDENTIFIER_METHOD=method): order = create_empty_order() order.save() assert order.identifier == custom_ident_gen(order) with pytest.raises(ValueError): get_order_identifier(order)
def test_custom_refno_generation(): methods = ( custom_refno_gen, "%s.%s" % (__name__, custom_refno_gen.__name__) ) for method in methods: with override_settings(WSHOP_REFERENCE_NUMBER_METHOD=method): order = create_empty_order() order.save() assert order.reference_number == custom_refno_gen(order) with pytest.raises(ValueError): get_reference_number(order)
def test_shipment_creation_with_invalid_unsaved_shipment(): shop = get_default_shop() supplier = get_default_supplier() order = _get_order(shop, supplier) second_order = create_empty_order(shop=shop) second_order.full_clean() second_order.save() product_lines = order.lines.exclude(product_id=None) for line in product_lines: for i in range(0, int(line.quantity)): with pytest.raises(AssertionError): unsaved_shipment = Shipment(supplier=supplier, order=second_order) order.create_shipment({line.product: 1}, shipment=unsaved_shipment) assert order.shipments.count() == 0
def test_known_extra_data(): order = create_empty_order() order.shipping_data = {"instruction": "Hello"} order.payment_data = {"ssn": "101010-010X"} order.extra_data = {"wrapping_color": "blue"} order.save() with override_settings( WSHOP_ORDER_KNOWN_SHIPPING_DATA_KEYS=[("instruction", "Instruction")], WSHOP_ORDER_KNOWN_PAYMENT_DATA_KEYS=[("ssn", "Social Security Number")], WSHOP_ORDER_KNOWN_EXTRA_DATA_KEYS=[("wrapping_color", "Wrapping Color")], ): known_data = dict(order.get_known_additional_data()) assert ("Instruction" in known_data) assert ("Social Security Number" in known_data) assert ("Wrapping Color" in known_data)
def test_get_by_order_date(admin_user): shop = get_default_shop() today = dt.today() yesterday = dt.today() - datetime.timedelta(days=1) for i in range(1, 10): order = create_empty_order(shop=shop) order.order_date = yesterday order.save() order = create_empty_order(shop=shop) order.save() client = _get_client(admin_user) response = client.get("/api/wshop/order/", data={"date": today}) assert response.status_code == status.HTTP_200_OK order_data = json.loads(response.content.decode("utf-8")) assert len(order_data) == 1 assert order_data[0].get("id") == order.id assert order_data[0].get("identifier") == order.identifier response = client.get("/api/wshop/order/", data={"date": yesterday}) assert response.status_code == status.HTTP_200_OK order_data = json.loads(response.content.decode("utf-8")) assert len(order_data) == 9
def test_product_detail(browser, admin_user, live_server, settings): activate(settings.PARLER_DEFAULT_LANGUAGE_CODE) shop = get_default_shop() order = create_empty_order(shop=shop) order.save() initialize_admin_browser_test(browser, live_server, settings) url = reverse("wshop_admin:order.detail", kwargs={"pk": order.pk}) browser.visit("%s%s" % (live_server, url)) wait_until_condition( browser, condition=lambda x: x.is_text_present("Order %s" % order.pk)) change_addresses(live_server, browser, order) set_status(browser, order, OrderStatus.objects.get_default_processing()) assert order.can_set_complete() set_status(browser, order, OrderStatus.objects.get_default_complete())
def _get_order(shop, supplier, stocked=False): order = create_empty_order(shop=shop) order.full_clean() order.save() for product_data in _get_product_data(stocked): quantity = product_data.pop("quantity") product = create_product( sku=product_data.pop("sku"), shop=shop, supplier=supplier, default_price=3.33, **product_data) add_product_to_order(order, supplier, product, quantity=quantity, taxless_base_unit_price=1) order.cache_prices() order.check_all_verified() order.save() return order
def test_delete_toolbar_button(rf, admin_user, view_cls, get_method, method_attr): method = get_method() assert method.can_delete() view = view_cls.as_view() request = apply_request_middleware(rf.get("/"), user=admin_user) check_for_delete(view, request, method) # Create order for method and test the can_delete and edit view order = create_empty_order() setattr(order, method_attr, method) order.save() assert not method.can_delete() check_for_delete(view, request, method) # Make sure that the actual delete is also blocked with pytest.raises(ProtectedError): method.delete()
def test_empty_order(): order = create_empty_order() order.save() with pytest.raises(NoProductsToShipException): order.create_shipment_of_all_products() with pytest.raises(NoProductsToShipException): order.create_shipment(supplier=None, product_quantities={1: 0}) assert order.can_edit() order.set_canceled() assert not order.can_edit(), "Can't edit canceled order" assert not order.can_set_complete(), "Can't process canceled order" order.set_canceled() # Again! (This should be a no-op) order.delete() assert order.pk and order.deleted, "Order is soft-deleted" order.delete() # Again! (This, too, should be a no-op) assert not order.get_available_shipping_methods() assert not order.get_available_shipping_methods()
def _get_order(shop, supplier, has_price): order = create_empty_order(shop=shop) order.full_clean() order.save() for product_data in _get_product_data(has_price): quantity = product_data.pop("quantity") tax_rate = product_data.pop("tax_rate") product = create_product( sku=product_data.pop("sku"), shop=shop, supplier=supplier, **product_data) add_product_to_order( order, supplier, product, quantity=quantity, taxless_base_unit_price=product_data["default_price"], tax_rate=tax_rate) order.cache_prices() order.check_all_verified() order.save() return order
def test_line_discount_more(): order = create_empty_order() order.save() ol = OrderLine(order=order, type=OrderLineType.OTHER) ol.quantity = 5 ol.base_unit_price = order.shop.create_price(30) ol.discount_amount = order.shop.create_price(50) ol.save() currency = order.shop.currency assert ol.taxless_base_unit_price == TaxlessPrice(30, currency) assert ol.taxless_discount_amount == TaxlessPrice(50, currency) assert ol.taxless_price == TaxlessPrice(5 * 30 - 50, currency) order_line_tax = OrderLineTax.from_tax( get_default_tax(), ol.taxless_price.amount, order_line=ol) order_line_tax.save() ol.taxes.add(order_line_tax) assert ol.taxless_discount_amount == TaxlessPrice(50, currency) assert ol.taxful_discount_amount == TaxfulPrice(75, currency) assert ol.taxless_price == TaxlessPrice(100, currency) assert ol.taxful_price == TaxfulPrice(150, currency) assert ol.taxless_base_unit_price == TaxlessPrice(30, currency) assert ol.taxful_base_unit_price == TaxfulPrice(45, currency)
def test_order_with_only_unshippable_products(): shop = get_default_shop() supplier = get_default_supplier() order = create_empty_order(shop=shop) order.full_clean() order.save() product = create_product( "unshippable", shop=shop, supplier=supplier, default_price=5.55) product.shipping_mode = ShippingMode.NOT_SHIPPED product.save() add_product_to_order(order, supplier, product, quantity=4, taxless_base_unit_price=3) order.cache_prices() order.check_all_verified() order.save() assert not order.can_create_shipment() assert order.can_set_complete()
def test_rounding_with_taxes(prices): shop = get_default_shop() supplier = get_default_supplier() order = create_empty_order(shop=shop) order.save() product = create_product("test_sku", shop=shop, supplier=supplier) tax_rate = Decimal("0.22222") for x, price in enumerate(prices): add_product_to_order(order, supplier, product, quantity=Decimal("2.22"), taxless_base_unit_price=Decimal(price), tax_rate=tax_rate) order.cache_prices() for x, order_line in enumerate(order.lines.all().order_by("ordering")): # Check that total prices calculated from priceful parts still matches assert _get_taxless_price(order_line) == order_line.taxless_price assert _get_taxful_price(order_line) == order_line.taxful_price assert order_line.price == ( order_line.base_unit_price * order_line.quantity - order_line.discount_amount)
def test_line_discount(): order = create_empty_order(prices_include_tax=False) order.save() currency = order.shop.currency ol = OrderLine( order=order, type=OrderLineType.OTHER, quantity=5, text="Thing" ) ol.discount_amount = order.shop.create_price(50) ol.base_unit_price = order.shop.create_price(40) ol.save() order_line_tax = OrderLineTax.from_tax( get_default_tax(), ol.taxless_price.amount, order_line=ol) order_line_tax.save() ol.taxes.add(order_line_tax) assert ol.taxless_discount_amount == order.shop.create_price(50) assert ol.taxful_discount_amount == TaxfulPrice(75, currency) assert ol.taxless_price == order.shop.create_price(150) assert ol.taxful_price == TaxfulPrice(150 + 75, currency) assert ol.taxless_base_unit_price == order.shop.create_price(40) assert ol.taxful_base_unit_price == TaxfulPrice(60, currency) assert "Thing" in six.text_type(ol)
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 test_rounding(prices): expected = 0 for p in prices: expected += bankers_round(p, 2) order = create_empty_order(prices_include_tax=False) order.save() for x, price in enumerate(prices): ol = OrderLine(order=order, type=OrderLineType.OTHER, quantity=1, text="Thing", ordering=x, base_unit_price=order.shop.create_price(price)) ol.save() order.cache_prices() for x, order_line in enumerate(order.lines.all().order_by("ordering")): price = Decimal(prices[x]).quantize(Decimal(".1")**9) # make sure prices are in database with original precision assert order_line.base_unit_price == order.shop.create_price(price) # make sure the line taxless price is rounded assert order_line.taxless_price == order.shop.create_price( bankers_round(price, 2)) # Check that total prices calculated from priceful parts still matches assert _get_taxless_price(order_line) == order_line.taxless_price assert _get_taxful_price(order_line) == order_line.taxful_price # make sure the line price is rounded assert order_line.price == order.shop.create_price(price) # make sure order total is rounded assert order.taxless_total_price == order.shop.create_price( bankers_round(expected, 2))
def test_anon_disabling(): with override_settings(WSHOP_ALLOW_ANONYMOUS_ORDERS=False): with pytest.raises(ValidationError): order = create_empty_order() order.save()
def _create_order_for_day(shop, day): order = create_empty_order(shop) order.order_date = day order.save()
def test_ref_lengths(): from wshop.admin.modules.settings import consts from wshop.admin.modules.settings.enums import OrderReferenceNumberMethod # clear shop configurations shop = get_default_shop() ConfigurationItem.objects.filter(shop=shop).delete() order = create_empty_order(shop=shop) order.save() order.reference_number = None order.save() ref_number = get_reference_number(order) # by default we return "unique" assert len(ref_number) == 17 + 1 # unique ref + checksum order.reference_number = None order.save() configuration.set(shop, consts.ORDER_REFERENCE_NUMBER_METHOD_FIELD, OrderReferenceNumberMethod.UNIQUE.value) ref_number = get_reference_number(order) assert len(ref_number) == 17 + 1 # unique ref + checksum order.reference_number = None order.save() configuration.set(shop, consts.ORDER_REFERENCE_NUMBER_LENGTH_FIELD, 25) ref_number = get_reference_number(order) assert len(ref_number) == 25 + 1 # unique ref + checksum order.reference_number = None order.save() configuration.set(shop, consts.ORDER_REFERENCE_NUMBER_LENGTH_FIELD, 19) ref_number = get_reference_number(order) assert len(ref_number) == 19 + 1 # Finnish case order.reference_number = None order.save() configuration.set(shop, consts.ORDER_REFERENCE_NUMBER_METHOD_FIELD, OrderReferenceNumberMethod.RUNNING.value) ref_number = get_reference_number(order) assert len(ref_number) == 19 + 1 order.reference_number = None order.save() configuration.set(shop, consts.ORDER_REFERENCE_NUMBER_PREFIX_FIELD, "123") ref_number = get_reference_number(order) assert len(ref_number) == 19 + 1 order.reference_number = None order.save() configuration.set(shop, consts.ORDER_REFERENCE_NUMBER_PREFIX_FIELD, 123) ref_number = get_reference_number(order) assert len(ref_number) == 19 + 1 # Finnish case order.reference_number = None order.save() # reset prefix configuration.set(shop, consts.ORDER_REFERENCE_NUMBER_PREFIX_FIELD, "") configuration.set(shop, consts.ORDER_REFERENCE_NUMBER_METHOD_FIELD, OrderReferenceNumberMethod.SHOP_RUNNING.value) ref_number = get_reference_number(order) assert len(ref_number) == 19 + 1 # Finnish case order.reference_number = None order.save()
def test_get_best_selling_products(admin_user): shop1 = get_default_shop() shop2 = get_shop(True) person1 = create_random_person() person1.user = admin_user person1.save() supplier = create_simple_supplier("supplier1") client = _get_client(admin_user) # list best selling products response = client.get("/api/wshop/front/shop_products/best_selling/", {"shop": shop2.pk, "limit": 20}) assert response.status_code == status.HTTP_200_OK products = json.loads(response.content.decode("utf-8")) assert len(products["results"]) == 0 # THIS IS IMPORTANT! cache.clear() products = [create_product("Standard-%d" % x, supplier=supplier, shop=shop2) for x in range(10)] # create 1 product with 4 variations parent_product = create_product("ParentProduct1", supplier=supplier, shop=shop2) children = [create_product("SimpleVarChild-%d" % x, supplier=supplier, shop=shop2) for x in range(4)] for child in children: child.link_to_parent(parent_product) best_selling = defaultdict(int) # create orders with standard products for p_index in range(len(products)): order = create_empty_order(shop=shop2) order.save() qty = (len(products)-p_index) add_product_to_order(order, supplier, products[p_index], qty, Decimal(1.0)) order.create_shipment_of_all_products() order.status = OrderStatus.objects.get_default_complete() order.save(update_fields=("status",)) best_selling[products[p_index].id] = qty # create orders with variation products - the parent product is counted instead of its children for p_index in range(2): variation = random.choice(children) qty = 5 order = create_empty_order(shop=shop2) order.save() add_product_to_order(order, supplier, variation, qty, Decimal(1.0)) order.create_shipment_of_all_products() order.status = OrderStatus.objects.get_default_complete() order.save(update_fields=("status",)) best_selling[parent_product.id] = best_selling[parent_product.id] + qty # get the top 100 best selling products response = client.get("/api/wshop/front/shop_products/best_selling/", {"shop": shop2.pk, "limit": 100}) assert response.status_code == status.HTTP_200_OK products = json.loads(response.content.decode("utf-8")) assert len(products["results"]) == len(best_selling) # as we added less then 100, this must be true assert products["next"] is None # check the if all IDS are part of best selling for ix in range(len(products)): assert products["results"][ix]["product_id"] in best_selling.keys() # get the top 5 best selling products (we should get paginated results) response = client.get("/api/wshop/front/shop_products/best_selling/", {"shop": shop2.pk, "limit": 5}) assert response.status_code == status.HTTP_200_OK products = json.loads(response.content.decode("utf-8")) assert len(products["results"]) == 5 assert products["count"] == len(best_selling) assert products["next"] is not None sorted_best_selling_ids = [prod[0] for prod in sorted(best_selling.items(), key=lambda prod: -prod[1])][:5] # check the if all the 5 best sellers are part of best selling for ix in range(len(products)): assert products["results"][ix]["product_id"] in sorted_best_selling_ids