Beispiel #1
0
def test_user_list(rf, admin_user):
    shop = get_default_shop()
    user = get_user_model().objects.create(
        username=printable_gibberish(20),
        first_name=printable_gibberish(10),
        last_name=printable_gibberish(10),
        password="******",
        is_staff=True,
        is_superuser=False
    )
    shop.staff_members.add(user)
    view_func = UserListView.as_view()
    request = rf.get("/", {"jq": json.dumps({"perPage": 100, "page": 1})})

    # check with superuser
    response = view_func(apply_request_middleware(request, user=admin_user))
    assert response.status_code == 200
    data = json.loads(response.content.decode("utf-8"))
    assert len(data["items"]) == 2

    # check with staff user
    response = view_func(apply_request_middleware(request, user=user))
    assert response.status_code == 200
    data = json.loads(response.content.decode("utf-8"))
    assert len(data["items"]) == 1
def test_mass_edit_products2(rf, admin_user):
    shop = get_default_shop()
    supplier = get_default_supplier()
    product1 = create_product(printable_gibberish(), shop=shop, supplier=supplier, default_price="50")
    product2 = create_product(printable_gibberish(), shop=shop, supplier=supplier, default_price="501")

    shop_product1 = product1.get_shop_instance(shop)
    shop_product2 = product2.get_shop_instance(shop)

    # ensure no categories set
    assert shop_product1.primary_category is None
    assert shop_product2.primary_category is None
    payload = {
        "action": InvisibleMassAction().identifier,
        "values": [product1.pk, product2.pk]
    }
    request = apply_request_middleware(rf.post(
        "/",
        user=admin_user,
    ))
    request._body = json.dumps(payload).encode("UTF-8")
    view = ProductListView.as_view()
    response = view(request=request)
    assert response.status_code == 200
    for product in Product.objects.all():
        assert product.get_shop_instance(shop).visibility == ShopProductVisibility.NOT_VISIBLE
def test_mass_edit_orders(rf, admin_user):
    shop = get_default_shop()
    supplier = get_default_supplier()
    contact1 = create_random_person()
    product1 = create_product(printable_gibberish(), shop=shop, supplier=supplier, default_price="50")
    product2 = create_product(printable_gibberish(), shop=shop, supplier=supplier, default_price="501")

    order = create_random_order(customer=contact1,
                                products=[product1, product2],
                                completion_probability=0)

    assert order.status.role != OrderStatusRole.CANCELED
    payload = {
        "action": CancelOrderAction().identifier,
        "values": [order.pk]
    }
    request = apply_request_middleware(rf.post(
        "/",
        user=admin_user,
    ))
    request._body = json.dumps(payload).encode("UTF-8")
    view = OrderListView.as_view()
    response = view(request=request)
    assert response.status_code == 200
    for order in Order.objects.all():
        assert order.status.role == OrderStatusRole.CANCELED
def get_frontend_order_state(contact, valid_lines=True):
    """
    Get a dict structure mirroring what the frontend JavaScript would submit.
    :type contact: Contact|None
    """
    translation.activate("en")
    shop = get_default_shop()
    tax = Tax.objects.create(code="test_code", rate=decimal.Decimal("0.20"), name="Default")
    tax_class = TaxClass.objects.create(identifier="test_tax_class", name="Default")
    rule = TaxRule.objects.create(tax=tax)
    rule.tax_classes.add(tax_class)
    rule.save()
    product = create_product(
        sku=printable_gibberish(),
        supplier=get_default_supplier(),
        shop=shop
    )
    product.tax_class = tax_class
    product.save()
    if valid_lines:
        lines = [
            {"id": "x", "type": "product", "product": {"id": product.id}, "quantity": "32", "baseUnitPrice": 50},
            {"id": "y", "type": "other", "sku": "hello", "text": "A greeting", "quantity": 1, "unitPrice": "5.5"},
            {"id": "z", "type": "text", "text": "This was an order!", "quantity": 0},
        ]
    else:
        unshopped_product = create_product(sku=printable_gibberish(), supplier=get_default_supplier())
        not_visible_product = create_product(
            sku=printable_gibberish(),
            supplier=get_default_supplier(),
            shop=shop
        )
        not_visible_shop_product = not_visible_product.get_shop_instance(shop)
        not_visible_shop_product.visible = False
        not_visible_shop_product.save()
        lines = [
            {"id": "x", "type": "product"},  # no product?
            {"id": "x", "type": "product", "product": {"id": unshopped_product.id}},  # not in this shop?
            {"id": "y", "type": "product", "product": {"id": -product.id}},  # invalid product?
            {"id": "z", "type": "other", "quantity": 1, "unitPrice": "q"},  # what's that price?
            {"id": "rr", "type": "product", "quantity": 1, "product": {"id": not_visible_product.id}}  # not visible
        ]

    state = {
        "customer": {"id": contact.id if contact else None},
        "lines": lines,
        "methods": {
            "shippingMethod": {"id": get_default_shipping_method().id},
            "paymentMethod": {"id": get_default_payment_method().id},
        },
        "shop": {
            "selected": {
                "id": shop.id,
                "name": shop.name,
                "currency": shop.currency,
                "priceIncludeTaxes": shop.prices_include_tax
            }
        }
    }
    return state
Beispiel #5
0
def test_basket_shipping_error(rf):
    StoredBasket.objects.all().delete()
    shop = get_default_shop()
    supplier = get_default_supplier()
    shipped_product = create_product(
        printable_gibberish(), shop=shop, supplier=supplier, default_price=50,
        shipping_mode=ShippingMode.SHIPPED
    )
    unshipped_product = create_product(
        printable_gibberish(), shop=shop, supplier=supplier, default_price=50,
        shipping_mode=ShippingMode.NOT_SHIPPED
    )

    request = rf.get("/")
    request.session = {}
    request.shop = shop
    apply_request_middleware(request)
    basket = get_basket(request)

    # With a shipped product but no shipping methods, we oughta get an error
    basket.add_product(supplier=supplier, shop=shop, product=shipped_product, quantity=1)
    assert any(ve.code == "no_common_shipping" for ve in basket.get_validation_errors())
    basket.clear_all()

    # But with an unshipped product, we should not
    basket.add_product(supplier=supplier, shop=shop, product=unshipped_product, quantity=1)
    assert not any(ve.code == "no_common_shipping" for ve in basket.get_validation_errors())
def test_mass_edit_orders3(rf, admin_user):
    shop = get_default_shop()
    supplier = get_default_supplier()
    contact1 = create_random_person()
    product1 = create_product(printable_gibberish(), shop=shop, supplier=supplier, default_price="50")
    product2 = create_product(printable_gibberish(), shop=shop, supplier=supplier, default_price="501")

    order1 = create_random_order(customer=contact1,
                                products=[product1, product2],
                                completion_probability=0)

    order2 = create_random_order(customer=contact1,
                                products=[product1, product2],
                                completion_probability=0)
    assert order1.status.role != OrderStatusRole.CANCELED
    assert order2.status.role != OrderStatusRole.CANCELED

    payload = {
        "action": OrderConfirmationPdfAction().identifier,
        "values": [order1.pk, order2.pk]
    }
    request = apply_request_middleware(rf.post(
        "/",
        user=admin_user,
    ))
    request._body = json.dumps(payload).encode("UTF-8")
    view = OrderListView.as_view()
    response = view(request=request)
    assert response.status_code == 200
    if weasyprint:
        assert response['Content-Disposition'] == 'attachment; filename=order_confirmation_pdf.zip'
    else:
        assert response["content-type"] == "application/json"
Beispiel #7
0
def test_draft_reversion():
    view_name = printable_gibberish()
    theme = ATestTheme()
    placeholder_name = "test_ph"
    vc = ViewConfig(theme=theme, view_name=view_name, draft=True)
    def get_layout_data(draft):
        # shorthand -- we're going to be doing this a lot in this test case
        return ViewConfig(theme=theme, view_name=view_name, draft=draft).saved_view_config.get_layout_data(placeholder_name)
    data1 = {printable_gibberish(): True}
    data2 = {printable_gibberish(): True}
    vc.save_placeholder_layout(placeholder_name, data1)
    vc.publish()

    assert get_layout_data(draft=False) == data1
    assert get_layout_data(draft=True) == data1
    vc = ViewConfig(theme=theme, view_name=view_name, draft=True)
    svc = vc.saved_view_config
    assert svc.draft
    assert svc.get_layout_data(placeholder_name) == data1
    # Make changes over the last published version
    svc.set_layout_data(placeholder_name, data2)
    svc.save()
    # Still all good in public?
    assert get_layout_data(draft=False) == data1
    # Still got it in draft?
    assert get_layout_data(draft=True) == data2
    # Actually revert those draft changes now!
    vc.revert()
    # So in draft we're back to the published version, right?
    assert get_layout_data(draft=True) == data1
Beispiel #8
0
def test_editor_view_commands():
    with initialize_editor_view(printable_gibberish(), printable_gibberish()) as view_obj:
        view_obj.request.method = "POST"
        view_obj.request.POST = {"command": "add_row"}
        view_obj._populate_vars()  # don't tell anyone we're calling a private method here
        assert len(view_obj.layout) == 0
        view_obj.dispatch(view_obj.request)
        assert len(view_obj.layout) == 1
Beispiel #9
0
def test_move_file():
    folder1 = Folder.objects.create(name=printable_gibberish())
    folder2 = Folder.objects.create(name=printable_gibberish())
    file = File.objects.create(folder=folder1)
    mbv_command({"action": "move_file", "file_id": file.pk, "folder_id": folder2.pk})
    assert File.objects.get(pk=file.pk).folder == folder2
    mbv_command({"action": "move_file", "file_id": file.pk, "folder_id": 0})
    assert File.objects.get(pk=file.pk).folder is None
