예제 #1
0
def test_order_creator_account_manager():
    company = create_random_company()
    shop = get_shop(identifier="random-shop", enabled=True)
    source = seed_source(create_random_user(), shop)
    source.customer = company
    source.add_line(
        type=OrderLineType.PRODUCT,
        product=get_default_product(),
        supplier=get_default_supplier(),
        quantity=1,
        base_unit_price=source.create_price(10),
    )
    creator = OrderCreator()
    order = creator.create_order(source)
    assert order.account_manager is None  # Company contact doesn't have account manager field

    person = create_random_person()
    person.account_manager = create_random_person()
    person.save()

    source = seed_source(create_random_user(), shop)
    source.customer = person
    source.add_line(
        type=OrderLineType.PRODUCT,
        product=get_default_product(),
        supplier=get_default_supplier(),
        quantity=1,
        base_unit_price=source.create_price(10),
    )
    creator = OrderCreator()
    order = creator.create_order(source)
    assert order.account_manager is not None
    assert order.account_manager == person.account_manager
    with pytest.raises(ProtectedError):
        person.account_manager.delete()
예제 #2
0
def test_context_contact_condition():
    rf = RequestFactory()
    original_price_value, discount_value = 2, 1
    request = get_request_for_contact_tests(rf)
    random_person = create_random_person()
    condition = ContactCondition.objects.create()
    condition.contacts.add(random_person)
    product = create_random_product_and_campaign(request.shop, [condition], original_price_value, discount_value)

    # random_person should get this campaign
    discounted_value = original_price_value - discount_value
    assert_product_price_value_with_customer(request, random_person, product, discounted_value)

    another_random_person = create_random_person()
    # another random person shouldn't
    assert_product_price_value_with_customer(request, another_random_person, product, original_price_value)

    # Add another random person for the rule and see if he get's the discount
    condition.contacts.add(another_random_person)
    assert_product_price_value_with_customer(request, another_random_person, product, discounted_value)

    # Remove random person from rule and see the discount disappear
    condition.contacts.remove(random_person)
    condition.save()
    assert_product_price_value_with_customer(request, random_person, product, original_price_value)
예제 #3
0
def test_category_links_plugin_with_customer(rf, show_all_categories):
    """
    Test plugin for categories that is visible for certain group
    """
    shop = get_default_shop()
    group = get_default_customer_group()
    customer = create_random_person()
    customer.groups.add(group)
    customer.save()

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

    category = get_default_category()
    category.status = CategoryStatus.VISIBLE
    category.visibility = CategoryVisibility.VISIBLE_TO_GROUPS
    category.visibility_groups.add(group)
    category.shops.add(shop)
    category.save()

    vars = {"request": request}
    context = get_jinja_context(**vars)
    plugin = CategoryLinksPlugin({"categories": [category.pk], "show_all_categories": show_all_categories})
    assert category.is_visible(customer)
    assert category in plugin.get_context_data(context)["categories"]

    customer_without_groups = create_random_person()
    customer_without_groups.groups.clear()

    assert not category.is_visible(customer_without_groups)
    request.customer = customer_without_groups
    context = get_jinja_context(**vars)
    assert category not in plugin.get_context_data(context)["categories"]
def test_basket_contact_condition(rf):
    product_price_value, campaign_discount_value = 2, 1
    request = get_request_for_contact_tests(rf)
    random_person = create_random_person()
    request.customer = random_person
    condition = ContactBasketCondition.objects.create()
    condition.contacts.add(random_person)
    basket, original_line_count, original_price = create_basket_and_campaign(
        request, [condition], product_price_value, campaign_discount_value)

    # random_person should get this campaign
    assert basket.customer == random_person
    assert_discounted_basket(basket, original_line_count, original_price, campaign_discount_value)

    another_random_person = create_random_person()
    basket.customer = another_random_person
    # another random person shouldn't
    assert_non_discounted_basket(basket, original_line_count, original_price)

    # Add another random person for the rule and see if he get's the discount
    condition.contacts.add(another_random_person)
    condition.save()
    assert_discounted_basket(basket, original_line_count, original_price, campaign_discount_value)
    assert basket.customer == another_random_person

    # Remove random person from rule and see the discount disappear
    condition.contacts.remove(random_person)
    condition.save()
    basket.customer = random_person
    assert_non_discounted_basket(basket, original_line_count, original_price)
    assert basket.customer == random_person
예제 #5
0
def test_customer_usage_limit(rf):
    default_price = 10
    request, product = _init_test_for_product_without_basket(rf, default_price)
    shop = request.shop
    customers = []
    for x in range(3):
        customers.append(factories.create_random_company(shop=shop))

    discount_percentage = 0.20
    coupon = CouponCode.objects.create(code="sUpErAle", active=True, usage_limit_customer=2)
    coupon.shops = [request.shop]
    discount = Discount.objects.create(
        active=True, product=product, coupon_code=coupon, discount_percentage=discount_percentage)
    discount.shops.add(request.shop)

    # Order product twice for each customer
    for customer in customers:
        for y in range(2):
            _create_order(request, customer, coupon, product, request.shop.create_price(8))

    assert coupon.usages.count() == 6  # Each customer 2 orders

    # Any of the customers created shouldn't be allowed to
    # order more with this coupon code.
    for customer in customers:
        assert not CouponCode.is_usable(shop, coupon, customer)

    # New customer should still be able to order some
    new_customer = factories.create_random_person()
    assert CouponCode.is_usable(shop, coupon, new_customer)
    _create_order(request, new_customer, coupon, product, request.shop.create_price(8))

    assert coupon.usages.count() == 7

    # Set usage limit and the new customer shouldn't be able to use the code
    coupon.usage_limit = 7
    coupon.save()
    assert not CouponCode.is_usable(request.shop, coupon, new_customer)
    _create_order(request, new_customer, coupon, product, request.shop.create_price(default_price))
    assert coupon.usages.count() == 7

    # One of the customer got refund
    refunded_customer = customers[0]
    order = refunded_customer.customer_orders.first()
    coupon_code_modifier = CouponCodeModule()
    coupon_code_modifier.clear_codes(order)

    assert coupon.usages.count() == 6

    # New customer still doesn't  able to create coupon
    new_customer = factories.create_random_person()
    assert CouponCode.is_usable(shop, coupon, new_customer)
    _create_order(request, new_customer, coupon, product, request.shop.create_price(8))
    assert coupon.usages.count() == 7
예제 #6
0
def test_get_by_pk(admin_user):
    get_default_shop()
    for i in range(0,10):
        create_random_person()

    contact = create_random_person()
    client = _get_client(admin_user)
    response = client.get("/api/shuup/contact/%s/" % contact.id)
    assert response.status_code == status.HTTP_200_OK
    contact_data = json.loads(response.content.decode("utf-8"))
    assert contact_data.get("id") == contact.id
    assert contact_data.get("name") == contact.name
