def test_order_statuses(admin_user): create_default_order_statuses() source = seed_source(admin_user) source.add_line( type=OrderLineType.PRODUCT, product=get_default_product(), supplier=get_default_supplier(), quantity=1, base_unit_price=source.create_price(10), ) source.add_line( type=OrderLineType.OTHER, quantity=1, base_unit_price=source.create_price(10), require_verification=True, ) creator = OrderCreator() order = creator.create_order(source) # new order, status/role is new/initial assert order.status.identifier == DefaultOrderStatus.INITIAL.value assert order.status.role == OrderStatusRole.INITIAL # FUTURE: order gets payment the status changes to processing/processing total = order.taxful_total_price.amount order.create_payment(total) assert order.status.identifier == DefaultOrderStatus.INITIAL.value assert order.status.role == OrderStatusRole.INITIAL # FUTURE: order is fully shipped the status changes to complete/complete order.create_shipment_of_all_products() assert order.status.identifier == DefaultOrderStatus.INITIAL.value assert order.status.role == OrderStatusRole.INITIAL
def test_order_statuses(admin_user): create_default_order_statuses() source = seed_source(admin_user) source.add_line( type=OrderLineType.PRODUCT, product=get_default_product(), supplier=get_default_supplier(), quantity=1, base_unit_price=source.create_price(10), ) source.add_line( type=OrderLineType.OTHER, quantity=1, base_unit_price=source.create_price(10), require_verification=True, ) creator = OrderCreator() order = creator.create_order(source) # new order, status/role is new/initial assert order.status.identifier == DefaultOrderStatus.INITIAL.value assert order.status.role == OrderStatusRole.INITIAL # FUTURE: order gets payment the status changes to processing/processing total = order.taxful_total_price.amount order.create_payment(total) assert order.status.identifier == DefaultOrderStatus.INITIAL.value assert order.status.role == OrderStatusRole.INITIAL # FUTURE: order is fully shipped the status changes to complete/complete order.create_shipment_of_all_products() assert order.status.identifier == DefaultOrderStatus.INITIAL.value assert order.status.role == OrderStatusRole.INITIAL
def test_basic_order_flow(with_company): create_default_order_statuses() n_orders_pre = Order.objects.count() populate_if_required() c = SmartClient() product_ids = _populate_client_basket(c) addresses_path = reverse("shuup:checkout", kwargs={"phase": "addresses"}) addresses_soup = c.soup(addresses_path) inputs = fill_address_inputs(addresses_soup, with_company=with_company) response = c.post(addresses_path, data=inputs) assert response.status_code == 302 # Should redirect forth methods_path = reverse("shuup:checkout", kwargs={"phase": "methods"}) methods_soup = c.soup(methods_path) assert c.post(methods_path, data=extract_form_fields(methods_soup)).status_code == 302 # Should redirect forth confirm_path = reverse("shuup:checkout", kwargs={"phase": "confirm"}) confirm_soup = c.soup(confirm_path) Product.objects.get(pk=product_ids[0]).soft_delete() assert c.post(confirm_path, data=extract_form_fields(confirm_soup)).status_code == 200 # user needs to reconfirm data = extract_form_fields(confirm_soup) data['product_ids'] = ','.join(product_ids[1:]) assert c.post(confirm_path, data=data).status_code == 302 # Should redirect forth n_orders_post = Order.objects.count() assert n_orders_post > n_orders_pre, "order was created"
def test_order_create_without_shipping_or_billing_method(admin_user): create_default_order_statuses() shop = get_default_shop() supplier = get_default_supplier() contact = create_random_person(locale="en_US", minimum_name_comp_len=5) product = create_product( sku=uuid4().hex, supplier=get_default_supplier(), shop=shop ) assert not Order.objects.count() client = _get_client(admin_user) lines = [ { "type": "product", "product": product.id, "supplier": supplier.id, "quantity": "1", "base_unit_price_value": "5.00" }, { "type": "product", "product": product.id, "supplier": supplier.id, "quantity": "2", "base_unit_price_value": "1.00", "discount_amount_value": "0.50" }, {"type": "other", "sku": "hello", "text": "A greeting", "quantity": 1, "base_unit_price_value": "3.5"}, {"type": "text", "text": "This was an order!", "quantity": 0}, ] response = client.post("/api/shuup/order/", content_type="application/json", data=json.dumps({ "shop": shop.pk, "customer": contact.pk, "lines": lines })) assert response.status_code == 201 assert Order.objects.count() == 1 order = Order.objects.first() assert order.shop == shop assert order.shipping_method is None assert order.payment_method is None assert order.customer == contact assert order.creator == admin_user assert order.billing_address == contact.default_billing_address.to_immutable() assert order.shipping_address == contact.default_shipping_address.to_immutable() assert order.payment_status == PaymentStatus.NOT_PAID assert order.shipping_status == ShippingStatus.NOT_SHIPPED assert order.status == OrderStatus.objects.get_default_initial() assert order.taxful_total_price_value == decimal.Decimal(10) assert order.lines.count() == 4 # 2 product lines, 2 other lines for idx, line in enumerate(order.lines.all()[:4]): assert line.quantity == decimal.Decimal(lines[idx].get("quantity")) assert line.base_unit_price_value == decimal.Decimal(lines[idx].get("base_unit_price_value", 0)) assert line.discount_amount_value == decimal.Decimal(lines[idx].get("discount_amount_value", 0))
def test_create_order(admin_user, settings, target_customer): configure(settings) shop = factories.get_default_shop() basket = factories.get_basket() factories.create_default_order_statuses() shop_product = factories.get_default_shop_product() shop_product.default_price = TaxfulPrice(1, shop.currency) shop_product.save() client = _get_client(admin_user) # add shop product payload = {'shop_product': shop_product.id} if target_customer == "other": target = factories.create_random_person() payload["customer_id"] = target.pk else: target = get_person_contact(admin_user) response = client.post( '/api/shuup/basket/{}-{}/add/'.format(shop.pk, basket.key), payload) assert response.status_code == status.HTTP_200_OK response_data = json.loads(response.content.decode("utf-8")) assert len(response_data["items"]) == 1 response = client.post( '/api/shuup/basket/{}-{}/create_order/'.format(shop.pk, basket.key), payload) assert response.status_code == status.HTTP_400_BAD_REQUEST response_data = json.loads(response.content.decode("utf-8")) assert "errors" in response_data factories.get_default_payment_method() factories.get_default_shipping_method() response = client.post( '/api/shuup/basket/{}-{}/create_order/'.format(shop.pk, basket.key), payload) assert response.status_code == status.HTTP_201_CREATED response_data = json.loads(response.content.decode("utf-8")) basket.refresh_from_db() assert basket.finished order = Order.objects.get( reference_number=response_data["reference_number"]) assert order.status == OrderStatus.objects.get_default_initial() assert order.payment_status == PaymentStatus.NOT_PAID assert order.shipping_status == ShippingStatus.NOT_SHIPPED assert not order.payment_method assert not order.shipping_method assert float(order.taxful_total_price_value) == 1 assert order.customer == target assert order.orderer == get_person_contact(admin_user) assert order.creator == admin_user assert not order.billing_address assert not order.shipping_address
def test_create_order(admin_user, settings, target_customer): configure(settings) shop = factories.get_default_shop() basket = factories.get_basket() factories.create_default_order_statuses() shop_product = factories.get_default_shop_product() shop_product.default_price = TaxfulPrice(1, shop.currency) shop_product.save() client = _get_client(admin_user) # add shop product payload = { 'shop_product': shop_product.id } if target_customer == "other": target = factories.create_random_person() payload["customer_id"] = target.pk else: target = get_person_contact(admin_user) response = client.post('/api/shuup/basket/{}-{}/add/'.format(shop.pk, basket.key), payload) assert response.status_code == status.HTTP_200_OK response_data = json.loads(response.content.decode("utf-8")) assert len(response_data["items"]) == 1 response = client.post('/api/shuup/basket/{}-{}/create_order/'.format(shop.pk, basket.key), payload) assert response.status_code == status.HTTP_400_BAD_REQUEST response_data = json.loads(response.content.decode("utf-8")) assert "errors" in response_data factories.get_default_payment_method() factories.get_default_shipping_method() response = client.post('/api/shuup/basket/{}-{}/create_order/'.format(shop.pk, basket.key), payload) assert response.status_code == status.HTTP_201_CREATED response_data = json.loads(response.content.decode("utf-8")) basket.refresh_from_db() assert basket.finished order = Order.objects.get(reference_number=response_data["reference_number"]) assert order.status == OrderStatus.objects.get_default_initial() assert order.payment_status == PaymentStatus.NOT_PAID assert order.shipping_status == ShippingStatus.NOT_SHIPPED assert not order.payment_method assert not order.shipping_method assert float(order.taxful_total_price_value) == 1 assert order.customer == target assert order.orderer == get_person_contact(admin_user) assert order.creator == admin_user assert not order.billing_address assert not order.shipping_address
def test_checkout_empty_basket(rf): create_default_order_statuses() n_orders_pre = Order.objects.count() populate_if_required() c = SmartClient() product_ids = _populate_client_basket(c) addresses_path = reverse("shuup:checkout", kwargs={"phase": "addresses"}) addresses_soup = c.soup(addresses_path) inputs = fill_address_inputs(addresses_soup) for product_id in product_ids: Product.objects.get(pk=product_id).soft_delete() response, soup = c.response_and_soup(addresses_path, data=inputs, method="post") assert response.status_code == 200 # Should redirect forth assert b"Your shopping cart is empty." in soup.renderContents()
def test_create_without_a_contact(admin_user): create_default_order_statuses() shop = get_default_shop() sm = get_default_shipping_method() pm = get_default_payment_method() assert not Order.objects.count() client = _get_client(admin_user) lines = [ { "type": "other", "sku": "hello", "text": "A greeting", "quantity": 1, "base_unit_price_value": "3.5" }, ] response = client.post( "/api/shuup/order/", content_type="application/json", data=json.dumps({ "shop": shop.pk, "customer": None, "shipping_method": sm.pk, "payment_method": pm.pk, "lines": lines }), ) assert response.status_code == 201 assert Order.objects.count() == 1 order = Order.objects.first() assert order.shop == shop assert order.customer is None assert order.creator == admin_user assert order.shipping_method == sm assert order.payment_method == pm assert order.billing_address is None assert order.shipping_address is None assert order.payment_status == PaymentStatus.NOT_PAID assert order.shipping_status == ShippingStatus.NOT_SHIPPED assert order.status == OrderStatus.objects.get_default_initial() assert order.taxful_total_price_value == decimal.Decimal(3.5) assert order.lines.count( ) == 3 # shipping line, payment line, 2 product lines, 2 other lines for idx, line in enumerate(order.lines.all()[:1]): assert line.quantity == decimal.Decimal(lines[idx].get("quantity")) assert line.base_unit_price_value == decimal.Decimal(lines[idx].get( "base_unit_price_value", 0)) assert line.discount_amount_value == decimal.Decimal(lines[idx].get( "discount_amount_value", 0))
def test_order_create_without_default_address(admin_user): create_default_order_statuses() shop = get_default_shop() sm = get_default_shipping_method() pm = get_default_payment_method() contact = create_random_person(locale="en_US", minimum_name_comp_len=5) contact.default_billing_address = None contact.default_shipping_address = None contact.save() product = create_product( sku=printable_gibberish(), supplier=get_default_supplier(), shop=shop ) assert not Order.objects.count() client = _get_client(admin_user) lines = [ {"type": "product", "product": product.id, "quantity": "1", "base_unit_price_value": "5.00"}, {"type": "product", "product": product.id, "quantity": "2", "base_unit_price_value": "1.00", "discount_amount_value": "0.50"}, {"type": "other", "sku": "hello", "text": "A greeting", "quantity": 1, "base_unit_price_value": "3.5"}, {"type": "text", "text": "This was an order!", "quantity": 0}, ] response = client.post("/api/shuup/order/", content_type="application/json", data=json.dumps({ "shop": shop.pk, "shipping_method": sm.pk, "payment_method": pm.pk, "customer": contact.pk, "lines": lines })) assert response.status_code == 201 assert Order.objects.count() == 1 order = Order.objects.first() assert order.shop == shop assert order.shipping_method == sm assert order.payment_method == pm assert order.customer == contact assert order.creator == admin_user assert order.billing_address is None assert order.shipping_address is None assert order.payment_status == PaymentStatus.NOT_PAID assert order.shipping_status == ShippingStatus.NOT_SHIPPED assert order.status == OrderStatus.objects.get_default_initial() assert order.taxful_total_price_value == decimal.Decimal(10) assert order.lines.count() == 6 # shipping line, payment line, 2 product lines, 2 other lines for idx, line in enumerate(order.lines.all()[:4]): assert line.quantity == decimal.Decimal(lines[idx].get("quantity")) assert line.base_unit_price_value == decimal.Decimal(lines[idx].get("base_unit_price_value", 0)) assert line.discount_amount_value == decimal.Decimal(lines[idx].get("discount_amount_value", 0))
def test_basic_order_flow(with_company, with_signal): cache.clear() create_default_order_statuses() n_orders_pre = Order.objects.count() populate_if_required() c = SmartClient() product_ids = _populate_client_basket(c) addresses_path = reverse("shuup:checkout", kwargs={"phase": "addresses"}) addresses_soup = c.soup(addresses_path) inputs = fill_address_inputs(addresses_soup, with_company=with_company) response = c.post(addresses_path, data=inputs) assert response.status_code == 302 # Should redirect forth # Make sure the address is initialized from storage # Go back to addresses right before back to methods c.soup(addresses_path) methods_path = reverse("shuup:checkout", kwargs={"phase": "methods"}) methods_soup = c.soup(methods_path) assert c.post(methods_path, data=extract_form_fields( methods_soup)).status_code == 302 # Should redirect forth if with_signal: checkout_complete.connect(checkout_complete_signal, dispatch_uid="checkout_complete_signal") confirm_path = reverse("shuup:checkout", kwargs={"phase": "confirm"}) confirm_soup = c.soup(confirm_path) Product.objects.get(pk=product_ids[0]).soft_delete() assert c.post(confirm_path, data=extract_form_fields( confirm_soup)).status_code == 200 # user needs to reconfirm data = extract_form_fields(confirm_soup) data['accept_terms'] = True data['product_ids'] = ','.join(product_ids[1:]) assert c.post(confirm_path, data=data).status_code == 302 # Should redirect forth n_orders_post = Order.objects.count() assert n_orders_post > n_orders_pre, "order was created" order = Order.objects.first() expected_ip = "127.0.0.2" if with_signal else "127.0.0.1" assert order.ip_address == expected_ip if with_signal: checkout_complete.disconnect(dispatch_uid="checkout_complete_signal")
def test_custom_status(language): """Test custom order statuses.""" with translation.override(language): create_default_order_statuses() status = OrderStatus.objects.create( identifier="test-identifier", role=OrderStatusRole.INITIAL, name="Test Name", public_name="Test Public Name", ordering=10, is_active=False, default=False, ) test_new_dentifier = "test-new-identifier" test_new_name = "Test New Name" test_new_public_name = "Test New Public Name" test_new_role = OrderStatusRole.PROCESSING test_new_ordering = 100 test_new_is_active = True frm = OrderStatusForm( languages=[language], instance=status, default_language=language, data={ "name__{}".format(language): test_new_name, "public_name__{}".format(language): test_new_public_name, "identifier": test_new_dentifier, "role": test_new_role, "ordering": test_new_ordering, "is_active": test_new_is_active, "allowed_next_statuses": [o for o in OrderStatus.objects.all()], }, ) assert frm.is_valid() assert not frm.errors frm.save(commit=False) assert frm.instance.name == test_new_name assert frm.instance.public_name == test_new_public_name assert frm.instance.identifier == test_new_dentifier assert frm.instance.role == test_new_role assert frm.instance.ordering == test_new_ordering assert frm.instance.is_active == test_new_is_active assert OrderStatus.objects.get_default_initial( ) in frm.instance.allowed_next_statuses.all() assert OrderStatus.objects.get_default_processing( ) in frm.instance.allowed_next_statuses.all()
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/shuup/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/shuup/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/shuup/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/shuup/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_single_default_status_for_role(): create_default_order_statuses() new_default_cancel = OrderStatus.objects.create( identifier="foo", role=OrderStatusRole.CANCELED, name="foo", default=True) assert new_default_cancel.default assert OrderStatus.objects.get_default_canceled() == new_default_cancel new_default_cancel.delete() # We can use this weird moment to cover the "no default" case, yay with pytest.raises(ObjectDoesNotExist): OrderStatus.objects.get_default_canceled() old_cancel = OrderStatus.objects.get(identifier="canc") assert not old_cancel.default # This will have been reset when another status became the default old_cancel.default = True old_cancel.save()
def test_basic_order_flow(with_company, with_signal): cache.clear() create_default_order_statuses() n_orders_pre = Order.objects.count() populate_if_required() c = SmartClient() product_ids = _populate_client_basket(c) addresses_path = reverse("shuup:checkout", kwargs={"phase": "addresses"}) addresses_soup = c.soup(addresses_path) inputs = fill_address_inputs(addresses_soup, with_company=with_company) response = c.post(addresses_path, data=inputs) assert response.status_code == 302 # Should redirect forth # Make sure the address is initialized from storage # Go back to addresses right before back to methods c.soup(addresses_path) methods_path = reverse("shuup:checkout", kwargs={"phase": "methods"}) methods_soup = c.soup(methods_path) assert c.post(methods_path, data=extract_form_fields(methods_soup)).status_code == 302 # Should redirect forth if with_signal: checkout_complete.connect(checkout_complete_signal, dispatch_uid="checkout_complete_signal") confirm_path = reverse("shuup:checkout", kwargs={"phase": "confirm"}) confirm_soup = c.soup(confirm_path) Product.objects.get(pk=product_ids[0]).soft_delete() assert c.post(confirm_path, data=extract_form_fields(confirm_soup)).status_code == 200 # user needs to reconfirm data = extract_form_fields(confirm_soup) data['product_ids'] = ','.join(product_ids[1:]) assert c.post(confirm_path, data=data).status_code == 302 # Should redirect forth n_orders_post = Order.objects.count() assert n_orders_post > n_orders_pre, "order was created" order = Order.objects.first() expected_ip = "127.0.0.2" if with_signal else "127.0.0.1" assert order.ip_address == expected_ip if with_signal: checkout_complete.disconnect(dispatch_uid="checkout_complete_signal")
def test_single_default_status_for_role(): create_default_order_statuses() new_default_cancel = OrderStatus.objects.create( identifier="foo", role=OrderStatusRole.CANCELED, name="foo", default=True ) assert new_default_cancel.default assert OrderStatus.objects.get_default_canceled() == new_default_cancel new_default_cancel.delete() # We can use this weird moment to cover the "no default" case, yay with pytest.raises(ObjectDoesNotExist): OrderStatus.objects.get_default_canceled() old_cancel = OrderStatus.objects.get(identifier=DefaultOrderStatus.CANCELED.value) assert not old_cancel.default # This will have been reset when another status became the default old_cancel.default = True old_cancel.save()
def test_custom_status(language): """Test custom order statuses.""" with translation.override(language): create_default_order_statuses() status = OrderStatus.objects.create( identifier='test-identifier', role=OrderStatusRole.INITIAL, name='Test Name', public_name='Test Public Name', ordering=10, is_active=False, default=False, ) test_new_dentifier = 'test-new-identifier' test_new_name = 'Test New Name' test_new_public_name = 'Test New Public Name' test_new_role = OrderStatusRole.PROCESSING test_new_ordering = 100 test_new_is_active = True frm = OrderStatusForm( languages=[language], instance=status, default_language=language, data={ 'name__{}'.format(language): test_new_name, 'public_name__{}'.format(language): test_new_public_name, "identifier": test_new_dentifier, "role": test_new_role, "ordering": test_new_ordering, "is_active": test_new_is_active, } ) assert frm.is_valid() assert not frm.errors frm.save(commit=False) assert frm.instance.name == test_new_name assert frm.instance.public_name == test_new_public_name assert frm.instance.identifier == test_new_dentifier assert frm.instance.role == test_new_role assert frm.instance.ordering == test_new_ordering assert frm.instance.is_active == test_new_is_active
def test_custom_status(language): """Test custom order statuses.""" with translation.override(language): create_default_order_statuses() status = OrderStatus.objects.create( identifier='test-identifier', role=OrderStatusRole.INITIAL, name='Test Name', public_name='Test Public Name', ordering=10, is_active=False, default=False, ) test_new_dentifier = 'test-new-identifier' test_new_name = 'Test New Name' test_new_public_name = 'Test New Public Name' test_new_role = OrderStatusRole.PROCESSING test_new_ordering = 100 test_new_is_active = True frm = OrderStatusForm( languages=[language], instance=status, default_language=language, data={ 'name__{}'.format(language): test_new_name, 'public_name__{}'.format(language): test_new_public_name, "identifier": test_new_dentifier, "role": test_new_role, "ordering": test_new_ordering, "is_active": test_new_is_active, } ) assert frm.is_valid() assert not frm.errors frm.save(commit=False) assert frm.instance.name == test_new_name assert frm.instance.public_name == test_new_public_name assert frm.instance.identifier == test_new_dentifier assert frm.instance.role == test_new_role assert frm.instance.ordering == test_new_ordering assert frm.instance.is_active == test_new_is_active
def test_default_status(language): """Test default order statuses. Check can change default statuses `name` and `public_name` fields but can't change other attributes. """ from django.utils.translation import activate activate(language) create_default_order_statuses() test_new_name = "Test New Name" test_new_public_name = "Test New Public Name" for status in OrderStatus.objects.all(): frm = OrderStatusForm( languages=[language], instance=status, default_language=language, data={ "name__{}".format(language): test_new_name, "public_name__{}".format(language): test_new_public_name, "identifier": "test new identifier", "role": OrderStatusRole.NONE, "ordering": 100, "is_active": not status.is_active, "allowed_next_statuses": [o for o in OrderStatus.objects.none()], }, ) assert frm.is_valid() assert not frm.errors frm.save(commit=False) assert frm.instance.name == test_new_name assert frm.instance.public_name == test_new_public_name assert frm.instance.identifier == status.identifier assert frm.instance.role == status.role assert frm.instance.ordering == status.ordering assert frm.instance.is_active == status.is_active
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/shuup/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/shuup/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/shuup/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/shuup/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_default_status(language): """Test default order statuses. Check can change default statuses `name` and `public_name` fields but can't change other attributes. """ from django.utils.translation import activate activate(language) create_default_order_statuses() test_new_name = 'Test New Name' test_new_public_name = 'Test New Public Name' for status in OrderStatus.objects.all(): frm = OrderStatusForm( languages=[language], instance=status, default_language=language, data={ 'name__{}'.format(language): test_new_name, 'public_name__{}'.format(language): test_new_public_name, "identifier": "test new identifier", "role": OrderStatusRole.NONE, "ordering": 100, "is_active": not status.is_active, } ) assert frm.is_valid() assert not frm.errors frm.save(commit=False) assert frm.instance.name == test_new_name assert frm.instance.public_name == test_new_public_name assert frm.instance.identifier == status.identifier assert frm.instance.role == status.role assert frm.instance.ordering == status.ordering assert frm.instance.is_active == status.is_active
def test_create_without_a_contact(admin_user): create_default_order_statuses() shop = get_default_shop() sm = get_default_shipping_method() pm = get_default_payment_method() assert not Order.objects.count() client = _get_client(admin_user) lines = [ {"type": "other", "sku": "hello", "text": "A greeting", "quantity": 1, "base_unit_price_value": "3.5"}, ] response = client.post("/api/shuup/order/", content_type="application/json", data=json.dumps({ "shop": shop.pk, "customer": None, "shipping_method": sm.pk, "payment_method": pm.pk, "lines": lines })) assert response.status_code == 201 assert Order.objects.count() == 1 order = Order.objects.first() assert order.shop == shop assert order.customer == None assert order.creator == admin_user assert order.shipping_method == sm assert order.payment_method == pm assert order.billing_address == None assert order.shipping_address == None assert order.payment_status == PaymentStatus.NOT_PAID assert order.shipping_status == ShippingStatus.NOT_SHIPPED assert order.status == OrderStatus.objects.get_default_initial() assert order.taxful_total_price_value == decimal.Decimal(3.5) assert order.lines.count() == 3 # shipping line, payment line, 2 product lines, 2 other lines for idx, line in enumerate(order.lines.all()[:1]): assert line.quantity == decimal.Decimal(lines[idx].get("quantity")) assert line.base_unit_price_value == decimal.Decimal(lines[idx].get("base_unit_price_value", 0)) assert line.discount_amount_value == decimal.Decimal(lines[idx].get("discount_amount_value", 0))
def test_order_flow_with_phases(get_shipping_method, shipping_data, get_payment_method, payment_data): create_default_order_statuses() populate_if_required() c = SmartClient() _populate_client_basket(c) # Create methods shipping_method = get_shipping_method() payment_method = get_payment_method() # Resolve paths addresses_path = reverse("shuup:checkout", kwargs={"phase": "addresses"}) methods_path = reverse("shuup:checkout", kwargs={"phase": "methods"}) shipping_path = reverse("shuup:checkout", kwargs={"phase": "shipping"}) payment_path = reverse("shuup:checkout", kwargs={"phase": "payment"}) confirm_path = reverse("shuup: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 to methods" # Phase: Methods response = c.get(methods_path) assert response.status_code == 200 response = c.post( methods_path, data={ "shipping_method": shipping_method.pk, "payment_method": payment_method.pk } ) assert response.status_code == 302, "Methods phase should redirect forth" if isinstance(shipping_method.carrier, CarrierWithCheckoutPhase): # Phase: Shipping response = c.get(shipping_path) assert response.status_code == 200 response = c.post(shipping_path, data=shipping_data) assert response.status_code == 302, "Payments phase should redirect forth" if isinstance(payment_method.payment_processor, PaymentWithCheckoutPhase): # Phase: payment response = c.get(payment_path) assert response.status_code == 200 response = c.post(payment_path, data=payment_data) assert response.status_code == 302, "Payments phase should redirect forth" # Phase: Confirm assert Order.objects.count() == 0 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" order = Order.objects.first() if isinstance(shipping_method.carrier, CarrierWithCheckoutPhase): assert order.shipping_data.get("input_value") == "20540" if isinstance(payment_method.payment_processor, PaymentWithCheckoutPhase): assert order.payment_data.get("input_value") assert order.payment_status == PaymentStatus.NOT_PAID # Resolve order specific paths (payment and complete) process_payment_path = reverse( "shuup:order_process_payment", kwargs={"pk": order.pk, "key": order.key}) process_payment_return_path = reverse( "shuup:order_process_payment_return", kwargs={"pk": order.pk, "key": order.key}) order_complete_path = reverse( "shuup: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_create_order(admin_user, target_customer): with override_settings(**REQUIRED_SETTINGS): set_configuration() factories.create_default_order_statuses() shop = factories.get_default_shop() client = _get_client(admin_user) # Create basket for target customer payload = {"shop": shop.pk} target = orderer = get_person_contact(admin_user) if target_customer == "other_person": target = orderer = factories.create_random_person() payload["customer"] = target.pk elif target_customer == "company": target = factories.create_random_company() orderer = factories.create_random_person() payload.update({ "customer": target.pk, "orderer": orderer.pk }) target.members.add(orderer) response = client.post("/api/shuup/basket/new/", payload) assert response.status_code == status.HTTP_201_CREATED basket_data = json.loads(response.content.decode("utf-8")) basket = Basket.objects.first() assert basket.key == basket_data["uuid"].split("-")[1] assert basket.customer == target assert basket.orderer == orderer shop_product = factories.get_default_shop_product() shop_product.default_price = TaxfulPrice(1, shop.currency) shop_product.save() # Add shop product to basket payload = {"shop_product": shop_product.id} response = client.post("/api/shuup/basket/{}-{}/add/".format(shop.pk, basket.key), payload) assert response.status_code == status.HTTP_200_OK response_data = json.loads(response.content.decode("utf-8")) assert len(response_data["items"]) == 1 # Create order from basket response = client.post("/api/shuup/basket/{}-{}/create_order/".format(shop.pk, basket.key), payload) assert response.status_code == status.HTTP_400_BAD_REQUEST response_data = json.loads(response.content.decode("utf-8")) assert "errors" in response_data factories.get_default_payment_method() factories.get_default_shipping_method() response = client.post("/api/shuup/basket/{}-{}/create_order/".format(shop.pk, basket.key), payload) assert response.status_code == status.HTTP_201_CREATED response_data = json.loads(response.content.decode("utf-8")) basket.refresh_from_db() assert basket.finished order = Order.objects.get(reference_number=response_data["reference_number"]) assert order.status == OrderStatus.objects.get_default_initial() assert order.payment_status == PaymentStatus.NOT_PAID assert order.shipping_status == ShippingStatus.NOT_SHIPPED assert not order.payment_method assert not order.shipping_method assert float(order.taxful_total_price_value) == 1 assert order.customer == target assert order.orderer == orderer assert order.creator == admin_user assert not order.billing_address assert not order.shipping_address
def test_order_statuses_are_translatable(): create_default_order_statuses() assert OrderStatus.objects.translated(get_language()).count() == OrderStatus.objects.count()
def test_order_flow_with_multiple_suppliers(): cache.clear() shop = factories.get_default_shop() factories.create_default_order_statuses() factories.get_default_payment_method() factories.get_default_shipping_method() n_orders_pre = Order.objects.count() product = factories.create_product("sku", shop=shop, default_price=30) shop_product = product.get_shop_instance(shop) # Activate show supplier info for front assert ThemeSettings.objects.count() == 1 theme_settings = ThemeSettings.objects.first() theme_settings.update_settings({"show_supplier_info": True}) supplier_data = [ ("Johnny Inc", 30), ("Mike Inc", 10), ("Simon Inc", 20), ] for name, product_price in supplier_data: supplier = Supplier.objects.create(name=name) shop_product.suppliers.add(supplier) SupplierPrice.objects.create(supplier=supplier, shop=shop, product=product, amount_value=product_price) strategy = "shuup.testing.supplier_pricing.supplier_strategy:CheapestSupplierPriceSupplierStrategy" with override_settings(SHUUP_PRICING_MODULE="supplier_pricing", SHUUP_SHOP_PRODUCT_SUPPLIERS_STRATEGY=strategy): # Ok so cheapest price should be default supplier expected_supplier = shop_product.get_supplier() assert expected_supplier.name == "Mike Inc" with override_current_theme_class( ClassicGrayTheme, shop): # Ensure settings is refreshed from DB c = SmartClient() # Case 1: use default supplier _add_to_basket(c, product.pk, 2) order = _complete_checkout(c, n_orders_pre + 1) assert order product_lines = order.lines.products() assert len(product_lines) == 1 assert product_lines[0].supplier.pk == expected_supplier.pk assert product_lines[0].base_unit_price_value == decimal.Decimal( "10") # Case 2: force supplier to Johnny Inc johnny_supplier = Supplier.objects.filter( name="Johnny Inc").first() _add_to_basket(c, product.pk, 3, johnny_supplier) order = _complete_checkout(c, n_orders_pre + 2) assert order product_lines = order.lines.products() assert len(product_lines) == 1 assert product_lines[0].supplier.pk == johnny_supplier.pk assert product_lines[0].base_unit_price_value == decimal.Decimal( "30") # Case 3: order 2 pcs from Mike and 3 pcs from Simon Inc mike_supplier = Supplier.objects.filter(name="Mike Inc").first() _add_to_basket(c, product.pk, 2, mike_supplier) simon_supplier = Supplier.objects.filter(name="Simon Inc").first() _add_to_basket(c, product.pk, 3, simon_supplier) order = _complete_checkout(c, n_orders_pre + 3) assert order assert order.taxful_total_price_value == decimal.Decimal( "80") # Math: 2x10e + 3x20e product_lines = order.lines.products() assert len(product_lines) == 2 mikes_line = [ line for line in product_lines if line.supplier.pk == mike_supplier.pk ][0] assert mikes_line assert mikes_line.quantity == 2 assert mikes_line.base_unit_price_value == decimal.Decimal("10") simon_line = [ line for line in product_lines if line.supplier.pk == simon_supplier.pk ][0] assert simon_line assert simon_line.quantity == 3 assert simon_line.base_unit_price_value == decimal.Decimal("20")
def test_create_order(admin_user, currency): create_default_order_statuses() shop = get_default_shop() shop.currency = currency tax = get_default_tax() Currency.objects.get_or_create(code=currency, decimal_places=2) shop.save() sm = get_default_shipping_method() pm = get_default_payment_method() contact = create_random_person(locale="en_US", minimum_name_comp_len=5) product = create_product(sku=printable_gibberish(), supplier=get_default_supplier(), shop=shop) assert not Order.objects.count() client = _get_client(admin_user) lines = [ { "type": "product", "product": product.id, "quantity": "1", "base_unit_price_value": "5.00" }, { "type": "product", "product": product.id, "quantity": "2", "base_unit_price_value": "1.00", "discount_amount_value": "0.50" }, { "type": "other", "sku": "hello", "text": "A greeting", "quantity": 1, "base_unit_price_value": "3.5" }, { "type": "text", "text": "This was an order!", "quantity": 0 }, ] response = client.post("/api/shuup/order/", content_type="application/json", data=json.dumps({ "shop": shop.pk, "shipping_method": sm.pk, "payment_method": pm.pk, "customer": contact.pk, "lines": lines })) assert response.status_code == 201 assert Order.objects.count() == 1 order = Order.objects.first() assert order.shop == shop assert order.shipping_method == sm assert order.payment_method == pm assert order.customer == contact assert order.creator == admin_user assert order.billing_address == contact.default_billing_address.to_immutable( ) assert order.shipping_address == contact.default_shipping_address.to_immutable( ) assert order.payment_status == PaymentStatus.NOT_PAID assert order.shipping_status == ShippingStatus.NOT_SHIPPED assert order.status == OrderStatus.objects.get_default_initial() assert order.taxful_total_price_value == decimal.Decimal(10) assert order.lines.count( ) == 6 # shipping line, payment line, 2 product lines, 2 other lines assert order.currency == currency for idx, line in enumerate(order.lines.all()[:4]): assert line.quantity == decimal.Decimal(lines[idx].get("quantity")) assert line.base_unit_price_value == decimal.Decimal(lines[idx].get( "base_unit_price_value", 0)) assert line.discount_amount_value == decimal.Decimal(lines[idx].get( "discount_amount_value", 0)) # Test tax summary response_data = json.loads(response.content.decode("utf-8")) # Tax summary should not be present here assert "summary" not in response_data response = client.get('/api/shuup/order/{}/taxes/'.format(order.pk)) assert response.status_code == status.HTTP_200_OK response_data = json.loads(response.content.decode("utf-8")) assert "lines" in response_data assert "summary" in response_data line_summary = response_data["lines"] summary = response_data["summary"] first_tax_summary = summary[0] assert int(first_tax_summary["tax_id"]) == tax.id assert first_tax_summary["tax_rate"] == tax.rate first_line_summary = line_summary[0] assert "tax" in first_line_summary
def test_order_flow_with_multiple_suppliers(): cache.clear() shop = factories.get_default_shop() factories.create_default_order_statuses() factories.get_default_payment_method() factories.get_default_shipping_method() n_orders_pre = Order.objects.count() product = factories.create_product("sku", shop=shop, default_price=30) shop_product = product.get_shop_instance(shop) # Activate show supplier info for front assert ThemeSettings.objects.count() == 1 theme_settings = ThemeSettings.objects.first() theme_settings.update_settings({"show_supplier_info": True}) supplier_data = [ ("Johnny Inc", 30), ("Mike Inc", 10), ("Simon Inc", 20), ] for name, product_price in supplier_data: supplier = Supplier.objects.create(name=name) shop_product.suppliers.add(supplier) SupplierPrice.objects.create(supplier=supplier, shop=shop, product=product, amount_value=product_price) strategy = "shuup.testing.supplier_pricing.supplier_strategy:CheapestSupplierPriceSupplierStrategy" with override_settings(SHUUP_PRICING_MODULE="supplier_pricing", SHUUP_SHOP_PRODUCT_SUPPLIERS_STRATEGY=strategy): # Ok so cheapest price should be default supplier expected_supplier = shop_product.get_supplier() assert expected_supplier.name == "Mike Inc" with override_current_theme_class(ClassicGrayTheme, shop): # Ensure settings is refreshed from DB c = SmartClient() # Case 1: use default supplier _add_to_basket(c, product.pk, 2) order = _complete_checkout(c, n_orders_pre + 1) assert order product_lines = order.lines.products() assert len(product_lines) == 1 assert product_lines[0].supplier.pk == expected_supplier.pk assert product_lines[0].base_unit_price_value == decimal.Decimal("10") # Case 2: force supplier to Johnny Inc johnny_supplier = Supplier.objects.filter(name="Johnny Inc").first() _add_to_basket(c, product.pk, 3, johnny_supplier) order = _complete_checkout(c, n_orders_pre + 2) assert order product_lines = order.lines.products() assert len(product_lines) == 1 assert product_lines[0].supplier.pk == johnny_supplier.pk assert product_lines[0].base_unit_price_value == decimal.Decimal("30") # Case 3: order 2 pcs from Mike and 3 pcs from Simon Inc mike_supplier = Supplier.objects.filter(name="Mike Inc").first() _add_to_basket(c, product.pk, 2, mike_supplier) simon_supplier = Supplier.objects.filter(name="Simon Inc").first() _add_to_basket(c, product.pk, 3, simon_supplier) order = _complete_checkout(c, n_orders_pre + 3) assert order assert order.taxful_total_price_value == decimal.Decimal("80") # Math: 2x10e + 3x20e product_lines = order.lines.products() assert len(product_lines) == 2 mikes_line = [line for line in product_lines if line.supplier.pk == mike_supplier.pk][0] assert mikes_line assert mikes_line.quantity == 2 assert mikes_line.base_unit_price_value == decimal.Decimal("10") simon_line = [line for line in product_lines if line.supplier.pk == simon_supplier.pk][0] assert simon_line assert simon_line.quantity == 3 assert simon_line.base_unit_price_value == decimal.Decimal("20")
def test_order_statuses_are_translatable(): create_default_order_statuses() assert OrderStatus.objects.translated( get_language()).count() == OrderStatus.objects.count()
def test_create_order(admin_user, target_customer): set_configuration() factories.create_default_order_statuses() shop = factories.get_default_shop() client = _get_client(admin_user) # Create basket for target customer payload = {"shop": shop.pk} target = orderer = get_person_contact(admin_user) if target_customer == "other_person": target = orderer = factories.create_random_person() payload["customer"] = target.pk elif target_customer == "company": target = factories.create_random_company() orderer = factories.create_random_person() payload.update({ "customer": target.pk, "orderer": orderer.pk }) target.members.add(orderer) response = client.post("/api/shuup/basket/new/", payload) assert response.status_code == status.HTTP_201_CREATED basket_data = json.loads(response.content.decode("utf-8")) basket = Basket.objects.first() assert basket.key == basket_data["uuid"].split("-")[1] assert basket.customer == target assert basket.orderer == orderer shop_product = factories.get_default_shop_product() shop_product.default_price = TaxfulPrice(1, shop.currency) shop_product.save() # Add shop product to basket payload = {"shop_product": shop_product.id} response = client.post("/api/shuup/basket/{}-{}/add/".format(shop.pk, basket.key), payload) assert response.status_code == status.HTTP_200_OK response_data = json.loads(response.content.decode("utf-8")) assert len(response_data["items"]) == 1 # Create order from basket response = client.post("/api/shuup/basket/{}-{}/create_order/".format(shop.pk, basket.key), payload) assert response.status_code == status.HTTP_400_BAD_REQUEST response_data = json.loads(response.content.decode("utf-8")) assert "errors" in response_data factories.get_default_payment_method() factories.get_default_shipping_method() response = client.post("/api/shuup/basket/{}-{}/create_order/".format(shop.pk, basket.key), payload) assert response.status_code == status.HTTP_201_CREATED response_data = json.loads(response.content.decode("utf-8")) basket.refresh_from_db() assert basket.finished order = Order.objects.get(reference_number=response_data["reference_number"]) assert order.status == OrderStatus.objects.get_default_initial() assert order.payment_status == PaymentStatus.NOT_PAID assert order.shipping_status == ShippingStatus.NOT_SHIPPED assert not order.payment_method assert not order.shipping_method assert float(order.taxful_total_price_value) == 1 assert order.customer == target assert order.orderer == orderer assert order.creator == admin_user assert not order.billing_address assert not order.shipping_address