Beispiel #10
0
def test_get_folder():
    folder1 = Folder.objects.create(name=printable_gibberish())
    folder2 = Folder.objects.create(name=printable_gibberish(), parent=folder1)
    root_resp = mbv_command({"action": "folder"}, "GET")
    assert any(f["id"] == folder1.pk for f in root_resp["folder"]["folders"])
    f1_resp = mbv_command({"action": "folder", "id": folder1.pk}, "GET")
    assert f1_resp["folder"]["folders"][0]["id"] == folder2.pk
    assert not f1_resp["folder"]["files"]
    assert f1_resp["folder"]["name"] == folder1.name
    assert mbv_command({"action": "folder", "id": -1}, "GET")["error"]
Beispiel #11
0
def test_basket_free_product(rf):
    request, shop, _ = initialize_test(rf, False)

    basket = get_basket(request)
    supplier = get_default_supplier()

    single_product_price = "50"
    original_quantity = 2
    # create basket rule that requires 2 products in basket
    product = create_product(printable_gibberish(), shop=shop, supplier=supplier, default_price=single_product_price)
    basket.add_product(supplier=supplier, shop=shop, product=product, quantity=2)
    basket.shipping_method = get_shipping_method(shop=shop)
    basket.save()

    second_product = create_product(printable_gibberish(),
                                    shop=shop,
                                    supplier=supplier,
                                    default_price=single_product_price)

    # no shop
    third_product = create_product(printable_gibberish(), supplier=supplier)

    rule = BasketTotalProductAmountCondition.objects.create(value="2")

    campaign = BasketCampaign.objects.create(active=True, shop=shop, name="test", public_name="test")
    campaign.conditions.add(rule)

    effect = FreeProductLine.objects.create(campaign=campaign, quantity=2)
    effect.products.add(second_product)
    discount_lines_count = len(effect.get_discount_lines(basket, [], supplier))
    assert discount_lines_count == 1

    # do not affect as there is no shop product for the product
    effect.products.add(third_product)
    assert len(effect.get_discount_lines(basket, [], supplier)) == discount_lines_count

    basket.uncache()
    final_lines = basket.get_final_lines()

    assert len(final_lines) == 3

    line_types = [l.type for l in final_lines]
    assert OrderLineType.DISCOUNT not in line_types

    for line in basket.get_final_lines():
        assert line.type in [OrderLineType.PRODUCT, OrderLineType.SHIPPING]
        if line.type == OrderLineType.SHIPPING:
            continue
        if line.product != product:
            assert line.product == second_product
            assert line.line_source == LineSource.DISCOUNT_MODULE
            assert line.quantity == original_quantity
        else:
            assert line.line_source == LineSource.CUSTOMER
Beispiel #12
0
def test_deleting_mid_folder(rf):
    folder1 = Folder.objects.create(name=printable_gibberish())
    folder2 = Folder.objects.create(name=printable_gibberish(), parent=folder1)
    folder3 = Folder.objects.create(name=printable_gibberish(), parent=folder2)
    tree = get_id_tree(mbv_command({"action": "folders"}, "GET"))
    assert tree[folder1.pk] == {folder2.pk: {folder3.pk: {}}}
    mbv_command({"action": "delete_folder", "id": folder2.pk})
    tree = get_id_tree(mbv_command({"action": "folders"}, "GET"))
    assert tree[folder1.pk] == {folder3.pk: {}}
    folder1 = Folder.objects.get(pk=folder1.pk)
    assert list(folder1.get_children()) == [folder3]
Beispiel #13
0
def test_get_folders(rf):
    # Create a structure and retrieve it
    folder1 = Folder.objects.create(name=printable_gibberish())
    folder2 = Folder.objects.create(name=printable_gibberish())
    folder3 = Folder.objects.create(name=printable_gibberish())
    folder4 = Folder.objects.create(name=printable_gibberish(), parent=folder2)
    folder5 = Folder.objects.create(name=printable_gibberish(), parent=folder3)

    tree = get_id_tree(mbv_command({"action": "folders"}, "GET"))
    assert set((folder1.id, folder2.id, folder3.id)) <= set(tree.keys())
    assert folder4.pk in tree[folder2.pk]
    assert folder5.pk in tree[folder3.pk]
Beispiel #14
0
def test_variable_variation_form():
    var1 = printable_gibberish()
    var2 = printable_gibberish()
    parent = create_product(printable_gibberish())
    for a in range(4):
        for b in range(3):
            child = create_product(printable_gibberish())
            child.link_to_parent(parent, variables={var1: a, var2: b})
    assert parent.variation_children.count() == 4 * 3

    form = VariableVariationChildrenForm(parent_product=parent)
    assert len(form.fields) == 12
Beispiel #15
0
def test_undiscounted_effects(rf, include_tax):
    request, shop, _ = initialize_test(rf, include_tax)

    basket = get_basket(request)
    supplier = get_default_supplier()

    single_product_price = Decimal(50)
    discounted_product_quantity = 4
    normal_priced_product_quantity = 2
    discount_percentage = Decimal(0.2)  # 20%
    discount_amount = basket.create_price(single_product_price * normal_priced_product_quantity * discount_percentage)

    category = CategoryFactory()

    discounted_product = create_product(
        printable_gibberish(), shop=shop, supplier=supplier, default_price=single_product_price)
    second_product = create_product(
        printable_gibberish(), shop=shop, supplier=supplier, default_price=single_product_price)

    ShopProduct.objects.get(shop=shop, product=discounted_product).categories.add(category)
    ShopProduct.objects.get(shop=shop, product=second_product).categories.add(category)
    basket.add_product(supplier=supplier, shop=shop, product=discounted_product, quantity=discounted_product_quantity)
    basket.add_product(supplier=supplier, shop=shop, product=second_product, quantity=normal_priced_product_quantity)
    basket.shipping_method = get_shipping_method(shop=shop)
    basket.save()

    # Store basket price before any campaigns exists
    original_price = basket.total_price

    # CatalogCampaign
    catalog_campaign = CatalogCampaign.objects.create(active=True, shop=shop, name="test", public_name="test")
    # Limit catalog campaign to "discounted_product"
    product_filter = ProductFilter.objects.create()
    product_filter.products.add(discounted_product)
    catalog_campaign.filters.add(product_filter)

    # BasketCampaign
    campaign = BasketCampaign.objects.create(
        active=True, shop=shop, name="test2", public_name="test2")

    final_lines = basket.get_final_lines()
    assert len(final_lines) == 3

    # Discount based on undiscounted product values
    DiscountPercentageFromUndiscounted.objects.create(campaign=campaign, discount_percentage=discount_percentage)

    basket.uncache()
    final_lines = basket.get_final_lines()
    assert len(final_lines) == 4

    discounted_basket_price = original_price - discount_amount
    assert basket.total_price.as_rounded() == discounted_basket_price.as_rounded()
Beispiel #16
0
def test_filter_caching(rf):
    request, shop, group = initialize_test(rf, False)
    price = shop.create_price
    product_price = "100"
    discount_percentage = "0.30"

    supplier = get_default_supplier()
    product = create_product(printable_gibberish(), shop=shop, supplier=supplier, default_price=product_price)
    product2 = create_product(printable_gibberish(), shop=shop, supplier=supplier, default_price=product_price)

    assert product.pk != product2.pk  # ensure they're different

    # create catalog campaign
    catalog_filter = ProductFilter.objects.create()
    catalog_filter.products.add(product)


    catalog_campaign = CatalogCampaign.objects.create(shop=shop, active=True, name="test")
    catalog_campaign.filters.add(catalog_filter)
    assert CatalogFilterCachedShopProduct.objects.count() == 1
    catalog_campaign.save()
    assert CatalogFilterCachedShopProduct.objects.count() == 1

    entry = CatalogFilterCachedShopProduct.objects.first()
    assert entry.pk == get_matching_catalog_filters(product.get_shop_instance(shop))[0]

    # create another campaign
    catalog_filter2 = ProductFilter.objects.create()
    catalog_filter2.products.add(product2)
    catalog_campaign2 = CatalogCampaign.objects.create(shop=shop, active=True, name="test")
    catalog_campaign2.filters.add(catalog_filter2)
    assert CatalogFilterCachedShopProduct.objects.count() == 2
    catalog_campaign2.save()
    assert CatalogFilterCachedShopProduct.objects.count() == 2  # new cache for this product was created

    entry = CatalogFilterCachedShopProduct.objects.last()
    assert entry.pk == get_matching_catalog_filters(product2.get_shop_instance(shop))[0]

    # third campaign
    catalog_filter3 = ProductFilter.objects.create()
    catalog_filter3.products.add(product2)
    catalog_campaign3 = CatalogCampaign.objects.create(shop=shop, active=True, name="test")
    catalog_campaign3.filters.add(catalog_filter3)
    assert CatalogFilterCachedShopProduct.objects.count() == 3
    catalog_campaign3.save()
    assert CatalogFilterCachedShopProduct.objects.count() == 3  # new one for this filter again

    expected = get_matching_catalog_filters(product2.get_shop_instance(shop))
    for id in expected:
        assert id in [catalog_filter2.pk, catalog_filter3.pk]
Beispiel #17
0
def test_mass_actions(rf, admin_user):
    shop = get_default_shop()
    supplier = get_default_supplier()
    product = create_product(printable_gibberish(), shop=shop, supplier=supplier, default_price=50)
    product2 = create_product(printable_gibberish(), shop=shop, supplier=supplier, default_price=50)

    ids = [product.id, product2.id]
    request = apply_request_middleware(rf.get("/"), user=admin_user)

    TestPicotableMassAction().process(request, ids)
    for product in Product.objects.all():
        assert product.cost_center == "test"

    mass_action_response = TestPicotableFileMassAction().process(request, ids)
    assert mass_action_response["Content-disposition"] == 'attachment; filename="products.csv"'