예제 #7
0
def test_get_shipments(admin_user):
    client = _get_client(admin_user)
    shop1 = get_shop(True)
    shop2 = get_shop(True)
    customer1 = create_random_person()
    customer2 = create_random_person()
    order1 = create_random_order(customer1, shop=shop1, completion_probability=1)
    order2 = create_random_order(customer2, shop=shop1, completion_probability=1)
    order3 = create_random_order(customer1, shop=shop2, completion_probability=1)
    order4 = create_random_order(customer2, shop=shop1, completion_probability=1)

    # list shipments
    response = client.get("/api/shuup/shipment/")
    assert response.status_code == status.HTTP_200_OK
    shipment_data = json.loads(response.content.decode("utf-8"))
    assert len(shipment_data) == 4
    assert shipment_data[0]["id"] == order1.shipments.first().pk
    assert shipment_data[1]["id"] == order2.shipments.first().pk
    assert shipment_data[2]["id"] == order3.shipments.first().pk
    assert shipment_data[3]["id"] == order4.shipments.first().pk

    # get shipment by id
    response = client.get("/api/shuup/shipment/%s/" % order1.shipments.first().pk)
    assert response.status_code == status.HTTP_200_OK
    shipment_data = json.loads(response.content.decode("utf-8"))
    assert shipment_data["id"] == order1.shipments.first().pk
    assert shipment_data["order"] == order1.pk

    # get shipment by product
    product = order2.shipments.first().products.first()
    response = client.get("/api/shuup/shipment/?product=%s" % product.pk)
    assert response.status_code == status.HTTP_200_OK
    shipment_data = json.loads(response.content.decode("utf-8"))
    for ship in shipment_data:
        for ship_product in shipment_data["product"]:
            assert ship_product["id"] == product.pk
            assert ship_product["order"] == order2.pk

    # get shipment by order
    response = client.get("/api/shuup/shipment/?order=%s" % order3.pk)
    assert response.status_code == status.HTTP_200_OK
    shipment_data = json.loads(response.content.decode("utf-8"))
    for ship in shipment_data:
        assert ship["order"] == order3.pk

    # get shipment by shop
    response = client.get("/api/shuup/shipment/?shop=%s" % shop1.pk)
    assert response.status_code == status.HTTP_200_OK
    shipment_data = json.loads(response.content.decode("utf-8"))
    for ship in shipment_data:
        assert Shipment.objects.filter(pk=ship["id"], order__shop=shop1).exists()
예제 #8
0
def test_min_amount_is_not_included():
    shop = get_default_shop()
    supplier = get_default_supplier()
    person = create_random_person()
    initial_group_count = person.groups.count()
    sales_ranges = [
        ("silver", 0, 50),
        ("gold", 50, 100),
        ("diamond", 100, 1000),
        ("reverse_diamond", 1000, 100)
    ]
    for identifier, min, max in sales_ranges:
        create_sales_range(identifier, shop, min, max)

    payment = create_fully_paid_order(shop, person, supplier, "sku1", 50)
    assert get_total_sales(shop, person) == 50
    update_customers_groups(Payment, payment)
    assert person.groups.count() == (initial_group_count + 1)
    assert bool([group for group in person.groups.all() if group.identifier == "gold"])
    assert not bool([group for group in person.groups.all() if group.identifier in ["silver", "diamond"]])

    payment = create_fully_paid_order(shop, person, supplier, "sku2", 50)
    assert get_total_sales(shop, person) == 100
    update_customers_groups(Payment, payment)
    assert person.groups.count() == (initial_group_count + 1)
    assert bool([group for group in person.groups.all() if group.identifier == "diamond"])
    assert not bool([group for group in person.groups.all() if group.identifier == "reverse_diamond"])
    assert not bool([group for group in person.groups.all() if group.identifier in ["silver", "gold"]])
예제 #9
0
def test_sales_ranges_update_after_range_update():
    shop = get_default_shop()
    supplier = get_default_supplier()
    person = create_random_person()
    company = create_random_company()
    create_fully_paid_order(shop, person, supplier, "sku1", 50)
    create_fully_paid_order(shop, company, supplier, "sku2", 100)
    assert get_total_sales(shop, person) == 50
    assert get_total_sales(shop, company) == 100

    sales_range = create_sales_range("gold", shop, 10, 90)
    assert sales_range.group in person.groups.all()
    assert sales_range.group not in company.groups.all()

    sales_range.max_value = None
    sales_range.save()
    assert sales_range.group in person.groups.all()
    assert sales_range.group in company.groups.all()

    # Make sure customers is actually removed when range changes
    sales_range.max_value = 60
    sales_range.save()
    assert sales_range.group in person.groups.all()
    assert sales_range.group not in company.groups.all()

    # Inactive ranges shouldn't update group members
    sales_range.min_value = None
    sales_range.save()
    assert sales_range.group in person.groups.all()
    assert sales_range.group not in company.groups.all()
예제 #10
0
def test_create_new_basket(admin_user):
    with override_settings(**REQUIRED_SETTINGS):
        shop = factories.get_default_shop()
        shop2 = create_shop("foobar")
        client = _get_client(admin_user)
        response = client.post("/api/shuup/basket/new/", {
            "shop": shop2.pk
        })
        assert response.status_code == status.HTTP_201_CREATED
        basket_data = json.loads(response.content.decode("utf-8"))
        basket = Basket.objects.first()
        assert basket.key == basket_data['uuid'].split("-")[1]
        assert basket.shop == shop2
        admin_contact = get_person_contact(admin_user)
        assert basket.customer == admin_contact
        assert basket.orderer == admin_contact
        assert basket.creator == admin_user

        # invalid shop
        response = client.post("/api/shuup/basket/new/", data={"shop": 1000})
        assert response.status_code == status.HTTP_400_BAD_REQUEST

        # no shop in multishop mode
        response = client.post("/api/shuup/basket/new/")
        assert response.status_code == status.HTTP_400_BAD_REQUEST

        # no shop in single shop mode
        with override_settings(SHUUP_ENABLE_MULTIPLE_SHOPS=False):
            response = client.post("/api/shuup/basket/new/")
            assert response.status_code == status.HTTP_201_CREATED
            basket_data = json.loads(response.content.decode("utf-8"))
            basket = Basket.objects.all()[1]
            assert basket.key == basket_data['uuid'].split("-")[1]
            assert basket.shop == shop
            assert basket.customer == admin_contact
            assert basket.orderer == admin_contact
            assert basket.creator == admin_user

            person = factories.create_random_person()

            response = client.post("/api/shuup/basket/new/", data={"customer": person.pk})
            assert response.status_code == status.HTTP_201_CREATED
            basket_data = json.loads(response.content.decode("utf-8"))
            basket = Basket.objects.all()[2]
            assert basket.key == basket_data['uuid'].split("-")[1]
            assert basket.shop == shop
            assert basket.creator == admin_user
            assert basket.customer.pk == person.pk
            assert basket.orderer.pk == person.pk
            assert basket.creator.pk == admin_user.pk

            # Try to fetch the basket as the customer
            user = factories.UserFactory()
            person.user = user
            person.save()
            response = client.get("/api/shuup/basket/{}/".format(basket_data['uuid']))
            assert response.status_code == 200
            customer_basket_data = json.loads(response.content.decode("utf-8"))
            assert basket.key == customer_basket_data['key']  # Still same basket as before
            assert customer_basket_data['customer']['id'] == person.pk  # Still same customer as before
