Esempio n. 1
0
def test_parallel_baskets(rf):
    request = get_request_with_basket()
    shop = get_default_shop()
    customer = create_random_person()

    request = rf.get("/")
    request.shop = shop
    apply_request_middleware(request)
    request.customer = customer

    basket_one = get_basket(request, basket_name="basket_one")
    basket_two = get_basket(request, basket_name="basket_two")

    product_one = get_default_product()
    product_two = get_default_product()
    product_two.sku = "derpy-hooves"
    sales_unit = SalesUnit.objects.create(identifier="test-sales-partial", decimals=2, name="Partial unit")
    product_two.sales_unit = sales_unit  # Set the sales unit for the product
    product_two.save()

    basket_commands.handle_add(request, basket_one, product_id=product_one.pk, quantity=1)
    basket_commands.handle_add(request, basket_two, product_id=product_two.pk, quantity=3.5)

    assert basket_one.product_count == 1
    assert basket_two.product_count == 3.5
Esempio n. 2
0
def get_initialized_test_event():
    get_default_product()
    customer = create_random_person()
    order = create_random_order(customer)
    return ATestEvent(
        order_language=order.language,
        order=order,
        just_some_text=random_title()
    )
Esempio n. 3
0
def test_refunds(browser, admin_user, live_server, settings):
    order = create_order_with_product(
        get_default_product(), get_default_supplier(), 10, decimal.Decimal("10"), n_lines=10,
        shop=get_default_shop())
    order2 = create_order_with_product(
        get_default_product(), get_default_supplier(), 10, decimal.Decimal("10"), n_lines=10,
        shop=get_default_shop())
    order2.create_payment(order2.taxful_total_price)
    initialize_admin_browser_test(browser, live_server, settings)
    _test_toolbar_visibility(browser, live_server, order)
    _test_create_full_refund(browser, live_server, order)
    _test_refund_view(browser, live_server, order2)
Esempio n. 4
0
def test_broken_order_lines():
    with pytest.raises(ValidationError):
        OrderLine(type=OrderLineType.PRODUCT).save()

    with pytest.raises(ValidationError):
        OrderLine(product=get_default_product(), type=OrderLineType.PRODUCT, supplier=None).save()

    with pytest.raises(ValidationError):
        OrderLine(product=get_default_product(), type=OrderLineType.OTHER).save()

    with pytest.raises(ValidationError):
        OrderLine(product=get_default_product(), type=OrderLineType.OTHER).save()
Esempio n. 5
0
def test_order_received(rf, regular_user):
    activate("en")
    get_default_product()
    get_default_supplier()
    get_test_script("test script", "order_received")

    template_data = STEP_DATA[0]["actions"][0]["template_data"]
    for lang in ["en", "fi"]:
        n_outbox_pre = len(mail.outbox)
        customer = create_random_person(locale=lang)
        create_random_order(customer)
        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"
Esempio n. 6
0
def test_basket_partial_quantity_update():
    request = get_request_with_basket()
    basket = request.basket
    product = get_default_product()

    sales_unit = SalesUnit.objects.create(identifier="test-sales-partial", decimals=2, name="Partial unit")
    product.sales_unit = sales_unit  # Set the sales unit for the product
    product.save()

    basket_commands.handle_add(request, basket, product_id=product.pk, quantity=1.5)
    assert basket.product_count == 1.5
    line_id = basket.get_lines()[0].line_id
    basket_commands.handle_update(request, basket, **{"q_%s" % line_id: "1.5"})
    assert basket.product_count == 1.5

    basket_commands.handle_update(request, basket, **{"q_%s" % line_id: "3.5"})
    assert basket.product_count == 3.5

    basket_commands.handle_update(request, basket, **{"q_%s" % line_id: "3.0"})
    assert basket.product_count == 3.0

    basket_commands.handle_update(request, basket, **{"q_%s" % line_id: "4"})
    assert basket.product_count == 4

    basket_commands.handle_update(request, basket, **{"delete_%s" % line_id: "1"})
    assert basket.product_count == 0