Beispiel #18
0
def test_basket_orderability_change_shop_product(rf):
    StoredBasket.objects.all().delete()
    shop = get_default_shop()
    supplier = get_default_supplier()
    product = create_product(printable_gibberish(), shop=shop, supplier=supplier, default_price=50)
    request = rf.get("/")
    request.session = {}
    request.shop = shop
    apply_request_middleware(request)
    basket = get_basket(request)
    line = basket.add_product(
        supplier=supplier,
        shop=shop,
        product=product,
        quantity=1,
        force_new_line=True,
        extra={"foo": "foo"}
    )
    assert len(basket.get_lines()) == 1
    assert len(basket.get_unorderable_lines()) == 0
    product.get_shop_instance(shop).delete()
    basket.uncache()
    assert basket.dirty
    assert len(basket.get_lines()) == 0
    assert len(basket.get_unorderable_lines()) == 1
def _get_order_with_coupon(request, initial_status, condition_product_count=1):
    shop = request.shop
    basket = get_basket(request)
    supplier = get_default_supplier()
    product = create_product(printable_gibberish(), shop=shop, supplier=supplier, default_price="50")
    basket.add_product(supplier=supplier, shop=shop, product=product, quantity=1)
    basket.shipping_method = get_shipping_method(shop=shop)  # For shippable products

    dc = Coupon.objects.create(code="TEST", active=True)
    campaign = BasketCampaign.objects.create(
        shop=shop,
        name="test",
        public_name="test",
        coupon=dc,
        active=True
    )

    BasketDiscountAmount.objects.create(discount_amount=shop.create_price("20"), campaign=campaign)

    rule = BasketTotalProductAmountCondition.objects.create(value=1)
    campaign.conditions.add(rule)
    campaign.save()
    basket.add_code(dc.code)
    basket.save()

    basket.status = initial_status
    creator = OrderCreator(request)
    order = creator.create_order(basket)
    assert order.lines.count() == 3
    assert OrderLineType.DISCOUNT in [l.type for l in order.lines.all()]
    return order
Beispiel #20
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)
Beispiel #21
0
def _add_products_to_basket(basket):
    shop = get_default_shop()
    supplier = get_default_supplier()
    product = create_product(printable_gibberish(), shop=shop, supplier=supplier, default_price=50)
    basket.add_product(supplier=supplier, shop=shop, product=product, quantity=2)
    assert basket.product_count, "basket has products"
    return basket
Beispiel #22
0
def test_order_creator_customer_details(rf, admin_user):
    shop = get_default_shop()
    contact = create_random_person(locale="en_US", minimum_name_comp_len=5)
    company = create_random_company()
    group = get_default_customer_group()
    contact.groups.add(group)
    contact.company_memberships.add(company)
    contact.save()
    product = create_product(sku=printable_gibberish(), supplier=get_default_supplier(), shop=shop)
    order = create_random_order(contact, products=[product])
    request = apply_request_middleware(rf.get("/", {"command": "customer_details", "id": contact.id}), user=admin_user)
    response = OrderEditView.as_view()(request)
    data = json.loads(response.content.decode("utf8"))

    assert "customer_info" in data
    assert "order_summary" in data
    assert "recent_orders" in data
    assert data["customer_info"]["name"] == contact.full_name
    assert data["customer_info"]["phone_no"] == contact.phone
    assert data["customer_info"]["email"] == contact.email
    assert company.full_name in data["customer_info"]["companies"]
    assert group.name in data["customer_info"]["groups"]
    assert data["customer_info"]["merchant_notes"] == contact.merchant_notes
    assert len(data["order_summary"]) == 1
    assert data["order_summary"][0]["year"] == order.order_date.year
    assert data["order_summary"][0]["total"] == format_money(order.taxful_total_price)
    assert len(data["recent_orders"]) == 1
    assert data["recent_orders"][0]["status"] == order.get_status_display()
    assert data["recent_orders"][0]["total"] == format_money(order.taxful_total_price)
    assert data["recent_orders"][0]["payment_status"] == force_text(order.payment_status.label)
    assert data["recent_orders"][0]["shipment_status"] == force_text(order.shipping_status.label)
def test_product_visibility(rf, admin_user, regular_user):
    anon_contact = get_person_contact(AnonymousUser())
    shop_product = get_default_shop_product()
    admin_contact = get_person_contact(admin_user)
    regular_contact = get_person_contact(regular_user)


    with modify(shop_product.product, deleted=True):  # NB: assigning to `product` here works because `get_shop_instance` populates `_product_cache`
        assert error_exists(shop_product.get_visibility_errors(customer=anon_contact), "product_deleted")
        assert error_exists(shop_product.get_visibility_errors(customer=admin_contact), "product_deleted")
        with pytest.raises(ProductNotVisibleProblem):
            shop_product.raise_if_not_visible(anon_contact)
        assert not shop_product.is_list_visible()

    with modify(shop_product, visibility_limit=ProductVisibility.VISIBLE_TO_ALL, visibility=ShopProductVisibility.NOT_VISIBLE):
        assert error_exists(shop_product.get_visibility_errors(customer=anon_contact), "product_not_visible")
        assert error_does_not_exist(shop_product.get_visibility_errors(customer=admin_contact), "product_not_visible")
        assert not shop_product.is_list_visible()

    with modify(shop_product, visibility_limit=ProductVisibility.VISIBLE_TO_LOGGED_IN, visibility=ShopProductVisibility.ALWAYS_VISIBLE):
        assert error_exists(shop_product.get_visibility_errors(customer=anon_contact), "product_not_visible_to_anonymous")
        assert error_does_not_exist(shop_product.get_visibility_errors(customer=admin_contact), "product_not_visible_to_anonymous")

    customer_group = get_default_customer_group()
    grouped_user = get_user_model().objects.create_user(username=printable_gibberish(20))
    grouped_contact = get_person_contact(grouped_user)
    with modify(shop_product, visibility_limit=ProductVisibility.VISIBLE_TO_GROUPS, visibility=ShopProductVisibility.ALWAYS_VISIBLE):
        shop_product.visibility_groups.add(customer_group)
        customer_group.members.add(grouped_contact)
        customer_group.members.remove(get_person_contact(regular_user))
        assert error_does_not_exist(shop_product.get_visibility_errors(customer=grouped_contact), "product_not_visible_to_group")
        assert error_does_not_exist(shop_product.get_visibility_errors(customer=admin_contact), "product_not_visible_to_group")
        assert error_exists(shop_product.get_visibility_errors(customer=regular_contact), "product_not_visible_to_group")
Beispiel #24
0
def test_protected_fields():
    activate("en")
    shop = Shop.objects.create(
        name="testshop",
        identifier="testshop",
        status=ShopStatus.ENABLED,
        public_name="test shop",
        domain="derp",
        currency="EUR"
    )
    get_currency("EUR")
    get_currency("USD")
    assert shop.name == "testshop"
    assert shop.currency == "EUR"
    assert not ConfigurationItem.objects.filter(shop=shop, key="languages").exists()
    shop_form = ShopBaseForm(instance=shop, languages=settings.LANGUAGES)
    assert not shop_form._get_protected_fields()  # No protected fields just yet, right?
    data = get_form_data(shop_form, prepared=True)
    shop_form = ShopBaseForm(data=data, instance=shop, languages=settings.LANGUAGES)
    _test_cleanliness(shop_form)
    shop_form.save()

    # Now let's make it protected!
    create_product(printable_gibberish(), shop=shop, supplier=get_default_supplier())
    order = create_random_order(customer=create_random_person(), shop=shop)
    assert order.shop == shop

    # And try again...
    data["currency"] = "USD"
    shop_form = ShopBaseForm(data=data, instance=shop, languages=settings.LANGUAGES)
    assert shop_form._get_protected_fields()  # So protected!
    _test_cleanliness(shop_form)
    shop = shop_form.save()
    assert shop.currency == "EUR"  # But the shop form ignored the change . . .
Beispiel #25
0
def test_product_not_in_normal_mode():
    FormSet = formset_factory(PackageChildForm, PackageChildFormSet, extra=5, can_delete=True)
    parent = create_product(printable_gibberish())
    child_1 = create_product(printable_gibberish())
    child_1.link_to_parent(parent)
    child_2 = create_product(printable_gibberish())
    parent.verify_mode()

    assert parent.mode == ProductMode.SIMPLE_VARIATION_PARENT

    # Trying to create a package from a non-normal mode product
    with pytest.raises(Problem):
        formset = FormSet(parent_product=parent)
        data = dict(get_form_data(formset, True), **{"form-0-child": child_2.pk, "form-0-quantity": 2})
        formset = FormSet(parent_product=parent, data=data)
        formset.save()
def _get_frontend_order_state(shop, contact):
    tax = Tax.objects.create(code="test_code", rate=decimal.Decimal("0.20"), name="Default")
    tax_class = TaxClass.objects.create(identifier="test_tax_class", name="Default")
    rule = TaxRule.objects.create(tax=tax)
    rule.tax_classes.add(tax_class)
    rule.save()
    product = create_product(sku=printable_gibberish(), supplier=get_default_supplier(), shop=shop)
    product.tax_class = tax_class
    product.save()
    lines = [{"id": "x", "type": "product", "product": {"id": product.id}, "quantity": "32", "baseUnitPrice": 50}]

    state = {
        "customer": {
            "id": contact.id if contact else None,
            "billingAddress": _encode_address(contact.default_billing_address) if contact else {},
            "shippingAddress": _encode_address(contact.default_shipping_address) if contact else {},
        },
        "lines": lines,
        "methods": {
            "shippingMethod": {"id": get_shipping_method(shop=shop).id},
            "paymentMethod": {"id": get_payment_method(shop=shop).id},
        },
        "shop": {
            "selected": {
                "id": shop.id,
                "name": shop.safe_translation_getter("name"),
                "currency": shop.currency,
                "priceIncludeTaxes": shop.prices_include_tax,
            }
        },
    }
    return state