예제 #11
0
def test_product_price_info(admin_user, prices_include_tax):
    shop = get_default_shop()
    shop.prices_include_tax = prices_include_tax
    shop.save()

    customer = create_random_person()
    group = customer.get_default_group()
    customer.user = admin_user
    customer.groups.add(group)
    customer.save()

    PRICE = 200.0
    DISCOUNT = 15.0

    product = create_product("Just-A-Product", shop, default_price=PRICE)
    CgpDiscount.objects.create(product=product, shop=shop, group=group, discount_amount_value=DISCOUNT)

    client = _get_client(admin_user)
    response = client.get("/api/shuup/front/shop_products/")
    products_data = json.loads(response.content.decode("utf-8"))

    assert products_data[0]["price"] == (PRICE-DISCOUNT)
    assert products_data[0]["price_info"]['base_price'] == PRICE
    assert products_data[0]["price_info"]['price'] == (PRICE-DISCOUNT)
    assert products_data[0]["price_info"]['discount_amount'] == DISCOUNT
    assert products_data[0]["price_info"]['discount_rate'] == DISCOUNT/PRICE
    assert products_data[0]["price_info"]['is_discounted'] is True
    assert products_data[0]["price_info"]['discount_percentage'] == DISCOUNT/PRICE * 100

    if prices_include_tax:
        assert products_data[0]["price_info"]['taxful_price'] == (PRICE-DISCOUNT)
    else:
        assert products_data[0]["price_info"]['taxless_price'] == (PRICE-DISCOUNT)
예제 #12
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 . . .
예제 #13
0
def test_mass_edit_contacts(rf, admin_user):
    shop = get_default_shop()
    contact1 = create_random_person()
    contact2 = create_random_person()
    contact1.gender = Gender.FEMALE
    contact1.save()
    contact2.gender = Gender.FEMALE
    contact2.save()
    request = apply_request_middleware(rf.post("/", data={"gender": Gender.MALE.value}), user=admin_user)
    request.session["mass_action_ids"] = [contact1.pk, contact2.pk]

    view = ContactMassEditView.as_view()
    response = view(request=request)
    assert response.status_code == 302
    for contact in Contact.objects.all():
        assert contact.gender == Gender.MALE
예제 #14
0
def test_order_creator_customer_data(rf, admin_user):
    get_default_shop()
    contact = create_random_person(locale="en_US", minimum_name_comp_len=5)
    request = apply_request_middleware(rf.get("/", {"command": "customer_data", "id": contact.id}), user=admin_user)
    response = OrderEditView.as_view()(request)
    assert_contains(response, "name")
    assert_contains(response, contact.name)
예제 #15
0
def test_parallel_baskets(rf):
    request = get_request_with_basket()
    shop = get_default_shop()
    customer = create_random_person()

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

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

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

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

    assert basket_one.product_count == 1
    assert basket_two.product_count == 3.5
예제 #16
0
def test_sales_between_ranges():
    shop = get_default_shop()
    supplier = get_default_supplier()
    person = create_random_person()
    initial_group_count = person.groups.count()
    sales_ranges = [
        ("wood", 15, 0),
        ("silver", 0, 50),
        ("diamond", 100, None)
    ]
    for identifier, min, max in sales_ranges:
        create_sales_range(identifier, shop, min, max)

    payment = create_fully_paid_order(shop, person, supplier, "sku1", 10)
    assert get_total_sales(shop, person) == 10
    update_customers_groups(Payment, payment)
    assert person.groups.count() == (initial_group_count + 1)
    assert bool([group for group in person.groups.all() if group.identifier == "silver"])
    assert not bool([group for group in person.groups.all() if group.identifier == "wood"])

    payment = create_fully_paid_order(shop, person, supplier, "sku2", 50)
    assert get_total_sales(shop, person) == 60
    update_customers_groups(Payment, payment)
    assert person.groups.count() == initial_group_count
    assert not bool([group for group in person.groups.all() if group.identifier in ["silver", "gold", "diamond"]])

    payment = create_fully_paid_order(shop, person, supplier, "sku3", 200)
    assert get_total_sales(shop, person) == 260
    update_customers_groups(Payment, payment)
    assert person.groups.count() == (initial_group_count + 1)
    assert bool([group for group in person.groups.all() if group.identifier == "diamond"])
예제 #17
0
def test_delete_payment(admin_user, rf):
    product = get_default_product()
    shop_product = product.get_shop_instance(get_default_shop())
    shop_product.default_price_value = 20
    shop_product.save()

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

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

    order.refresh_from_db()
    assert order.is_paid()

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

    order.refresh_from_db()
    assert order.is_not_paid()
예제 #18
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)
예제 #19
0
def test_order_creator_source_data(rf, admin_user):
    get_initial_order_status()  # Needed for the API
    contact = create_random_person(locale="en_US", minimum_name_comp_len=5)
    request = get_frontend_request_for_command(get_frontend_order_state(contact), "source_data", admin_user)
    response =OrderEditView.as_view()(request)
    data = json.loads(response.content.decode("utf8"))
    assert len(data.get("orderLines")) == 5
예제 #20
0
def test_user_detail_contact_seed(rf, admin_user):
    get_default_shop()
    contact = create_random_person()

    # Using random data for name and email would need escaping when
    # checking if it is rendered, therefore use something very basic instead
    contact.name = "Matti Perustyyppi"
    contact.email = "*****@*****.**"
    contact.save()

    view_func = UserDetailView.as_view()
    # Check that fields populate . . .
    request = apply_request_middleware(rf.get("/", {"contact_id": contact.pk}), user=admin_user)
    response = view_func(request)
    response.render()
    content = force_text(response.content)
    assert force_text(contact.first_name) in content
    assert force_text(contact.last_name) in content
    assert force_text(contact.email) in content
    # POST the password too to create the user . . .
    post = extract_form_fields(BeautifulSoup(content))
    post["password"] = "******"
    request.method = "POST"
    request.POST = post
    response = view_func(request)
    assert response.status_code < 500
    # Check this new user is visible in the details now
    user = Contact.objects.get(pk=contact.pk).user
    request = apply_request_middleware(rf.get("/", {"contact_id": contact.pk}), user=admin_user)
    response = view_func(request, pk=user.pk)
    response.render()
    content = force_text(response.content)
    assert force_text(contact.first_name) in content
    assert force_text(contact.last_name) in content
    assert force_text(contact.email) in content
예제 #21
0
def test_get_suppliable_products():
    customer = create_random_person()
    shop_product = get_default_shop_product()
    shop = get_default_shop()
    supplier = get_default_supplier()
    # Check for default orderable shop product with unstocked behavior
    assert len(list(supplier.get_suppliable_products(shop, customer=customer))) == 1

    supplier.stock_managed = True
    supplier.save()

    # Make sure supplier now omits unorderable product
    assert not list(supplier.get_suppliable_products(shop, customer=customer))
    assert len(list(supplier.get_orderability_errors(shop_product, quantity=1, customer=customer))) == 1

    shop_product.backorder_maximum = 10
    shop_product.save()

    assert len(list(supplier.get_suppliable_products(shop, customer=customer))) == 1
    assert len(list(supplier.get_orderability_errors(shop_product, quantity=10, customer=customer))) == 0
    assert len(list(supplier.get_orderability_errors(shop_product, quantity=11, customer=customer))) == 1

    shop_product.backorder_maximum = None
    shop_product.save()

    assert len(list(supplier.get_suppliable_products(shop, customer=customer))) == 1
    assert len(list(supplier.get_orderability_errors(shop_product, quantity=1000, customer=customer))) == 0