Esempio n. 7
0
def test_ajax():
    product = get_default_product()
    commands = get_basket_command_dispatcher(get_request_with_basket())
    commands.ajax = True
    rv = commands.handle("add", kwargs=dict(product_id=product.pk, quantity=-3))
    assert isinstance(rv, JsonResponse)
    assert commands.basket.product_count == 0
Esempio n. 8
0
def test_tracking_codes():
    product = get_default_product()
    supplier = get_default_supplier()
    order = create_order_with_product(
        product,
        supplier=supplier,
        quantity=1,
        taxless_base_unit_price=10,
        tax_rate=decimal.Decimal("0.5")
    )
    _add_product_to_order(order, "duck-tape-1", 3, order.shop, supplier)
    _add_product_to_order(order, "water-1", 2, order.shop, supplier)

    order.cache_prices()
    order.check_all_verified()
    order.save()

    # Create shipment with tracking code for every product line.
    product_lines = order.lines.exclude(product_id=None)
    assert len(product_lines) == 3
    for line in product_lines:
        shipment = order.create_shipment({line.product: line.quantity}, supplier=supplier)
        if line.quantity != 3:
            shipment.tracking_code = "123FI"
            shipment.save()

    tracking_codes = order.get_tracking_codes()
    code_count = (len(product_lines)-1)  # We skipped that one
    assert len(tracking_codes) == code_count
    assert len([tracking_code for tracking_code in tracking_codes if tracking_code == "123FI"]) == code_count
Esempio n. 9
0
def test_report_writers():
    """
    Just check whether something breaks while writing differnt types of data
    """
    shop = get_default_shop()
    product = get_default_product()
    supplier = get_default_supplier()
    order = create_order_with_product(
        product=product, supplier=supplier, quantity=1, taxless_base_unit_price=10, tax_rate=0, n_lines=2, shop=shop)
    order.create_payment(order.taxful_total_price.amount)

    data = {
        "report": SalesTestReport.get_name(),
        "shop": shop.pk,
        "date_range": DateRangeChoices.THIS_YEAR,
        "writer": "html",
        "force_download": 1,
    }
    report = SalesTestReport(**data)

    for writer_cls in [ExcelReportWriter, PDFReportWriter, PprintReportWriter, HTMLReportWriter, JSONReportWriter]:
        writer = writer_cls()
        report_data = [
            {
                "date": order,
                "order_count": Decimal(2),
                "product_count": int(3),
                "taxless_total": lazy(lambda: order.taxless_total_price_value),
                "taxful_total": order.taxful_total_price,
            }
        ]
        writer.write_data_table(report, report_data)
        assert writer.get_rendered_output()
Esempio n. 10
0
def test_simple_product_works(rf):
    product = get_default_product()
    request = rf.get("/")
    apply_request_middleware(request)
    assert product.get_child_price_range(request) == (None, None)
    assert product.get_cheapest_child_price_info(request) is None
    assert product.get_cheapest_child_price(request) is None
Esempio n. 11
0
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)
Esempio n. 12
0
def test_all_categories_view(rf, admin_user):
    shop = get_default_shop()
    supplier = get_default_supplier()
    category = get_default_category()
    product = get_default_product()
    request = apply_request_middleware(rf.get("/"))
    _check_product_count(request, 0)

    shop_product = product.get_shop_instance(shop)
    shop_product.categories.add(category)
    _check_product_count(request, 1)

    # Create few categories for better test results
    for i in range(10):
        cat = Category.objects.create(name=printable_gibberish())
        cat.shops.add(shop)

    new_product_count = random.randint(1, 3) + 1
    for i in range(1, new_product_count):
        product = create_product("sku-%s" % i, shop=shop, supplier=supplier, default_price=10)
        shop_product = product.get_shop_instance(shop)

        # Add random categories expect default category which we will make
        # hidden to make sure that products linked to hidden categories are
        # not listed
        shop_product.categories = Category.objects.exclude(id=category.pk).order_by("?")[:i]

    _check_product_count(request, new_product_count)

    category.status = CategoryStatus.INVISIBLE
    category.save()
    _check_product_count(request, new_product_count - 1)