Beispiel #27
0
def test_productfilter_works(rf):
    request, shop, group = initialize_test(rf, False)
    price = shop.create_price
    product_price = "100"
    discount_percentage = "0.30"

    supplier = get_default_supplier()
    product = create_product(printable_gibberish(), shop=shop, supplier=supplier, default_price=product_price)
    shop_product = product.get_shop_instance(shop)

    # create catalog campaign
    catalog_filter = ProductFilter.objects.create()
    catalog_filter.products.add(product)

    assert catalog_filter.matches(shop_product)

    catalog_campaign = CatalogCampaign.objects.create(shop=shop, active=True, name="test")
    catalog_campaign.filters.add(catalog_filter)
    cdp = ProductDiscountPercentage.objects.create(campaign=catalog_campaign, discount_percentage=discount_percentage)

    # add product to basket
    basket = get_basket(request)
    basket.add_product(supplier=supplier, shop=shop, product=product, quantity=1)
    basket.shipping_method = get_shipping_method(shop=shop)
    basket.save()

    expected_total = price(product_price) - (Decimal(discount_percentage) * price(product_price))
    assert basket.total_price == expected_total
def test_percentage_campaign(rf):
    request, shop, group = initialize_test(rf, False)
    price = shop.create_price

    basket = get_basket(request)
    supplier = get_default_supplier()
    # create a basket rule that requires at least value of 200
    rule = BasketTotalAmountCondition.objects.create(value="200")

    product_price = "200"

    discount_percentage = "0.1"

    expected_discounted_price = price(product_price) - (price(product_price) * Decimal(discount_percentage))

    product = create_product(printable_gibberish(), shop=shop, supplier=supplier, default_price=product_price)
    basket.add_product(supplier=supplier, shop=shop, product=product, quantity=1)

    campaign = BasketCampaign.objects.create(
        shop=shop, public_name="test", name="test", active=True)
    campaign.conditions.add(rule)
    campaign.save()

    BasketDiscountPercentage.objects.create(campaign=campaign, discount_percentage=discount_percentage)

    assert len(basket.get_final_lines()) == 2
    assert basket.product_count == 1
    assert basket.total_price == expected_discounted_price
def test_only_cheapest_price_is_selected(rf):
    request, shop, group = initialize_test(rf, False)
    price = shop.create_price

    basket = get_basket(request)
    supplier = get_default_supplier()
     # create a basket rule that requires atleast value of 200
    rule = BasketTotalAmountCondition.objects.create(value="200")

    product_price = "200"

    discount1 = "10"
    discount2 = "20"  # should be selected
    product = create_product(printable_gibberish(), shop=shop, supplier=supplier, default_price=product_price)
    basket.add_product(supplier=supplier, shop=shop, product=product, quantity=1)

    campaign1 = BasketCampaign.objects.create(shop=shop, public_name="test", name="test", active=True)
    campaign1.conditions.add(rule)
    campaign1.save()
    BasketDiscountAmount.objects.create(discount_amount=discount1, campaign=campaign1)

    campaign2 = BasketCampaign.objects.create(shop=shop, public_name="test", name="test", active=True)
    campaign2.conditions.add(rule)
    campaign2.save()
    BasketDiscountAmount.objects.create(discount_amount=discount2, campaign=campaign2)

    assert len(basket.get_final_lines()) == 2

    line_types = [l.type for l in basket.get_final_lines()]
    assert OrderLineType.DISCOUNT in line_types

    for line in basket.get_final_lines():
        if line.type == OrderLineType.DISCOUNT:
            assert line.discount_amount == price(discount2)
Beispiel #30
0
def test_basket_free_product_coupon(rf):
    request, shop, _ = initialize_test(rf, False)

    basket = get_basket(request)
    supplier = get_default_supplier()

    single_product_price = "50"
    discount_amount_value = "10"

     # create basket rule that requires 2 products in basket
    product = create_product(printable_gibberish(), shop=shop, supplier=supplier, default_price=single_product_price)
    basket.add_product(supplier=supplier, shop=shop, product=product, quantity=1)
    basket.add_product(supplier=supplier, shop=shop, product=product, quantity=1)
    basket.shipping_method = get_shipping_method(shop=shop)
    basket.save()

    second_product = create_product(printable_gibberish(),
                                    shop=shop,
                                    supplier=supplier,
                                    default_price=single_product_price)

    rule = BasketTotalProductAmountCondition.objects.create(value="2")
    coupon = Coupon.objects.create(code="TEST", active=True)

    campaign = BasketCampaign.objects.create(active=True, shop=shop, name="test", public_name="test", coupon=coupon)
    campaign.conditions.add(rule)

    effect = FreeProductLine.objects.create(campaign=campaign)
    effect.products.add(second_product)

    basket.add_code(coupon.code)

    basket.uncache()
    final_lines = basket.get_final_lines()

    assert len(final_lines) == 3

    line_types = [l.type for l in final_lines]
    assert OrderLineType.DISCOUNT not in line_types

    for line in basket.get_final_lines():
        assert line.type in [OrderLineType.PRODUCT, OrderLineType.SHIPPING]
        if line.type == OrderLineType.SHIPPING:
            continue

        if line.product != product:
            assert line.product == second_product
Beispiel #31
0
def test_user_detail_works_at_all(rf, admin_user):
    shop = get_default_shop()
    user = get_user_model().objects.create(username=printable_gibberish(20),
                                           first_name=printable_gibberish(10),
                                           last_name=printable_gibberish(10),
                                           password="******")
    view_func = UserDetailView.as_view()
    response = view_func(apply_request_middleware(rf.get("/"),
                                                  user=admin_user),
                         pk=user.pk)
    assert response.status_code == 200
    response.render()
    assert force_text(user) in force_text(response.content)
    response = view_func(apply_request_middleware(rf.post(
        "/", {"set_is_active": "0"}),
                                                  user=admin_user),
                         pk=user.pk)
    assert response.status_code < 500 and not get_user_model().objects.get(
        pk=user.pk).is_active
    with pytest.raises(Problem):
        view_func(apply_request_middleware(rf.post("/",
                                                   {"set_is_active": "0"}),
                                           user=admin_user),
                  pk=admin_user.pk)

    user = get_user_model().objects.create(username=printable_gibberish(20),
                                           first_name=printable_gibberish(10),
                                           last_name=printable_gibberish(10),
                                           password="******",
                                           is_staff=True,
                                           is_superuser=False)
    shop.staff_members.add(user)
    # non superusers can't see superusers
    with pytest.raises(Http404):
        view_func(apply_request_middleware(rf.get("/"), user=user),
                  pk=admin_user.pk)
Beispiel #32
0
def test_basket_free_product_coupon(rf):
    request, shop, group = initialize_test(rf, False)
    price = shop.create_price

    basket = get_basket(request)
    supplier = get_default_supplier()

    single_product_price = "50"
    discount_amount_value = "10"

    # create basket rule that requires 2 products in basket
    product = create_product(printable_gibberish(),
                             shop=shop,
                             supplier=supplier,
                             default_price=single_product_price)
    basket.add_product(supplier=supplier,
                       shop=shop,
                       product=product,
                       quantity=1)
    basket.add_product(supplier=supplier,
                       shop=shop,
                       product=product,
                       quantity=1)
    basket.shipping_method = get_shipping_method(shop=shop)
    basket.save()

    second_product = create_product(printable_gibberish(),
                                    shop=shop,
                                    supplier=supplier,
                                    default_price=single_product_price)

    rule = BasketTotalProductAmountCondition.objects.create(value="2")
    coupon = Coupon.objects.create(code="TEST", active=True)

    campaign = BasketCampaign.objects.create(active=True,
                                             shop=shop,
                                             name="test",
                                             public_name="test",
                                             coupon=coupon)
    campaign.conditions.add(rule)

    effect = FreeProductLine.objects.create(campaign=campaign)
    effect.products.add(second_product)

    basket.add_code(coupon.code)

    basket.uncache()
    final_lines = basket.get_final_lines()

    assert len(final_lines) == 3

    line_types = [l.type for l in final_lines]
    assert OrderLineType.DISCOUNT not in line_types

    for line in basket.get_final_lines():
        assert line.type in [OrderLineType.PRODUCT, OrderLineType.SHIPPING]
        if line.type == OrderLineType.SHIPPING:
            continue

        if line.product != product:
            assert line.product == second_product
Beispiel #33
0
def test_delete_folder(admin_user):
    shop = get_default_shop()
    folder = get_or_create_folder(shop, printable_gibberish())
    mbv_command(admin_user, {"action": "delete_folder", "id": folder.pk})
    assert not Folder.objects.filter(pk=folder.pk).exists()
Beispiel #34
0
def test_basket_free_product(rf):
    request, shop, _ = initialize_test(rf, False)

    basket = get_basket(request)
    supplier = get_default_supplier(shop)

    single_product_price = "50"
    original_quantity = 2
    # create basket rule that requires 2 products in basket
    product = create_product(printable_gibberish(),
                             shop=shop,
                             supplier=supplier,
                             default_price=single_product_price)
    basket.add_product(supplier=supplier,
                       shop=shop,
                       product=product,
                       quantity=2)
    basket.shipping_method = get_shipping_method(shop=shop)
    basket.save()

    second_product = create_product(printable_gibberish(),
                                    shop=shop,
                                    supplier=supplier,
                                    default_price=single_product_price)

    # no shop
    third_product = create_product(printable_gibberish(), supplier=supplier)

    rule = BasketTotalProductAmountCondition.objects.create(value="2")

    campaign = BasketCampaign.objects.create(active=True,
                                             shop=shop,
                                             name="test",
                                             public_name="test")
    campaign.conditions.add(rule)

    effect = FreeProductLine.objects.create(campaign=campaign, quantity=2)
    effect.products.add(second_product)
    discount_lines_count = len(effect.get_discount_lines(basket, [], supplier))
    assert discount_lines_count == 1

    # do not affect as there is no shop product for the product
    effect.products.add(third_product)
    assert len(effect.get_discount_lines(basket, [],
                                         supplier)) == discount_lines_count

    basket.uncache()
    final_lines = basket.get_final_lines()

    assert len(final_lines) == 3

    line_types = [l.type for l in final_lines]
    assert OrderLineType.DISCOUNT not in line_types

    for line in basket.get_final_lines():
        assert line.type in [OrderLineType.PRODUCT, OrderLineType.SHIPPING]
        if line.type == OrderLineType.SHIPPING:
            continue
        if line.product != product:
            assert line.product == second_product
            assert line.line_source == LineSource.DISCOUNT_MODULE
            assert line.quantity == original_quantity
        else:
            assert line.line_source == LineSource.CUSTOMER