예제 #22
0
def test_contact_details_view_with_many_groups(rf, admin_user):
    get_default_shop()
    person = create_random_person()
    person.groups.add(
        ContactGroup.objects.create(name="Czz Group"),
        ContactGroup.objects.create(name="Azz Group"),
        ContactGroup.objects.create(name="Bzz Group"),
        ContactGroup.objects.language('fi').create(name="Dzz ryhmä"),
    )

    # Group with name in two languages
    grp_e = ContactGroup.objects.language('en').create(name="Ezz Group")
    grp_e.set_current_language('fi')
    grp_e.name = "Ezz ryhmä"
    grp_e.save()
    person.groups.add(grp_e)

    request = apply_request_middleware(rf.get("/"), user=admin_user)
    with translation.override('en'):
        view_func = ContactDetailView.as_view()
        response = view_func(request, pk=person.pk)
    content = response.render().content.decode('utf-8')
    assert "Azz Group" in content
    assert "Bzz Group" in content
    assert "Czz Group" in content
    assert "Dzz ryhmä" in content, "no name in active language, still present"
    assert "Ezz Group" in content, "rendered with active language"
    positions = [content.index(x + "zz ") for x in 'ABCDE']
    assert positions == sorted(positions), "Groups are sorted"
    assert response.status_code == 200
예제 #23
0
def test_order_creator_view_for_customer(rf, admin_user):
    get_default_shop()
    contact = create_random_person(locale="en_US", minimum_name_comp_len=5)
    request = apply_request_middleware(rf.get("/", {"contact_id": contact.id}), user=admin_user)
    response = OrderEditView.as_view()(request)
    assert_contains(response, "customerData")  # in the config
    assert_contains(response, "isCompany")  # in the config
예제 #24
0
def test_campaign_with_non_active_coupon(rf):
    initial_status = get_initial_order_status()
    request, shop, group = initialize_test(rf, include_tax=False)
    order = _get_order_with_coupon(request, initial_status)
    coupon = order.coupon_usages.first().coupon
    coupon.active = False
    coupon.save()

    modifier = UserFactory()
    contact = create_random_person(locale="en_US", minimum_name_comp_len=5)
    assert order.customer != contact
    state = _get_frontend_order_state(shop, contact)
    assert order.shop.id == state["shop"]["selected"]["id"]

    request = get_frontend_request_for_command(state, "finalize", modifier)
    response = OrderEditView.as_view()(request, pk=order.pk)
    assert_contains(response, "orderIdentifier")
    data = json.loads(response.content.decode("utf8"))
    edited_order = Order.objects.get(pk=order.pk)

    assert edited_order.identifier == data["orderIdentifier"] == order.identifier
    assert edited_order.pk == order.pk
    assert edited_order.lines.count() == 3
    assert OrderLineType.DISCOUNT not in [l.type for l in edited_order.lines.all()]
    assert edited_order.coupon_usages.count() == 0
예제 #25
0
def test_product_pricing_cache(admin_user):
    shop = get_default_shop()
    group = create_random_contact_group()
    group2 = create_random_contact_group()
    product = create_product("Just-A-Product", shop, default_price=200)
    CgpPrice.objects.create(product=product, shop=shop, group=group, price_value=175)
    CgpPrice.objects.create(product=product, shop=shop, group=group2, price_value=150)
    client = _get_client(admin_user)
    response = client.get("/api/shuup/front/shop_products/")
    products_data = json.loads(response.content.decode("utf-8"))
    assert products_data[0]["price"] == 200

    user = get_user_model().objects.first()
    user.pk = None
    user.username = "******"
    user.save()
    customer = create_random_person()
    customer.groups.add(group)
    customer.user = user
    customer.save()
    client = _get_client(user)
    response = client.get("/api/shuup/front/shop_products/")
    products_data = json.loads(response.content.decode("utf-8"))
    assert products_data[0]["price"] == 175

    client = _get_client(admin_user)
    response = client.get("/api/shuup/front/shop_products/")
    products_data = json.loads(response.content.decode("utf-8"))
    assert products_data[0]["price"] == 200
예제 #26
0
def test_coupon_amount_limit():
    coupon = Coupon.objects.create(code="TEST", active=True)
    get_default_campaign(coupon)

    contact = create_random_person()
    shop = get_default_shop()
    product = create_product("test", shop=shop, supplier=get_default_supplier(), default_price="12")
    order = create_random_order(customer=contact)

    for x in range(50):
       coupon.use(order)

    assert coupon.usages.count() == 50
    coupon.increase_usage_limit_by(5)
    coupon.save()

    assert coupon.usage_limit == 55
    assert coupon.can_use_code(contact)

    for x in range(5):
        coupon.use(order)

    assert coupon.usages.count() == 55

    assert not Coupon.is_usable(coupon.code, order.customer)
    assert coupon.usages.count() == 55  # no change, limit met
예제 #27
0
def test_filter_parameter_contact_groups():
    customer_price = 10.3
    anonymous_price = 14.6

    def get_price_info_mock(context, product, quantity=1):
        if context.customer.get_default_group() == AnonymousContact().get_default_group():
            price = context.shop.create_price(anonymous_price)
        else:
            price = context.shop.create_price(customer_price)
        return PriceInfo(quantity * price, quantity * price, quantity)

    with patch.object(DummyPricingModule, 'get_price_info', side_effect=get_price_info_mock):
        (engine, context) = _get_template_engine_and_context(product_sku="123")
        # test with anonymous
        context['request'].customer = AnonymousContact()
        context['request'].person = context['request'].customer
        result = engine.from_string("{{ prod|price(quantity=2) }}")
        assert result.render(context) == "$%0.2f" % (anonymous_price * 2)

        # Get fresh content. I guess the prices shouldn't change between request.
        (engine, context) = _get_template_engine_and_context(product_sku="1234")
        # test with customer
        context['request'].customer = create_random_person()
        context['request'].person = context['request'].customer
        result = engine.from_string("{{ prod|price(quantity=2) }}")
        assert result.render(context) == "$%0.2f" % (customer_price * 2)
예제 #28
0
def test_get_by_email(admin_user):
    get_default_shop()
    for i in range(0, 10):
        create_random_person()

    contact = create_random_person()
    client = _get_client(admin_user)

    response = client.get("/api/shuup/contact/", data={"email": contact.email})
    assert response.status_code == status.HTTP_200_OK
    contact_data = json.loads(response.content.decode("utf-8"))

    assert Contact.objects.filter(email=contact.email).count() == len(contact_data)
    assert contact_data[0].get("id") == contact.id
    assert contact_data[0].get("email") == contact.email
    assert contact_data[0].get("name") == contact.name