Esempio n. 13
0
def test_applied_attributes():
    product = get_default_product()
    for spec in ATTR_SPECS:  # This loop sets each attribute twice. That's okay.
        attr = Attribute.objects.get(identifier=spec["identifier"])
        pa, _ = ProductAttribute.objects.get_or_create(product=product, attribute=attr)
        _populate_applied_attribute(pa)
        pa.save()
        if not attr.is_translated:
            product.set_attribute_value(attr.identifier, pa.value)

    assert product.get_attribute_value("bogomips") == 320, "integer attribute loaded neatly"
    product.set_attribute_value("bogomips", 480)
    assert product.get_attribute_value("bogomips") == 480, "integer attribute updated neatly"
    Product.cache_attributes_for_targets(
        applied_attr_cls=ProductAttribute,
        targets=[product],
        attribute_identifiers=[a["identifier"] for a in ATTR_SPECS],
        language=get_language()
    )
    assert (get_language(), "bogomips",) in product._attr_cache, "integer attribute in cache"
    assert product.get_attribute_value("bogomips") == 480, "integer attribute value in cache"
    assert product.get_attribute_value("ba:gelmips", default="Britta") == "Britta", "non-existent attributes return default value"
    assert product._attr_cache[(get_language(), "ba:gelmips")] is NoSuchAttributeHere, "cache miss saved"
    attr_info = product.get_all_attribute_info(language=get_language(), visibility_mode=AttributeVisibility.SHOW_ON_PRODUCT_PAGE)
    assert set(attr_info.keys()) <= set(a["identifier"] for a in ATTR_SPECS), "get_all_attribute_info gets all attribute info"
Esempio n. 14
0
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_custom_payment_processor_cash_service(choice_identifier, expected_payment_status):
    shop = get_default_shop()
    product = get_default_product()
    supplier = get_default_supplier()
    processor = CustomPaymentProcessor.objects.create()
    payment_method = PaymentMethod.objects.create(
        shop=shop,
        payment_processor=processor,
        choice_identifier=choice_identifier,
        tax_class=get_default_tax_class())

    order = create_order_with_product(
        product=product,
        supplier=supplier,
        quantity=1,
        taxless_base_unit_price=Decimal('5.55'),
        shop=shop)
    order.taxful_total_price = TaxfulPrice(Decimal('5.55'), u'EUR')
    order.payment_method = payment_method
    order.save()

    assert order.payment_status == PaymentStatus.NOT_PAID
    processor.process_payment_return_request(choice_identifier, order, None)
    assert order.payment_status == expected_payment_status
    processor.process_payment_return_request(choice_identifier, order, None)
    assert order.payment_status == expected_payment_status
Esempio n. 16
0
def test_mass_action_multishop(rf, admin_user):
    def create_shop(name):
        return Shop.objects.create(
            name="foobar",
            identifier=name,
            status=ShopStatus.ENABLED,
            public_name=name,
            currency=get_default_currency().code
        )
    shop_one = get_default_shop()
    shop_two = create_shop("foobar")
    product = get_default_product()
    shop_product_one = product.get_shop_instance(shop_one)
    shop_product_two = ShopProduct.objects.create(shop=shop_two, product=product)
    shop_product_two.save()
    assert shop_product_one.visibility == ShopProductVisibility.ALWAYS_VISIBLE
    assert shop_product_two.visibility == ShopProductVisibility.ALWAYS_VISIBLE
    request = apply_request_middleware(rf.get("/"), user=admin_user, shop=shop_one)
    InvisibleMassAction().process(request, 'all')
    shop_product_one.refresh_from_db()
    shop_product_two.refresh_from_db()
    assert shop_product_one.visibility == ShopProductVisibility.NOT_VISIBLE
    assert shop_product_two.visibility == ShopProductVisibility.ALWAYS_VISIBLE
    request = apply_request_middleware(rf.get("/"), user=admin_user, shop=shop_one)
    VisibleMassAction().process(request, 'all')
    shop_product_one.refresh_from_db()
    shop_product_two.refresh_from_db()
    assert shop_product_two.visibility == ShopProductVisibility.ALWAYS_VISIBLE
    assert shop_product_one.visibility == ShopProductVisibility.ALWAYS_VISIBLE