Beispiel #35
0
def test_undiscounted_effects(rf, include_tax):
    request, shop, _ = initialize_test(rf, include_tax)

    basket = get_basket(request)
    supplier = get_default_supplier(shop)

    single_product_price = Decimal(50)
    discounted_product_quantity = 4
    normal_priced_product_quantity = 2
    discount_percentage = Decimal(0.2)  # 20%
    discount_amount = basket.create_price(single_product_price *
                                          normal_priced_product_quantity *
                                          discount_percentage)

    category = CategoryFactory()

    discounted_product = create_product(printable_gibberish(),
                                        shop=shop,
                                        supplier=supplier,
                                        default_price=single_product_price)
    second_product = create_product(printable_gibberish(),
                                    shop=shop,
                                    supplier=supplier,
                                    default_price=single_product_price)

    ShopProduct.objects.get(
        shop=shop, product=discounted_product).categories.add(category)
    ShopProduct.objects.get(shop=shop,
                            product=second_product).categories.add(category)
    basket.add_product(supplier=supplier,
                       shop=shop,
                       product=discounted_product,
                       quantity=discounted_product_quantity)
    basket.add_product(supplier=supplier,
                       shop=shop,
                       product=second_product,
                       quantity=normal_priced_product_quantity)
    basket.shipping_method = get_shipping_method(shop=shop)
    basket.save()

    # Store basket price before any campaigns exists
    original_price = basket.total_price

    # CatalogCampaign
    catalog_campaign = CatalogCampaign.objects.create(active=True,
                                                      shop=shop,
                                                      name="test",
                                                      public_name="test")
    # Limit catalog campaign to "discounted_product"
    product_filter = ProductFilter.objects.create()
    product_filter.products.add(discounted_product)
    catalog_campaign.filters.add(product_filter)

    # BasketCampaign
    campaign = BasketCampaign.objects.create(active=True,
                                             shop=shop,
                                             name="test2",
                                             public_name="test2")

    final_lines = basket.get_final_lines()
    assert len(final_lines) == 3

    # Discount based on undiscounted product values
    DiscountPercentageFromUndiscounted.objects.create(
        campaign=campaign, discount_percentage=discount_percentage)

    basket.uncache()
    final_lines = basket.get_final_lines()
    assert len(final_lines) == 4

    discounted_basket_price = original_price - discount_amount
    assert basket.total_price.as_rounded(
    ) == discounted_basket_price.as_rounded()
Beispiel #36
0
def test_filter_caching(rf):
    request, shop, group = initialize_test(rf, False)
    price = shop.create_price
    product_price = "100"
    discount_percentage = "0.30"

    supplier = get_default_supplier()
    product = create_product(printable_gibberish(),
                             shop=shop,
                             supplier=supplier,
                             default_price=product_price)
    product2 = create_product(printable_gibberish(),
                              shop=shop,
                              supplier=supplier,
                              default_price=product_price)

    assert product.pk != product2.pk  # ensure they're different

    # create catalog campaign
    catalog_filter = ProductFilter.objects.create()
    catalog_filter.products.add(product)

    catalog_campaign = CatalogCampaign.objects.create(shop=shop,
                                                      active=True,
                                                      name="test")
    catalog_campaign.filters.add(catalog_filter)
    assert CatalogFilterCachedShopProduct.objects.count() == 1
    catalog_campaign.save()
    assert CatalogFilterCachedShopProduct.objects.count() == 1

    entry = CatalogFilterCachedShopProduct.objects.first()
    assert entry.pk == get_matching_catalog_filters(
        product.get_shop_instance(shop))[0]

    # create another campaign
    catalog_filter2 = ProductFilter.objects.create()
    catalog_filter2.products.add(product2)
    catalog_campaign2 = CatalogCampaign.objects.create(shop=shop,
                                                       active=True,
                                                       name="test")
    catalog_campaign2.filters.add(catalog_filter2)
    assert CatalogFilterCachedShopProduct.objects.count() == 2
    catalog_campaign2.save()
    assert CatalogFilterCachedShopProduct.objects.count(
    ) == 2  # new cache for this product was created

    entry = CatalogFilterCachedShopProduct.objects.last()
    assert entry.pk == get_matching_catalog_filters(
        product2.get_shop_instance(shop))[0]

    # third campaign
    catalog_filter3 = ProductFilter.objects.create()
    catalog_filter3.products.add(product2)
    catalog_campaign3 = CatalogCampaign.objects.create(shop=shop,
                                                       active=True,
                                                       name="test")
    catalog_campaign3.filters.add(catalog_filter3)
    assert CatalogFilterCachedShopProduct.objects.count() == 3
    catalog_campaign3.save()
    assert CatalogFilterCachedShopProduct.objects.count(
    ) == 3  # new one for this filter again

    expected = get_matching_catalog_filters(product2.get_shop_instance(shop))
    for id in expected:
        assert id in [catalog_filter2.pk, catalog_filter3.pk]
Beispiel #37
0
def test_order_creator_view_invalid_command(rf, admin_user):
    get_default_shop()
    request = apply_request_middleware(rf.get("/", {"command": printable_gibberish()}), user=admin_user)
    response = OrderEditView.as_view()(request)
    assert_contains(response, "unknown command", status_code=400)
def test_upload(rf):
    response = mbv_upload()
    assert not File.objects.get(pk=response["file"]["id"]).folder
    folder = Folder.objects.create(name=printable_gibberish())
    response = mbv_upload(folder_id=folder.pk)
    assert File.objects.get(pk=response["file"]["id"]).folder == folder
Beispiel #39
0
def test_variation_detail_view(client):
    shop = get_default_shop()

    parent = create_product(printable_gibberish(), shop)

    assert parent.mode == ProductMode.NORMAL

    volume = ProductVariationVariable.objects.create(
        identifier='volume',
        name='volume',
        product=parent,
        ordering=0,
    )
    for index, value in enumerate(['1ml', '2ml', '3ml']):
        ProductVariationVariableValue.objects.create(
            identifier=value,
            value=value,
            variable=volume,
            ordering=index,
        )

    color = ProductVariationVariable.objects.create(
        identifier='color',
        name='color',
        product=parent,
        ordering=1,
    )
    for index, value in enumerate(['red', 'green', 'blue']):
        ProductVariationVariableValue.objects.create(
            identifier=value,
            value=value,
            variable=color,
            ordering=index,
        )

    child = create_product(printable_gibberish(), shop)

    values = [volume.values.all()[1], color.values.all()[1]]
    assert child.link_to_parent(parent,
                                variables={
                                    volume: values[0],
                                    color: values[1],
                                })

    assert parent.mode == ProductMode.VARIABLE_VARIATION_PARENT

    variation_url = '{}?variation={}'.format(
        reverse('shuup:product', kwargs=dict(pk=parent.pk, slug=parent.slug)),
        child.sku)
    response = client.get(variation_url + 'BAD_VARIATION_SKU')
    assert response.status_code == 404

    response = client.get(variation_url)
    assert response.status_code == 200

    assert response.context_data['shop_product']

    assert response.context_data['selected_variation'] == child
    assert response.context_data['selected_variation_values'] == [
        v.pk for v in values
    ]
def test_new_folder():
    folder1 = Folder.objects.create(name=printable_gibberish())
    child_folder_data = mbv_command({"action": "new_folder", "name": "y", "parent": folder1.id})["folder"]
    assert Folder.objects.get(pk=child_folder_data["id"]).parent == folder1
    root_folder_data = mbv_command({"action": "new_folder", "name": "y"})["folder"]
    assert not Folder.objects.get(pk=root_folder_data["id"]).parent_id
Beispiel #41
0
def test_missing_plugin_render():
    plugin_id = printable_gibberish()
    cell = LayoutCell(FauxTheme, plugin_identifier=plugin_id)
    assert not cell.plugin_class
    assert not cell.instantiate_plugin()
    assert ("%s?" % plugin_id) in cell.render(None)  # Should render a "whut?" comment
Beispiel #42
0
def test_unsaved_vc_reversion():
    shop=get_default_shop()
    vc = ViewConfig(theme=ATestTheme(shop=shop), shop=shop, view_name=printable_gibberish(), draft=True)
    vc.revert()  # No-op, since this has never been saved (but shouldn't crash either)
def test_rename_folder():
    folder = Folder.objects.create(name=printable_gibberish())
    mbv_command({"action": "rename_folder", "id": folder.pk, "name": "Space"})
    assert Folder.objects.get(pk=folder.pk).name == "Space"