예제 #29
0
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
예제 #30
0
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"
예제 #31
0
def test_admin_cash_order(rf, admin_user, price, target, mode):
    activate("en")
    get_initial_order_status()  # Needed for the API
    shop = get_default_shop()
    contact = create_random_person(locale="en_US", minimum_name_comp_len=5)

    processor = CustomPaymentProcessor.objects.create(rounding_mode=mode)
    cash_method = PaymentMethod.objects.create(
        shop=shop,
        payment_processor=processor,
        choice_identifier="cash",
        tax_class=get_default_tax_class(),
        name="Cash")

    state = get_frontend_order_state(contact, cash_method, price)
    order = get_order_from_state(state, admin_user)
    assert order.payment_method == cash_method
    assert order.lines.count(
    ) == 5  # 2 submitted, two for the shipping and payment method, and a rounding line
    assert order.creator == admin_user
    assert order.customer == contact
    assert order.taxful_total_price == shop.create_price(target)
예제 #32
0
def test_context_contact_group_condition():
    rf = RequestFactory()
    original_price_value, discount_value = 123, 15
    request = get_request_for_contact_tests(rf)
    customer = create_random_person()
    default_group = get_default_customer_group()
    customer.groups.add(default_group)
    request.customer = customer

    condition = ContactGroupCondition.objects.create()
    condition.contact_groups.add(default_group)
    product = create_random_product_and_campaign(request.shop, [condition],
                                                 original_price_value,
                                                 discount_value)

    discounted_value = original_price_value - discount_value
    assert_product_price_value_with_customer(request, customer, product,
                                             discounted_value)

    request.customer.groups.clear()
    assert_product_price_value_with_customer(request, customer, product,
                                             original_price_value)
예제 #33
0
def initialize_test(rf, include_tax=False):
    activate("en")
    shop = get_shop(prices_include_tax=include_tax)
    shop.domain = "campaign"
    shop.save()

    # Valid baskets needs some payment methods to be available
    get_payment_method(shop)
    # Since some of the baskets are created for the default shop:
    get_payment_method(None)

    group = get_default_customer_group()
    customer = create_random_person()
    customer.groups.add(group)
    customer.save()

    request = rf.get("/")
    request.shop = shop
    request.META["HTTP_HOST"] = "campaign.shuup.com"
    apply_request_middleware(request)
    request.customer = customer
    return request, shop, group
예제 #34
0
def test_order_creator_valid(rf, admin_user):
    get_initial_order_status()  # Needed for the API
    contact = create_random_person(locale="en_US", minimum_name_comp_len=5)

    order = get_order_from_state(get_frontend_order_state(contact), admin_user)
    assert order.lines.count(
    ) == 5  # 3 submitted, two for the shipping and payment method
    assert order.creator == admin_user
    assert order.customer == contact

    supplier = get_default_supplier()

    for line in order.lines.all():
        if line.type == OrderLineType.PRODUCT:
            # Check that product line have right taxes
            assert [line_tax.tax.code
                    for line_tax in line.taxes.all()] == ["test_code"]
            assert line.taxful_price.amount > line.taxless_price.amount

        if line.type not in {OrderLineType.PAYMENT, OrderLineType.SHIPPING}:
            # Check that all of the lines that a supplier set, kept it.
            assert line.supplier == supplier
예제 #35
0
def test_gdpr_admin_download_data(client, admin_user):
    """
    Test that admin user can download customer data
    """
    activate("en")
    shop = factories.get_default_shop()
    customer = factories.create_random_person("en")
    product = factories.create_product("p1", shop,
                                       factories.get_default_supplier())
    [factories.create_random_order(customer, [product]) for order in range(3)]

    client = SmartClient()
    admin_user.set_password("admin")
    admin_user.save()
    client.login(username=admin_user.username, password="******")
    admin_download_url = reverse("shuup_admin:gdpr.download_data",
                                 kwargs=dict(pk=customer.pk))
    response = client.post(admin_download_url)
    assert response.status_code == 200
    assert response._headers["content-disposition"][0] == "Content-Disposition"
    assert response._headers["content-disposition"][1].startswith(
        "attachment; filename=user_data_")
def test_product_visibility_change_basic(hide_unorderable_product):
    """
    Make sure that the signal for hiding products when they become
    unorderable is called on shop product save.
    """
    if hide_unorderable_product:
        # Connect signal to hide products when they become unorderable
        stocks_updated.connect(receiver=shop_product_orderability_check,
                               dispatch_uid="shop_product_orderability_check")

    shop = get_default_shop()
    contact = create_random_person()
    supplier = get_default_supplier()
    product = create_product("test",
                             shop=shop,
                             supplier=supplier,
                             default_price=10)
    shop_product = product.get_shop_instance(shop=shop)
    assert shop_product.is_visible(contact)
    assert shop_product.is_purchasable(supplier, contact, 1)
    assert shop_product.is_orderable(supplier, contact, 1)

    shop_product.purchasable = False
    shop_product.save()
    shop_product.refresh_from_db()

    if hide_unorderable_product:
        assert not shop_product.is_visible(contact)
        assert not shop_product.is_purchasable(supplier, contact, 1)
        assert not shop_product.is_orderable(supplier, contact, 1)
        # Disconnect signal just in case...
        stocks_updated.disconnect(
            receiver=shop_product_orderability_check,
            dispatch_uid="shop_product_orderability_check")
    else:
        assert shop_product.is_visible(
            contact)  # Still visible in front but not purchasable or orderable
        assert not shop_product.is_purchasable(supplier, contact, 1)
        assert not shop_product.is_orderable(supplier, contact, 1)
예제 #37
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")
    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 . . .
예제 #38
0
def create_random_review_for_product(shop,
                                     product,
                                     reviewer=None,
                                     order=None,
                                     approved=True,
                                     rating=None,
                                     would_recommend=None,
                                     generate_comment=True):
    if reviewer is None:
        reviewer = factories.create_random_person("en")

    if order is None:
        order = factories.create_order_with_product(
            product=product,
            supplier=factories.get_default_supplier(),
            quantity=1,
            taxless_base_unit_price=10,
            shop=shop)

    if rating is None:
        rating = random.randint(1, 5)

    if would_recommend is None:
        would_recommend = random.choice([True, False])

    comment = None
    if generate_comment:
        comment = Faker().text(100)

    return ProductReview.objects.create(
        shop=shop,
        product=product,
        reviewer=reviewer,
        order=order,
        rating=rating,
        comment=comment,
        would_recommend=would_recommend,
        status=(ReviewStatus.APPROVED if approved else ReviewStatus.PENDING))