Esempio n. 17
0
def test_order_creation_adds_usage(rf, admin_user):
    request, shop, group = initialize_test(rf, False)

    source = seed_source(admin_user, shop)
    source.add_line(
        type=OrderLineType.PRODUCT,
        product=get_default_product(),
        supplier=get_default_supplier(),
        quantity=1,
        base_unit_price=source.create_price(10),
    )
    source.add_line(
        type=OrderLineType.OTHER,
        quantity=1,
        base_unit_price=source.create_price(10),
        require_verification=True,
    )

    # add coupon
    coupon = Coupon.objects.create(active=True, code="asdf")

    campaign = BasketCampaign.objects.create(
        active=True,
        shop=shop,
        name="test",
        public_name="test",
        coupon=coupon)
    BasketDiscountPercentage.objects.create(campaign=campaign, discount_percentage="0.1")

    source.add_code(coupon.code)

    creator = OrderCreator()
    creator.create_order(source)

    assert CouponUsage.objects.count() == 1
Esempio n. 18
0
def test_simple_search_get_ids_works(rf):
    cache.clear()
    prod = get_default_product()
    bit = prod.name[:5]
    request = apply_request_middleware(rf.get("/"))
    assert prod.pk in get_search_product_ids(request, bit)
    assert prod.pk in get_search_product_ids(request, bit)  # Should use cache
Esempio n. 19
0
def test_delete_payment(admin_user, rf):
    product = get_default_product()
    shop_product = product.get_shop_instance(get_default_shop())
    shop_product.default_price_value = 20
    shop_product.save()

    order = create_random_order(customer=create_random_person(), products=(product,), completion_probability=0)
    payment_amount = order.taxful_total_price_value

    # create a payment
    view = OrderCreatePaymentView.as_view()
    request = apply_request_middleware(rf.post("/", {"amount": payment_amount}), user=admin_user)
    response = view(request, pk=order.pk)
    assert response.status_code == 302

    order.refresh_from_db()
    assert order.is_paid()

    # delete the payment
    payment = order.payments.last()
    view = OrderDeletePaymentView.as_view()
    request = apply_request_middleware(rf.post("/", {"payment": payment.pk}), user=admin_user)
    response = view(request, pk=order.pk)
    assert response.status_code == 302

    order.refresh_from_db()
    assert order.is_not_paid()
Esempio n. 20
0
def test_edit_view_adding_messages_to_form_group(rf, admin_user):
    shop = get_default_shop()  # obvious prerequisite
    product = get_default_product()
    shop_product = product.get_shop_instance(shop)
    view = ProductEditView.as_view()
    request = apply_request_middleware(rf.get("/"), user=admin_user)
    response = view(request, pk=shop_product.pk)
    response.render()
    assert 200 <= response.status_code < 300

    assert ProductEditView.add_form_errors_as_messages

    content = force_text(response.content)
    post = extract_form_fields(BeautifulSoup(content, "lxml"))
    post_data = {
        # Error in the base form part
        "base-name__en": "",
    }
    post.update(post_data)
    request = apply_request_middleware(rf.post("/", post), user=admin_user)
    response = view(request, pk=shop_product.pk)

    errors = response.context_data["form"].errors

    assert "base" in errors
    assert "name__en" in errors["base"]