def test_variation_activation(rf):
    shop = get_default_shop()
    parent = create_product(printable_gibberish(), shop=shop)
    user = create_random_user(is_superuser=True, is_staff=True)
    request = apply_request_middleware(rf.get("/"), user=user, shop=shop)
    form = VariationVariablesDataForm(parent_product=parent, request=request)
    assert len(ProductVariationVariable.objects.all()
               ) == 0  # Assert no active Variations are present
    assert form.get_variation_templates() == [
    ]  # Assert no templates exist (yet)
    var_data_dict = {
        'data': json.dumps({"variable_values": var_data}),
        'activate_template': True,
        'template_name': ''
    }  # Base skeleton
    form.cleaned_data = var_data_dict
    form.is_valid()
    form.save()

    assert len(
        ProductVariationVariable.objects.filter(product=parent)) == 1  # Size
    assert len(ProductVariationVariableValue.objects.all()) == 2  # X,S

    var_data_one_value = [{
        "pk":
        "$0.3",
        "identifier":
        "",
        "names": {
            "en": "Size"
        },
        "values": [{
            "pk": "$0.8",
            "identifier": "",
            "texts": {
                "en": "X"
            }
        }]
    }]  #  Delete one value
    var_data_dict['data'] = json.dumps({"variable_values": var_data_one_value})
    form.cleaned_data = var_data_dict
    form.save()

    assert len(ProductVariationVariable.objects.filter(product=parent)) == 1
    assert len(ProductVariationVariableValue.objects.all()) == 1
    var_data_dict["template_name"] = printable_gibberish()  # Create template
    form.save()

    assert len(ProductVariationVariable.objects.filter(product=parent)) == 1
    assert len(ProductVariationVariableValue.objects.all()) == 1
    assert len(form.get_variation_templates()) == 1

    template_identifier = form.get_variation_templates()[0].get('identifier')
    # dict with template identifier which contains only one ProductVariationVariableValue data
    one_value_dict = json.dumps({
        "variable_values": var_data_one_value,
        'template_identifier': template_identifier
    })
    two_values_dict = json.dumps({
        "variable_values": var_data,
        'template_identifier': template_identifier
    })  # Has two PVVV
    var_data_dict['data'] = two_values_dict
    var_data_dict['template_name'] = ''
    form.cleaned_data = var_data_dict
    form.save()

    assert len(ProductVariationVariable.objects.filter(product=parent)) == 1
    assert len(ProductVariationVariableValue.objects.all()) == 2
    var_template_data = form.get_variation_templates()[0].get("data")
    assert var_template_data == var_data
    var_data_dict['data'] = one_value_dict
    form.cleaned_data = var_data_dict
    form.save()

    assert len(ProductVariationVariable.objects.filter(product=parent)) == 1
    assert len(ProductVariationVariableValue.objects.all()) == 1
    var_template_data = form.get_variation_templates()[0].get("data")
    assert var_template_data == var_data_one_value

    var_data_dict['data'] = two_values_dict
    var_data_dict['activate_template'] = False
    form.cleaned_data = var_data_dict
    form.save()

    assert len(ProductVariationVariable.objects.filter(product=parent)) == 1
    assert len(
        ProductVariationVariableValue.objects.all()
    ) == 1  # Assert newest template data hasn't been activated since activated_template = False
    var_template_data = form.get_variation_templates()[0].get("data")
    assert var_template_data == var_data
Beispiel #45
0
def test_order_create_without_shipping_or_billing_method(admin_user):
    create_default_order_statuses()
    shop = get_default_shop()
    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,
                               "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))
Beispiel #46
0
def get_frontend_order_state(contact, valid_lines=True):
    """
    Get a dict structure mirroring what the frontend JavaScript would submit.
    :type contact: Contact|None
    """
    translation.activate("en")
    shop = get_default_shop()
    tax, created = Tax.objects.get_or_create(code="test_code",
                                             defaults={
                                                 "rate":
                                                 decimal.Decimal("0.20"),
                                                 "name": "Default"
                                             })
    tax_class, created = TaxClass.objects.get_or_create(
        identifier="test_tax_class", defaults={"name": "Default"})
    rule, created = TaxRule.objects.get_or_create(tax=tax)
    rule.tax_classes.add(tax_class)
    rule.save()
    product = create_product(sku=printable_gibberish(),
                             supplier=get_default_supplier(),
                             shop=shop)
    product.tax_class = tax_class
    product.save()
    if valid_lines:
        lines = [
            {
                "id": "x",
                "type": "product",
                "product": {
                    "id": product.id
                },
                "quantity": "32",
                "baseUnitPrice": 50
            },
            {
                "id": "y",
                "type": "other",
                "sku": "hello",
                "text": "A greeting",
                "quantity": 1,
                "unitPrice": "5.5"
            },
            {
                "id": "z",
                "type": "text",
                "text": "This was an order!",
                "quantity": 0
            },
        ]
    else:
        unshopped_product = create_product(sku=printable_gibberish(),
                                           supplier=get_default_supplier())
        not_visible_product = create_product(sku=printable_gibberish(),
                                             supplier=get_default_supplier(),
                                             shop=shop)
        not_visible_shop_product = not_visible_product.get_shop_instance(shop)
        not_visible_shop_product.visibility = ShopProductVisibility.NOT_VISIBLE
        not_visible_shop_product.save()
        lines = [
            {
                "id": "x",
                "type": "product"
            },  # no product?
            {
                "id": "x",
                "type": "product",
                "product": {
                    "id": unshopped_product.id
                }
            },  # not in this shop?
            {
                "id": "y",
                "type": "product",
                "product": {
                    "id": -product.id
                }
            },  # invalid product?
            {
                "id": "z",
                "type": "other",
                "quantity": 1,
                "unitPrice": "q"
            },  # what's that price?
            {
                "id": "rr",
                "type": "product",
                "quantity": 1,
                "product": {
                    "id": not_visible_product.id
                }
            }  # not visible
        ]
    state = {
        "customer": {
            "id": contact.id if contact else None,
            "billingAddress":
            encode_address(contact.default_billing_address) if contact else {},
            "shippingAddress": encode_address(contact.default_shipping_address)
            if contact else {},
        },
        "lines": lines,
        "methods": {
            "shippingMethod": {
                "id": get_default_shipping_method().id
            },
            "paymentMethod": {
                "id": get_default_payment_method().id
            },
        },
        "shop": {
            "selected": {
                "id": shop.id,
                "name": shop.name,
                "currency": shop.currency,
                "priceIncludeTaxes": shop.prices_include_tax
            }
        }
    }
    return state
Beispiel #47
0
def test_editor_view_unknown_command():
    with initialize_editor_view(printable_gibberish(), printable_gibberish()) as view_obj:
        view_obj.request.method = "POST"
        view_obj.request.POST = {"command": printable_gibberish()}
        with pytest.raises(Problem):
            view_obj.dispatch(view_obj.request)
Beispiel #48
0
def test_basket_campaign_case2(rf):
    request, shop, group = initialize_test(rf, False)
    price = shop.create_price

    basket = get_basket(request)
    supplier = get_default_supplier(shop)
    # create a basket rule that requires at least value of 200
    rule = BasketTotalAmountCondition.objects.create(value="200")

    single_product_price = "50"
    discount_amount_value = "10"

    unique_shipping_method = get_shipping_method(shop, price=50)

    for x in range(3):
        product = create_product(printable_gibberish(),
                                 shop=shop,
                                 supplier=supplier,
                                 default_price=single_product_price)
        basket.add_product(supplier=supplier,
                           shop=shop,
                           product=product,
                           quantity=1)

    assert basket.product_count == 3

    campaign = BasketCampaign.objects.create(shop=shop,
                                             public_name="test",
                                             name="test",
                                             active=True)
    campaign.conditions.add(rule)
    campaign.save()

    BasketDiscountAmount.objects.create(discount_amount=discount_amount_value,
                                        campaign=campaign)

    assert len(basket.get_final_lines()) == 3
    assert basket.total_price == price(
        single_product_price) * basket.product_count

    # check that shipping method affects campaign
    basket.shipping_method = unique_shipping_method
    basket.save()
    basket.uncache()
    assert len(basket.get_final_lines()
               ) == 4  # Shipping should not affect the rule being triggered

    line_types = [l.type for l in basket.get_final_lines()]
    assert OrderLineType.DISCOUNT not in line_types

    product = create_product(printable_gibberish(),
                             shop=shop,
                             supplier=supplier,
                             default_price=single_product_price)
    basket.add_product(supplier=supplier,
                       shop=shop,
                       product=product,
                       quantity=1)

    assert len(basket.get_final_lines()) == 6  # Discount included
    assert OrderLineType.DISCOUNT in [l.type for l in basket.get_final_lines()]
Beispiel #49
0
def test_rename_folder(admin_user):
    shop = get_default_shop()
    folder = get_or_create_folder(shop, printable_gibberish())
    mbv_command(admin_user, {"action": "rename_folder", "id": folder.pk, "name": "Space"})
    assert Folder.objects.get(pk=folder.pk).name == "Space"
Beispiel #50
0
def test_multiple_campaigns_match_with_coupon(rf):
    request, shop, group = initialize_test(rf, False)
    price = shop.create_price

    basket = get_basket(request)
    supplier = get_default_supplier(shop)
    # create a basket rule that requires atleast value of 200
    rule = BasketTotalAmountCondition.objects.create(value="200")

    product_price = "200"

    discount1 = "10"
    discount2 = "20"
    product = create_product(printable_gibberish(),
                             shop=shop,
                             supplier=supplier,
                             default_price=product_price)
    basket.add_product(supplier=supplier,
                       shop=shop,
                       product=product,
                       quantity=1)
    basket.shipping_method = get_shipping_method(shop=shop)

    campaign = BasketCampaign.objects.create(shop=shop,
                                             public_name="test",
                                             name="test",
                                             active=True)
    campaign.conditions.add(rule)
    campaign.save()

    BasketDiscountAmount.objects.create(discount_amount=discount1,
                                        campaign=campaign)

    dc = Coupon.objects.create(code="TEST", active=True)
    campaign2 = BasketCampaign.objects.create(shop=shop,
                                              public_name="test",
                                              name="test",
                                              coupon=dc,
                                              active=True)

    BasketDiscountAmount.objects.create(discount_amount=discount2,
                                        campaign=campaign2)
    basket.add_product(supplier=supplier,
                       shop=shop,
                       product=product,
                       quantity=1)

    resp = handle_add_campaign_code(request, basket, dc.code)
    assert resp.get("ok")

    discount_lines_values = [
        line.discount_amount for line in basket.get_final_lines()
        if line.type == OrderLineType.DISCOUNT
    ]
    assert price(discount1) in discount_lines_values
    assert price(discount2) in discount_lines_values
    assert basket.total_price == (price(product_price) * basket.product_count -
                                  price(discount1) - price(discount2))

    assert basket.codes == [dc.code]

    # test code removal
    resp = handle_remove_campaign_code(request, basket, dc.code)
    assert resp.get("ok")

    assert basket.codes == []
    discount_lines_values = [
        line.discount_amount for line in basket.get_final_lines()
        if line.type == OrderLineType.DISCOUNT
    ]
    assert price(discount1) in discount_lines_values
    assert not price(discount2) in discount_lines_values