예제 #39
0
def test_mass_edit_orders4(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": OrderDeliveryPdfAction().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
    assert response["content-type"] == "application/json"

    order.create_shipment_of_all_products(supplier)
    order.save()
    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=shipment_%s_delivery.pdf' % order.pk
    else:
        assert response["content-type"] == "application/json"
예제 #40
0
def test_products_not_available_shop(admin_user):
    shop1 = get_default_shop()
    person1 = create_random_person()
    person1.user = admin_user
    person1.save()

    supplier1 = create_simple_supplier("supplier1")
    product1 = create_product("product1", shop=shop1, supplier=supplier1)
    product3 = create_product("product3", shop=shop1, supplier=supplier1)
    # add images for products 1 and 3
    add_product_image(product1)
    add_product_image(product3)

    # product 3 not visible
    shop1_product3 = ShopProduct.objects.get(shop=shop1, product=product3)
    shop1_product3.visibility = ShopProductVisibility.NOT_VISIBLE
    shop1_product3.save()

    request = get_request("/api/shuup/front/shop_products/", admin_user, person1)
    response = FrontShopProductViewSet.as_view({"get": "list"})(request)
    response.render()
    products_data = json.loads(response.content.decode("utf-8"))
    assert len(products_data) == 1

    # now product3 becomes visible
    shop1_product3.visibility = ShopProductVisibility.ALWAYS_VISIBLE
    shop1_product3.save()
    request = get_request("/api/shuup/front/shop_products/", admin_user, person1)
    response = FrontShopProductViewSet.as_view({"get": "list"})(request)
    response.render()
    products_data = json.loads(response.content.decode("utf-8"))
    assert len(products_data) == 2
    assert products_data[0]["is_orderable"] is True
    assert products_data[1]["is_orderable"] is True

    # check for images
    assert products_data[0]["image"] == request.build_absolute_uri(product1.primary_image.url)
    assert products_data[1]["image"] == request.build_absolute_uri(product3.primary_image.url)
예제 #41
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)
예제 #42
0
def test_products_all_shops(admin_user):
    shop1 = get_default_shop()
    shop1.logo = get_random_filer_image()
    shop1.save()

    person1 = create_random_person()
    person1.user = admin_user
    person1.save()

    shop2 = Shop.objects.create(status=ShopStatus.ENABLED)
    shop2.favicon = get_random_filer_image()
    shop2.save()
    supplier1 = create_simple_supplier("supplier1")
    supplier2 = create_simple_supplier("supplier2")

    # create 2 products for shop2
    product1 = create_product("product1", shop=shop1, supplier=supplier1)
    product2 = create_product("product2", shop=shop2, supplier=supplier2)
    product3 = create_product("product3", shop=shop2, supplier=supplier1)

    # list all orderable products - 2 just created are for shop2
    request = get_request("/api/shuup/front/shop_products/", admin_user, person1)
    response = FrontShopProductViewSet.as_view({"get": "list"})(request)
    response.render()
    products = json.loads(response.content.decode("utf-8"))
    assert len(products) == 3

    assert products[0]["product_id"] == product1.id
    assert products[0]["shop"]["id"] == shop1.id
    assert products[0]["shop"]["logo"] == request.build_absolute_uri(shop1.logo.url)

    assert products[1]["product_id"] == product2.id
    assert products[1]["shop"]["id"] == shop2.id
    assert products[1]["shop"]["favicon"] == request.build_absolute_uri(shop2.favicon.url)

    assert products[2]["product_id"] == product3.id
    assert products[2]["shop"]["id"] == shop2.id
    assert products[2]["shop"]["favicon"] == request.build_absolute_uri(shop2.favicon.url)
예제 #43
0
def test_set_not_active_customer(rf):
    """
    Set a not active customer to the basket
    """
    with override_settings(**CORE_BASKET_SETTINGS):
        user = factories.create_random_user()
        request = apply_request_middleware(rf.get("/"), user=user)
        basket = get_basket(request, "basket")
        basket.customer = get_person_contact(user)

        person = factories.create_random_person()
        person.is_active = False
        person.save()

        company = factories.create_random_company()
        company.is_active = False
        company.save()

        for customer in [person, company]:
            with pytest.raises(ValidationError) as exc:
                basket_commands.handle_set_customer(request, basket, customer)
            assert exc.value.code == "invalid_customer"
            assert basket.customer == get_person_contact(user)
예제 #44
0
def test_order_edit_with_coupon(rf):
    initial_status = get_initial_order_status()
    request, shop, group = initialize_test(rf, include_tax=False)
    order = _get_order_with_coupon(request, initial_status)

    modifier = UserFactory()
    contact = create_random_person(locale="en_US", minimum_name_comp_len=5)
    assert order.customer != contact
    state = _get_frontend_order_state(shop, contact)
    assert order.shop.id == state["shop"]["selected"]["id"]

    request = get_frontend_request_for_command(state, "finalize", modifier)
    response = OrderEditView.as_view()(request, pk=order.pk)
    assert_contains(response, "orderIdentifier")
    data = json.loads(response.content.decode("utf8"))
    edited_order = Order.objects.get(pk=order.pk)

    assert edited_order.identifier == data[
        "orderIdentifier"] == order.identifier
    assert edited_order.pk == order.pk
    assert edited_order.lines.count() == 4
    assert OrderLineType.DISCOUNT in [l.type for l in edited_order.lines.all()]
    assert edited_order.coupon_usages.count() == 1
예제 #45
0
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"
예제 #46
0
def test_contact_module_search_multishop(rf):
    with override_settings(SHUUP_MANAGE_CONTACTS_PER_SHOP=True, SHUUP_ENABLE_MULTIPLE_SHOPS=True):
        staff_user = create_random_user(is_staff=True)

        shop1 = get_shop(identifier="shop-1", enabled=True)
        shop2 = get_shop(identifier="shop-2", enabled=True)

        shop1.staff_members.add(staff_user)
        shop2.staff_members.add(staff_user)

        cm = ContactModule()
        contact = create_random_person(locale="en_US", minimum_name_comp_len=5)
        contact.add_to_shop(shop2)

        request = apply_request_middleware(rf.get("/"), user=staff_user, shop=shop2)

        # find the shop
        assert not empty_iterable(cm.get_search_results(request, query=contact.email))
        assert not empty_iterable(cm.get_search_results(request, query=contact.first_name))

        # no shop found
        request = apply_request_middleware(rf.get("/"), user=staff_user, shop=shop1)
        assert empty_iterable(cm.get_search_results(request, query=contact.email))
예제 #47
0
def test_min_amount_is_not_included():
    shop = get_default_shop()
    supplier = get_default_supplier()
    person = create_random_person()
    initial_group_count = person.groups.count()
    sales_ranges = [("silver", 0, 50), ("gold", 50, 100), ("diamond", 100, 1000), ("reverse_diamond", 1000, 100)]
    for identifier, min, max in sales_ranges:
        create_sales_range(identifier, shop, min, max)

    payment = create_fully_paid_order(shop, person, supplier, "sku1", 50)
    assert get_total_sales(shop, person) == 50
    update_customers_groups(Payment, payment)
    assert person.groups.count() == (initial_group_count + 1)
    assert bool([group for group in person.groups.all() if group.identifier == "gold"])
    assert not bool([group for group in person.groups.all() if group.identifier in ["silver", "diamond"]])

    payment = create_fully_paid_order(shop, person, supplier, "sku2", 50)
    assert get_total_sales(shop, person) == 100
    update_customers_groups(Payment, payment)
    assert person.groups.count() == (initial_group_count + 1)
    assert bool([group for group in person.groups.all() if group.identifier == "diamond"])
    assert not bool([group for group in person.groups.all() if group.identifier == "reverse_diamond"])
    assert not bool([group for group in person.groups.all() if group.identifier in ["silver", "gold"]])