Esempio n. 21
0
def test_fixed_cost_with_waiving_costs():
    sm = get_shipping_method(name="Fixed and waiving", price=5)

    sm.behavior_components.add(
        *[WaivingCostBehaviorComponent.objects.create(
            price_value=p, waive_limit_value=w)
          for (p, w) in [(3, 5), (7, 10), (10, 30)]])

    source = BasketishOrderSource(get_default_shop())
    source.shipping_method = sm

    def pricestr(pi):
        assert pi.price.unit_matches_with(source.create_price(0))
        return "%.0f EUR (%.0f EUR)" % (pi.price.value, pi.base_price.value)

    assert pricestr(sm.get_total_cost(source)) == "25 EUR (25 EUR)"
    assert source.total_price.value == 25

    source.add_line(
        type=OrderLineType.PRODUCT, product=get_default_product(),
        base_unit_price=source.create_price(2), quantity=1)
    assert pricestr(sm.get_total_cost(source)) == "25 EUR (25 EUR)"
    assert source.total_price.value == 27

    source.add_line(
        type=OrderLineType.PRODUCT, product=get_default_product(),
        base_unit_price=source.create_price(3), quantity=1)
    assert pricestr(sm.get_total_cost(source)) == "22 EUR (25 EUR)"
    assert source.total_price.value == 27

    source.add_line(
        type=OrderLineType.PRODUCT, product=get_default_product(),
        base_unit_price=source.create_price(10), quantity=1)
    assert pricestr(sm.get_total_cost(source)) == "15 EUR (25 EUR)"
    assert source.total_price.value == 30

    source.add_line(
        type=OrderLineType.PRODUCT, product=get_default_product(),
        base_unit_price=source.create_price(10), quantity=1)
    assert pricestr(sm.get_total_cost(source)) == "15 EUR (25 EUR)"
    assert source.total_price.value == 40

    source.add_line(
        type=OrderLineType.PRODUCT, product=get_default_product(),
        base_unit_price=source.create_price(10), quantity=1)
    assert pricestr(sm.get_total_cost(source)) == "5 EUR (25 EUR)"
    assert source.total_price.value == 40
Esempio n. 22
0
def test_update_order_admin_comment(admin_user, rf):
    order = create_random_order(customer=create_random_person(), products=(get_default_product(),))
    assert order.admin_comment == ""
    view = UpdateAdminCommentView.as_view()
    comment = "updated admin comment"
    request = apply_request_middleware(rf.post("/", {"comment": comment}), user=admin_user)
    response = view(request, pk=order.pk)
    assert response.status_code < 400
    order.refresh_from_db()
    assert order.admin_comment == comment
Esempio n. 23
0
def test_add_order_log_entry(admin_user, rf):
    order = create_random_order(customer=create_random_person(), products=(get_default_product(),))
    assert not OrderLogEntry.objects.filter(target=order).exists()
    view = NewLogEntryView.as_view()
    test_message = "test_order"
    request = apply_request_middleware(rf.post("/", {"message": test_message}), user=admin_user)
    response = view(request, pk=order.pk)
    assert response.status_code < 400
    assert OrderLogEntry.objects.filter(target=order).exists()
    assert OrderLogEntry.objects.filter(target=order).first().message == test_message
Esempio n. 24
0
def test_product_price_without_shop_product(client):
    shop = get_default_shop()
    product = get_default_product()
    response = client.get(
        reverse('E-Commerce:xtheme_extra_view', kwargs={
                'view': 'product_price'
            }
        ) + "?id=%s" % (product.pk)
    )
    assert response.context_data["product"] == product
    assert "Combination not available" in response.content.decode("utf-8")
Esempio n. 25
0
def test_product_price(client):
    shop = get_default_shop()
    product = get_default_product()
    response = client.get(
        reverse('E-Commerce:xtheme_extra_view', kwargs={
                'view': 'product_price'
            }
        ) + "?id=%s&quantity=%s" % (product.pk, 1)
    )
    assert response.context_data["product"] == product
    assert b"form" in response.content