Beispiel #51
0
def test_unknown_theme_fails(rf):
    request = rf.get("/", {"theme": printable_gibberish()})
    request.user = SuperUser()
    request.shop = get_default_shop()
    with pytest.raises(Problem):
        EditorView.as_view()(request)
def test_delete_folder():
    folder = Folder.objects.create(name=printable_gibberish())
    mbv_command({"action": "delete_folder", "id": folder.pk})
    assert not Folder.objects.filter(pk=folder.pk).exists()
Beispiel #53
0
def test_product_category_discount_amount_with_minimum_price(rf):
    # Buy X amount of Y get Z discount from Y
    request, shop, _ = initialize_test(rf, False)

    basket = get_basket(request)
    supplier = get_default_supplier(shop)

    single_product_price = Decimal("50")
    single_product_min_price = Decimal("40")
    discount_amount_value = Decimal("200")  # will exceed the minimum price
    quantity = 2

    # the expected discount amount should not be greater than the products
    expected_discount_amount = basket.create_price(
        single_product_price) * quantity

    category = CategoryFactory()

    # create basket rule that requires 2 products in basket
    product = create_product(printable_gibberish(),
                             shop=shop,
                             supplier=supplier,
                             default_price=single_product_price)
    shop_product = ShopProduct.objects.get(shop=shop, product=product)
    shop_product.minimum_price_value = single_product_min_price
    shop_product.save()
    shop_product.categories.add(category)

    basket.add_product(supplier=supplier,
                       shop=shop,
                       product=product,
                       quantity=quantity)
    basket.shipping_method = get_shipping_method(shop=shop)
    basket.save()

    rule = ProductsInBasketCondition.objects.create(quantity=2)
    rule.products.add(product)
    rule.save()

    campaign = BasketCampaign.objects.create(active=True,
                                             shop=shop,
                                             name="test",
                                             public_name="test")
    campaign.conditions.add(rule)

    DiscountFromCategoryProducts.objects.create(
        campaign=campaign,
        discount_amount=discount_amount_value,
        category=category)
    assert rule.matches(basket, [])
    basket.uncache()

    # the discount amount should not exceed the minimum price. as the configued discount
    # will exceed, it should limit the discount amount
    final_lines = basket.get_final_lines()
    expected_discount_amount = basket.create_price(
        (single_product_price - single_product_min_price) * quantity)
    original_price = basket.create_price(single_product_price) * quantity
    line = final_lines[0]
    assert line.discount_amount == expected_discount_amount
    assert basket.total_price == original_price - expected_discount_amount
Beispiel #54
0
def test_variation_templates(browser, admin_user, live_server, settings):
    cache.clear()  # Avoid cache from past tests
    shop = get_default_shop()
    configuration_key = "saved_variation_templates"
    assert configuration.get(shop, configuration_key, None) is None
    product = create_product("test_sku",
                             shop,
                             default_price=10,
                             mode=ProductMode.VARIABLE_VARIATION_PARENT)
    assert product.is_variation_parent()
    initialize_admin_browser_test(browser, live_server, settings)
    browser.driver.set_window_size(800, 1000)
    url = reverse("shuup_admin:shop_product.edit_variation",
                  kwargs={"pk": product.pk})
    browser.visit("%s%s" % (live_server, url + "#variables-section"))
    click_element(browser,
                  '#variables-section > div:nth-child(1) > a:nth-child(2)')
    wait_until_condition(browser, lambda x: x.is_text_present("New template"))

    assert len(
        ProductVariationVariable.objects.filter(product=product)) == 0  # Size
    assert len(ProductVariationVariableValue.objects.all()
               ) == 0  # Assert no variations are active
    click_element(browser, '.fa.fa-plus')

    wait_until_condition(browser, lambda x: x.is_text_present("New template"))
    browser.fill("variables-template_name",
                 printable_gibberish())  # variables-template_name
    click_element(browser, '#save_template_name')
    wait_until_condition(browser,
                         lambda x: not x.is_text_present("New template"))
    assert len(configuration.get(shop, configuration_key, [])) == 1
    click_element(browser,
                  '#variables-section > div:nth-child(1) > a:nth-child(2)')
    click_element(browser, "#variation-variable-editor")
    browser.find_by_xpath(
        '//*[@id="variation-variable-editor"]/div/div/select/option[2]'
    ).first.click()
    wait_until_condition(browser,
                         lambda x: x.is_text_present("Add new variable"))
    click_element(browser, ".btn.btn-lg.btn-text")
    browser.find_by_xpath(
        '//*[@id="product-variable-wrap"]/div/div[2]/div[1]/table/tbody[1]/tr/td[1]/input'
    ).first.fill("Size")
    click_element(browser, ".btn.btn-xs.btn-text")
    browser.find_by_xpath(
        '//*[@id="product-variable-wrap"]/div/div[2]/div[1]/table/tbody[2]/tr/td[1]/input'
    ).first.fill("S")
    click_element(browser, ".fa.fa-check-circle")  # Save

    assert len(
        ProductVariationVariable.objects.filter(product=product)) == 1  # Size
    assert len(ProductVariationVariableValue.objects.all()) == 1  # S

    click_element(browser,
                  '#variables-section > div:nth-child(1) > a:nth-child(2)')
    click_element(browser, "#variation-variable-editor")  # id_variables-data
    cache.clear()  # Avoid cache from past tests
    assert len(configuration.get(shop, configuration_key, [])) == 1

    browser.find_by_xpath(
        '//*[@id="variation-variable-editor"]/div/div/select/option[2]'
    ).first.click()
    template_data = configuration.get(shop, configuration_key,
                                      [])[0].get('data')[0]
    browser_data = json.loads(browser.find_by_css(
        "#id_variables-data").value).get('variable_values')[0]
    assert browser_data == template_data  # assert shown template data matches template data in the db
Beispiel #55
0
def test_discount_no_limits(rf, include_tax):
    # check whether is it possible to earn money buying from us
    # adding lots of effects
    request, shop, _ = initialize_test(rf, include_tax)

    basket = get_basket(request)
    supplier = get_default_supplier(shop)

    single_product_price = Decimal(50)
    quantity = 4
    discount_amount = (single_product_price * quantity * 2)
    discount_percentage = Decimal(1.9)  # 190%

    second_product = create_product(printable_gibberish(),
                                    shop=shop,
                                    supplier=supplier,
                                    default_price=single_product_price)

    # the expected discount amount should not be greater than the products
    expected_discount_amount = basket.create_price(
        single_product_price) * quantity

    category = CategoryFactory()

    # create basket rule that requires 2 products in basket
    product = create_product(printable_gibberish(),
                             shop=shop,
                             supplier=supplier,
                             default_price=single_product_price)
    ShopProduct.objects.get(shop=shop,
                            product=product).categories.add(category)
    basket.add_product(supplier=supplier,
                       shop=shop,
                       product=product,
                       quantity=quantity)
    basket.shipping_method = get_shipping_method(shop=shop)
    basket.save()

    rule = ProductsInBasketCondition.objects.create(quantity=2)
    rule.products.add(product)
    rule.save()

    # BasketCampaign
    campaign = BasketCampaign.objects.create(active=True,
                                             shop=shop,
                                             name="test",
                                             public_name="test")
    campaign.conditions.add(rule)

    # effect 1 - categories from products
    DiscountFromCategoryProducts.objects.create(
        campaign=campaign,
        discount_percentage=discount_percentage,
        category=category)

    # effect 2 - discount from products
    effect2 = DiscountFromProduct.objects.create(
        campaign=campaign, discount_amount=discount_amount)
    effect2.products.add(product)

    # effect 3 - basket discount
    BasketDiscountAmount.objects.create(campaign=campaign,
                                        discount_amount=discount_amount)

    # effect 4 - basket discount percetage
    BasketDiscountPercentage.objects.create(
        campaign=campaign, discount_percentage=discount_percentage)

    basket.uncache()

    final_lines = basket.get_final_lines()
    assert len(final_lines) == 3

    original_price = basket.create_price(single_product_price) * quantity
    line = final_lines[0]
    assert line.discount_amount == expected_discount_amount
    assert basket.total_price == original_price - expected_discount_amount

    # effect free - aaaww yes, it's free
    effect_free = FreeProductLine.objects.create(campaign=campaign, quantity=1)
    effect_free.products.add(second_product)

    basket.uncache()

    final_lines = basket.get_final_lines()
    assert len(final_lines) == 4
    line = final_lines[0]
    assert line.discount_amount == expected_discount_amount
    assert basket.total_price == original_price - expected_discount_amount

    # CatalogCampaign
    catalog_campaign = CatalogCampaign.objects.create(active=True,
                                                      shop=shop,
                                                      name="test2",
                                                      public_name="test")
    product_filter = ProductFilter.objects.create()
    product_filter.products.add(product)
    catalog_campaign.filters.add(product_filter)

    # effect 5 - ProductDiscountAmount
    ProductDiscountAmount.objects.create(campaign=catalog_campaign,
                                         discount_amount=discount_amount)

    # effct 6 - ProductDiscountPercentage
    ProductDiscountPercentage.objects.create(
        campaign=catalog_campaign, discount_percentage=discount_percentage)

    basket.uncache()

    final_lines = basket.get_final_lines()
    assert len(final_lines) == 4
    line = final_lines[0]
    assert line.discount_amount == expected_discount_amount
    assert basket.total_price == original_price - expected_discount_amount