예제 #48
0
def test_get_products(admin_user):
    shop = get_default_shop()
    supplier = get_default_supplier()

    person1 = create_random_person()
    person1.user = admin_user
    person1.save()

    create_product("product1", shop=shop, supplier=supplier)
    create_product("product2", shop=shop, supplier=supplier)

    # Generate complex variations
    product_parent = create_product("product3", shop=shop, supplier=supplier)
    populate_variations_for_parent(product_parent, shop, supplier)
    assert product_parent.mode == ProductMode.VARIABLE_VARIATION_PARENT

    # Generate simple variations
    simple_parent = create_product("product4", shop=shop, supplier=supplier)
    simple_child = create_product("product5", shop=shop, supplier=supplier)
    simple_child.link_to_parent(simple_parent)
    assert simple_child.is_variation_child()
    assert simple_parent.mode == ProductMode.SIMPLE_VARIATION_PARENT

    request = get_request("/api/shuup/front/shop_products/", admin_user, person1)
    response = FrontShopProductViewSet.as_view({"get": "list"})(request)
    response.render()
    assert response.status_code == status.HTTP_200_OK
    products_data = json.loads(response.content.decode("utf-8"))
    assert len(products_data) == 4

    complex_parent_data = [data for data in products_data if data["product_id"] == product_parent.id][0]
    assert len(complex_parent_data["variations"]) == 12

    simple_parent_data = [data for data in products_data if data["product_id"] == simple_parent.id][0]
    assert len(simple_parent_data["variations"]) == 1
    assert simple_parent_data["variations"][0]["sku_part"] == simple_child.sku
    assert simple_parent_data["variations"][0]["product"]["product_id"] == simple_child.id
예제 #49
0
def test_contact_company_edit_multishop(rf):
    with override_settings(SHUUP_MANAGE_CONTACTS_PER_SHOP=True, SHUUP_ENABLE_MULTIPLE_SHOPS=True):
        staff_user = create_random_user(is_staff=True)

        shop1 = get_shop(identifier="shop-1", enabled=True)
        shop2 = get_shop(identifier="shop-2", enabled=True)

        shop1.staff_members.add(staff_user)
        shop2.staff_members.add(staff_user)

        # only available in shop2
        contact = create_random_person(locale="en_US", minimum_name_comp_len=5)
        contact.shops.add(shop2)

        # only available in shop1
        company = create_random_company()
        company.shops.add(shop1)

        view = ContactEditView.as_view()

        # permission denied for contact and shop1
        request = apply_request_middleware(rf.get("/"), user=staff_user, shop=shop1)
        with pytest.raises(PermissionDenied):
            response = view(request, pk=contact.id)
        # permission granted for contact and shop2
        request = apply_request_middleware(rf.get("/"), user=staff_user, shop=shop2)
        response = view(request, pk=contact.id)
        assert response.status_code == 200

        # permission denied for company and shop2
        request = apply_request_middleware(rf.get("/"), user=staff_user, shop=shop2)
        with pytest.raises(PermissionDenied):
            response = view(request, pk=company.id)
        # permission granted for company and shop1
        request = apply_request_middleware(rf.get("/"), user=staff_user, shop=shop1)
        response = view(request, pk=company.id)
        assert response.status_code == 200
예제 #50
0
def test_user_detail_contact_seed(rf, admin_user):
    get_default_shop()
    contact = create_random_person()

    # Using random data for name and email would need escaping when
    # checking if it is rendered, therefore use something very basic instead
    contact.name = "Matti Perustyyppi"
    contact.email = "*****@*****.**"
    contact.save()

    view_func = UserDetailView.as_view()
    # Check that fields populate . . .
    request = apply_request_middleware(rf.get("/", {"contact_id": contact.pk}),
                                       user=admin_user)
    response = view_func(request)
    response.render()
    content = force_text(response.content)
    assert force_text(contact.first_name) in content
    assert force_text(contact.last_name) in content
    assert force_text(contact.email) in content
    # POST the password too to create the user . . .
    post = extract_form_fields(BeautifulSoup(content))
    post["password"] = "******"
    request.method = "POST"
    request.POST = post
    response = view_func(request)
    assert response.status_code < 500
    # Check this new user is visible in the details now
    user = Contact.objects.get(pk=contact.pk).user
    request = apply_request_middleware(rf.get("/", {"contact_id": contact.pk}),
                                       user=admin_user)
    response = view_func(request, pk=user.pk)
    response.render()
    content = force_text(response.content)
    assert force_text(contact.first_name) in content
    assert force_text(contact.last_name) in content
    assert force_text(contact.email) in content
예제 #51
0
def test_reviews_view_multiple_supplires(rf):
    shop = factories.get_default_shop()
    customer = factories.create_random_person("en")
    user = factories.create_random_user("en")
    user.set_password("user")
    user.save()
    customer.user = user
    customer.save()

    supplier1_name = "Supplier 1 name"
    supplier1 = Supplier.objects.create(identifier="1", name=supplier1_name)
    supplier1.shops.set([shop])
    supplier2_name = "Supplier 2 name"
    supplier2 = Supplier.objects.create(identifier="2", name=supplier2_name)
    supplier2.shops.set([shop])
    product = factories.create_product("test1",
                                       shop=shop,
                                       supplier=supplier1,
                                       default_price=10)
    shop_product = product.get_shop_instance(shop=shop)
    assert shop_product.suppliers.filter(id=supplier1.id).exists()
    shop_product.suppliers.add(supplier2)
    assert shop_product.suppliers.filter(id=supplier2.id).exists()

    create_multi_supplier_order_to_review(shop_product, customer)

    client = SmartClient()
    client.login(username=user.username, password="******")

    response, soup = client.response_and_soup(reverse("shuup:vendor_reviews"))
    assert "Vendors to Review" in soup.text
    assert len(
        soup.findAll("div",
                     attrs={"class": "vendors-to-review"})[0].findChildren(
                         "div", attrs={"class": "list-group-item"})) == 2
    assert "%s" % supplier2_name in soup.text
    assert "%s" % supplier1_name in soup.text
예제 #52
0
def test_contact_edit_multishop(rf):
    with override_settings(SHUUP_MANAGE_CONTACTS_PER_SHOP=True,
                           SHUUP_ENABLE_MULTIPLE_SHOPS=True):
        staff_user = create_random_user(is_staff=True)

        shop1 = get_shop(identifier="shop-1", enabled=True)
        shop2 = get_shop(identifier="shop-2", enabled=True)

        shop1.staff_members.add(staff_user)
        shop2.staff_members.add(staff_user)

        contact = create_random_person(locale="en_US",
                                       minimum_name_comp_len=5,
                                       shop=shop2)
        # only available in shop2
        assert contact.registered_in(shop2)
        assert contact.in_shop(shop2)

        request = apply_request_middleware(rf.get("/"),
                                           user=staff_user,
                                           shop=shop1)
        view = ContactDetailView.as_view()

        # contact not found for this shop
        with pytest.raises(Http404):
            response = view(request, pk=contact.id)

        request = apply_request_middleware(rf.get("/"),
                                           user=staff_user,
                                           shop=shop2)
        response = view(request, pk=contact.id)
        assert response.status_code == 200

        assert contact.registered_in(shop2)
        assert contact.in_shop(shop2)
        assert not contact.registered_in(shop1)
        assert not contact.in_shop(shop1)