Esempio n. 26
0
def test_product_view_extra_context(rf, admin_user):
    product = get_default_product()
    request = apply_request_middleware(rf.get("/"), user=admin_user)
    view_func = ProductDetailView.as_view()

    # Test that we can insert extra information into ProductDetailView context
    with override_provides("product_context_extra", [
        "E-Commerce_tests.front.test_product:ExtraContextTest",
    ]):
        response = view_func(request, pk=product.pk)
        assert response.context_data['product_sku'] == product.sku
Esempio n. 27
0
def test_product_page(client):
    get_default_shop()
    product = get_default_product()
    response = client.get(
        reverse('E-Commerce:product', kwargs={
            'pk': product.pk,
            'slug': product.slug
            }
        )
    )
    assert b'no such element' not in response.content, 'All items are not rendered correctly'
    # TODO test purchase_multiple and  sales_unit.allow_fractions

    product_mode_forms = [
        "E-Commerce.front.forms.order_forms:VariableVariationProductOrderForm",
        "E-Commerce.front.forms.order_forms:SimpleVariationProductOrderForm",
        "E-Commerce.front.forms.order_forms:SimpleProductOrderForm",
        "E-Commerce.testing.extend_classes:DifferentProductOrderForm"
    ]

    with override_provides("front_product_order_form", product_mode_forms):
        get_default_shop()
        product = get_default_product()
        product_modes = [ProductMode.NORMAL, ProductMode.PACKAGE_PARENT,
                         ProductMode.VARIABLE_VARIATION_PARENT, ProductMode.SIMPLE_VARIATION_PARENT,
                         ProductMode.SUBSCRIPTION]

        for product_mode in product_modes:
            product.mode = product_mode
            product.save()

            response = client.get(
                reverse('E-Commerce:product', kwargs={
                    'pk': product.pk,
                    'slug': product.slug
                }
                        )
            )
            assert b'no such element' not in response.content, 'All items are not rendered correctly'
            if product_mode == ProductMode.SUBSCRIPTION:
                assert b'This is different' in response.content, 'DifferentProductOrderForm not rendered properly'
Esempio n. 28
0
def test_waiver():
    sm = get_shipping_method(name="Waivey", price=100, waive_at=370)
    source = BasketishOrderSource(get_default_shop())
    assert sm.get_effective_name(source) == u"Waivey"
    assert sm.get_total_cost(source).price == source.create_price(100)
    source.add_line(
        type=OrderLineType.PRODUCT,
        product=get_default_product(),
        base_unit_price=source.create_price(400),
        quantity=1
    )
    assert sm.get_total_cost(source).price == source.create_price(0)
Esempio n. 29
0
def test_order_set_status_canceled_works(admin_user, rf):
    order = create_random_order(customer=create_random_person(), products=(get_default_product(),))
    assert order.shipping_status == ShippingStatus.NOT_SHIPPED
    assert order.status.role == OrderStatusRole.INITIAL
    canceled_status = OrderStatus.objects.get_default_canceled()
    view = OrderSetStatusView.as_view()
    request = apply_request_middleware(rf.post("/", {"status": canceled_status.pk}), user=admin_user)
    response = view(request, pk=order.pk)
    assert response.status_code < 400
    order = Order.objects.get(pk=order.pk)
    assert order.status_id == canceled_status.id
    assert order.log_entries.filter(identifier="status_change").exists()
Esempio n. 30
0
def test_order_set_status_completed_works(admin_user, rf):
    order = create_random_order(customer=create_random_person(), products=(get_default_product(),))
    order.create_shipment_of_all_products()  # Need to be shipped to set complete
    assert order.status.role == OrderStatusRole.INITIAL
    complete_status = OrderStatus.objects.get_default_complete()
    view = OrderSetStatusView.as_view()
    request = apply_request_middleware(rf.post("/", {"status": complete_status.pk}), user=admin_user)
    response = view(request, pk=order.pk)
    assert response.status_code < 400
    order = Order.objects.get(pk=order.pk)
    assert order.status_id == complete_status.id
    assert order.log_entries.filter(identifier="status_change").exists()