def test_multiple_campaigns_cheapest_price():
    rf = RequestFactory()
    request, shop, group = initialize_test(rf, False)
    price = shop.create_price
    product_price = "100"
    discount_percentage = "0.30"
    discount_amount_value = "10"
    total_discount_amount = "50"

    expected_total = price(product_price) - (Decimal(discount_percentage) *
                                             price(product_price))
    matching_expected_total = price(product_price) - price(
        total_discount_amount)

    category = get_default_category()
    supplier = get_default_supplier()
    product = create_product(printable_gibberish(),
                             shop=shop,
                             supplier=supplier,
                             default_price=product_price)
    shop_product = product.get_shop_instance(shop)
    shop_product.categories.add(category)

    # create catalog campaign
    catalog_filter = ProductFilter.objects.create()
    catalog_filter.products.add(product)
    catalog_campaign = CatalogCampaign.objects.create(shop=shop,
                                                      active=True,
                                                      name="test")
    catalog_campaign.filters.add(catalog_filter)

    cdp = ProductDiscountPercentage.objects.create(
        campaign=catalog_campaign, discount_percentage=discount_percentage)

    # create basket campaign
    condition = CategoryProductsBasketCondition.objects.create(
        operator=ComparisonOperator.EQUALS, quantity=1)
    condition.categories.add(category)
    basket_campaign = BasketCampaign.objects.create(shop=shop,
                                                    public_name="test",
                                                    name="test",
                                                    active=True)
    basket_campaign.conditions.add(condition)

    effect = DiscountFromProduct.objects.create(
        campaign=basket_campaign, discount_amount=discount_amount_value)
    effect.products.add(product)

    # add product to basket
    basket = get_basket(request)
    basket.add_product(supplier=supplier,
                       shop=shop,
                       product=product,
                       quantity=1)
    basket.shipping_method = get_shipping_method(shop=shop)
    final_lines = basket.get_final_lines()
    assert len(final_lines) == 2
    assert basket.total_price == expected_total

    effect.discount_amount = total_discount_amount
    effect.save()
    basket.uncache()
    catalog_campaign.save()  # save to bump caches
    basket_campaign.save()  # save to bump caches

    assert basket.total_price == matching_expected_total  # discount is now bigger than the original

    effect.delete()  # remove effect
    basket.uncache()
    catalog_campaign.save()  # save to bump caches
    basket_campaign.save()  # save to bump caches

    assert BasketLineEffect.objects.count() == 0

    assert basket.total_price == expected_total
    # add new effect
    effect = DiscountFromCategoryProducts.objects.create(
        category=category,
        campaign=basket_campaign,
        discount_amount=discount_amount_value)
    assert basket.total_price == expected_total

    effect.discount_amount = total_discount_amount
    effect.save()
    basket.uncache()
    catalog_campaign.save()  # save to bump caches
    basket_campaign.save()  # save to bump caches
    assert basket.total_price == matching_expected_total  # discount is now bigger than the original
Beispiel #57
0
def test_variation_detail_view(client):
    shop = get_default_shop()

    parent = create_product(printable_gibberish(), shop)

    assert parent.mode == ProductMode.NORMAL

    volume = ProductVariationVariable.objects.create(
        identifier="volume",
        name="volume",
        product=parent,
        ordering=0,
    )
    for index, value in enumerate(["1ml", "2ml", "3ml"]):
        ProductVariationVariableValue.objects.create(
            identifier=value,
            value=value,
            variable=volume,
            ordering=index,
        )

    color = ProductVariationVariable.objects.create(
        identifier="color",
        name="color",
        product=parent,
        ordering=1,
    )
    for index, value in enumerate(["red", "green", "blue"]):
        ProductVariationVariableValue.objects.create(
            identifier=value,
            value=value,
            variable=color,
            ordering=index,
        )

    child = create_product(printable_gibberish(), shop)

    values = [volume.values.all()[1], color.values.all()[1]]
    assert child.link_to_parent(
        parent,
        variables={
            volume: values[0],
            color: values[1],
        },
    )

    assert parent.mode == ProductMode.VARIABLE_VARIATION_PARENT

    variation_url = "{}?variation={}".format(
        reverse("shuup:product", kwargs=dict(pk=parent.pk, slug=parent.slug)), child.sku
    )
    response = client.get(variation_url + "BAD_VARIATION_SKU")
    assert response.status_code == 404

    response = client.get(variation_url)
    assert response.status_code == 200

    assert response.context_data["shop_product"]

    assert response.context_data["selected_variation"] == child
    assert response.context_data["selected_variation_values"] == [v.pk for v in values]
Beispiel #58
0
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_product_visibility(rf, admin_user, regular_user):
    anon_contact = get_person_contact(AnonymousUser())
    shop_product = get_default_shop_product()
    admin_contact = get_person_contact(admin_user)
    regular_contact = get_person_contact(regular_user)

    configuration.set(None, get_all_seeing_key(admin_contact), True)

    with modify(
            shop_product.product, deleted=True
    ):  # NB: assigning to `product` here works because `get_shop_instance` populates `_product_cache`
        assert error_exists(
            shop_product.get_visibility_errors(customer=anon_contact),
            "product_deleted")
        assert error_exists(
            shop_product.get_visibility_errors(customer=admin_contact),
            "product_deleted")
        with pytest.raises(ProductNotVisibleProblem):
            shop_product.raise_if_not_visible(anon_contact)
        assert not shop_product.is_list_visible()

    with modify(shop_product,
                visibility_limit=ProductVisibility.VISIBLE_TO_ALL,
                visibility=ShopProductVisibility.NOT_VISIBLE):
        assert error_exists(
            shop_product.get_visibility_errors(customer=anon_contact),
            "product_not_visible")
        assert error_does_not_exist(
            shop_product.get_visibility_errors(customer=admin_contact),
            "product_not_visible")
        assert not shop_product.is_list_visible()

    with modify(shop_product,
                visibility_limit=ProductVisibility.VISIBLE_TO_LOGGED_IN,
                visibility=ShopProductVisibility.ALWAYS_VISIBLE):
        assert error_exists(
            shop_product.get_visibility_errors(customer=anon_contact),
            "product_not_visible_to_anonymous")
        assert error_does_not_exist(
            shop_product.get_visibility_errors(customer=admin_contact),
            "product_not_visible_to_anonymous")

    customer_group = get_default_customer_group()
    grouped_user = get_user_model().objects.create_user(
        username=printable_gibberish(20))
    grouped_contact = get_person_contact(grouped_user)
    with modify(shop_product,
                visibility_limit=ProductVisibility.VISIBLE_TO_GROUPS,
                visibility=ShopProductVisibility.ALWAYS_VISIBLE):
        shop_product.visibility_groups.add(customer_group)
        customer_group.members.add(grouped_contact)
        customer_group.members.remove(get_person_contact(regular_user))
        assert error_does_not_exist(
            shop_product.get_visibility_errors(customer=grouped_contact),
            "product_not_visible_to_group")
        assert error_does_not_exist(
            shop_product.get_visibility_errors(customer=admin_contact),
            "product_not_visible_to_group")
        assert error_exists(
            shop_product.get_visibility_errors(customer=regular_contact),
            "product_not_visible_to_group")

    configuration.set(None, get_all_seeing_key(admin_contact), False)
Beispiel #60
0
def test_user_create(rf, admin_user):
    shop = get_default_shop()
    view_func = UserDetailView.as_view()
    before_count = get_user_model().objects.count()
    response = view_func(
        apply_request_middleware(rf.post(
            "/", {
                "username": "******",
                "email": "*****@*****.**",
                "first_name": "test",
                "last_name": "test",
                "password": "******",
                "send_confirmation": True
            }),
                                 user=admin_user))
    assert response.status_code == 302
    assert get_user_model().objects.count() == before_count + 1
    last_user = get_user_model().objects.last()
    assert last_user not in shop.staff_members.all()
    assert not len(mail.outbox), "mail not sent since user is not staff"

    response = view_func(
        apply_request_middleware(rf.post(
            "/", {
                "username": "******",
                "email": "*****@*****.**",
                "first_name": "test",
                "last_name": "test",
                "password": "******",
                "is_staff": True,
                "send_confirmation": True
            }),
                                 user=admin_user))
    assert response.status_code == 302
    assert get_user_model().objects.count() == before_count + 2
    last_user = get_user_model().objects.last()
    assert last_user in shop.staff_members.all()
    assert len(mail.outbox) == 1, "mail sent"

    user = get_user_model().objects.create(username=printable_gibberish(20),
                                           first_name=printable_gibberish(10),
                                           last_name=printable_gibberish(10),
                                           password="******",
                                           is_staff=True,
                                           is_superuser=False)
    response = view_func(apply_request_middleware(rf.get("/", user=user)))
    assert response.status_code == 200
    response.render()
    assert "Staff status" not in force_text(response.content)
    assert "Superuser status" not in force_text(response.content)

    # remove user staff permission
    view_func = UserChangePermissionsView.as_view()
    response = view_func(apply_request_middleware(rf.post(
        "/", {"is_staff": False}),
                                                  user=admin_user),
                         pk=last_user.id)
    assert response.status_code == 302
    last_user = get_user_model().objects.last()
    assert last_user not in shop.staff_members.all()

    # add again
    view_func = UserChangePermissionsView.as_view()
    response = view_func(apply_request_middleware(rf.post(
        "/", {"is_staff": True}),
                                                  user=admin_user),
                         pk=last_user.id)
    assert response.status_code == 302
    last_user = get_user_model().objects.last()
    assert last_user in shop.staff_members.all()