def test_simple_supplier_out_of_stock(rf, anonymous):
    supplier = get_simple_supplier()
    shop = get_default_shop()
    product = create_product("simple-test-product", shop, supplier, stock_behavior=StockBehavior.STOCKED)

    if anonymous:
        customer = AnonymousContact()
    else:
        customer = create_random_person()

    ss = supplier.get_stock_status(product.pk)
    assert ss.product == product
    assert ss.logical_count == 0
    num = random.randint(100, 500)
    supplier.adjust_stock(product.pk, +num)
    assert supplier.get_stock_status(product.pk).logical_count == num

    shop_product = product.get_shop_instance(shop)
    assert shop_product.is_orderable(supplier, customer, 1)

    # Create order
    order = create_order_with_product(product, supplier, num, 3, shop=shop)
    order.get_product_ids_and_quantities()
    pss = supplier.get_stock_status(product.pk)
    assert pss.logical_count == 0
    assert pss.physical_count == num

    assert not shop_product.is_orderable(supplier, customer, 1)

    # Create shipment
    shipment = order.create_shipment_of_all_products(supplier)
    assert isinstance(shipment, Shipment)
    pss = supplier.get_stock_status(product.pk)
    assert pss.logical_count == 0
    assert pss.physical_count == 0

    assert not shop_product.is_orderable(supplier, customer, 1)
예제 #54
0
def test_filter_parameter_contact_groups():
    (engine, context) = _get_template_engine_and_context()
    customer_price = 10.3
    anonymous_price = 14.6

    def get_price_info_mock(context, product, quantity=1):
        if context.customer.get_default_group() == AnonymousContact().get_default_group():
            price = context.shop.create_price(anonymous_price)
        else:
            price = context.shop.create_price(customer_price)
        return PriceInfo(quantity * price, quantity * price, quantity)

    with patch.object(DummyPricingModule, 'get_price_info', side_effect=get_price_info_mock):
        # test with anonymous
        context['request'].customer = AnonymousContact()
        context['request'].person = context['request'].customer
        result = engine.from_string("{{ prod|price(quantity=2) }}")
        assert result.render(context) == "$%0.2f" % (anonymous_price * 2)

        # test with customer
        context['request'].customer = create_random_person()
        context['request'].person = context['request'].customer
        result = engine.from_string("{{ prod|price(quantity=2) }}")
        assert result.render(context) == "$%0.2f" % (customer_price * 2)
예제 #55
0
def test_coupon_user_limit():
    coupon = Coupon.objects.create(code="TEST", active=True)
    get_default_campaign(coupon)
    contact = create_random_person()
    shop = get_default_shop()
    product = create_product("test", shop=shop, supplier=get_default_supplier(shop), default_price="12")
    order = create_random_order(customer=contact)
    for x in range(50):
       coupon.use(order)

    assert coupon.usages.count() == 50

    # set limit to coupon_usage
    coupon.increase_customer_usage_limit_by(5)
    coupon.save()

    assert coupon.usage_limit_customer == 55
    assert coupon.can_use_code(contact)
    for x in range(5):
        coupon.use(order)
    assert coupon.usages.count() == 55

    assert not Coupon.is_usable(coupon.code, order.customer)
    assert coupon.usages.count() == 55  # no change, limit met
예제 #56
0
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
예제 #57
0
def test_order_creator_view_2(browser, admin_user, live_server, settings):
    shop = get_default_shop()
    pm = get_default_payment_method()
    sm = get_default_shipping_method()
    get_initial_order_status()
    supplier = get_default_supplier()
    person = create_random_person()
    create_product("test-sku0", shop=shop, default_price=10, supplier=supplier)
    create_product("test-sku1", shop=shop, default_price=10, supplier=supplier)
    object_created.connect(_add_custom_order_created_message,
                           sender=Order,
                           dispatch_uid="object_created_signal_test")

    initialize_admin_browser_test(browser, live_server, settings)
    browser.driver.set_window_size(1920, 1080)
    _visit_order_creator_view(browser, live_server)
    _test_customer_using_search(browser, person)
    _test_add_lines(browser)
    _test_methods(browser, sm, pm)
    _test_confirm(browser)
    assert Order.objects.first().log_entries.filter(
        identifier=OBJECT_CREATED_LOG_IDENTIFIER).count() == 1
    object_created.disconnect(sender=Order,
                              dispatch_uid="object_created_signal_test")
예제 #58
0
    def setUp(self):
        OrderStatusManager().ensure_default_statuses()
        product = factories.create_product("p", factories.get_default_shop(), factories.get_default_supplier())

        customer = factories.create_random_person()
        # Initial Order
        intial_status = OrderStatus.objects.filter(identifier=DefaultOrderStatus.INITIAL.value).first()
        self.order_initial = factories.create_random_order(customer=customer, products=[product])
        self.order_initial.change_status(intial_status)

        # Processing Order
        process_status = OrderStatus.objects.filter(identifier=DefaultOrderStatus.PROCESSING.value).first()
        self.order_processing = factories.create_random_order(customer=customer, products=[product])
        self.order_processing.change_status(process_status)

        # Complete Order
        complete_status = OrderStatus.objects.filter(identifier=DefaultOrderStatus.COMPLETE.value).first()
        self.order_complete = factories.create_random_order(customer=customer, products=[product])
        self.order_complete.change_status(complete_status)

        # Canceled Order
        canceled_status = OrderStatus.objects.filter(identifier=DefaultOrderStatus.CANCELED.value).first()
        self.order_canceled = factories.create_random_order(customer=customer, products=[product])
        self.order_canceled.change_status(canceled_status)
예제 #59
0
def test_gdpr_admin_anonymize(client, admin_user):
    """
    Test that admin user can anonymize contact
    """
    activate("en")
    factories.get_default_shop()
    person = factories.create_random_person("en")
    person.user = factories.create_random_user("en")
    person.save()

    client = SmartClient()
    admin_user.set_password("admin")
    admin_user.save()
    client.login(username=admin_user.username, password="******")
    admin_anonymize_url = reverse("shuup_admin:gdpr.anonymize",
                                  kwargs=dict(pk=person.pk))
    response = client.post(admin_anonymize_url)
    assert response.status_code == 302
    assert response.url.endswith(
        reverse("shuup_admin:contact.detail", kwargs=dict(pk=person.pk)))

    anonymized_person = PersonContact.objects.get(id=person.id)
    assert anonymized_person.name != person.name
    assert anonymized_person.user.username != person.user.username
예제 #60
0
def test_order_creator_view(browser, admin_user, live_server):
    shop = get_default_shop()
    pm = get_default_payment_method()
    sm = get_default_shipping_method()
    get_initial_order_status()
    supplier = get_default_supplier()
    person = create_random_person()
    product0 = create_product("test-sku0",
                              shop=shop,
                              default_price=10,
                              supplier=supplier)
    product1 = create_product("test-sku1",
                              shop=shop,
                              default_price=10,
                              supplier=supplier)

    initialize_admin_browser_test(browser, live_server)
    _visit_order_creator_view(browser, live_server)
    _test_language_change(browser)
    _test_customer_data(browser, person)
    _test_add_lines(browser)
    _test_quick_add_lines(browser)
    _test_methods(browser)
    _test_confirm(browser)