Пример #1
0
def test_create_services():
    carrier = CorreiosCarrier.objects.create(name="Correios")

    pac_service = carrier.create_service(
        'PAC',
        shop=get_default_shop(),
        enabled=True,
        tax_class=get_default_tax_class(),
        name="Correios PAC")
    assert pac_service.behavior_components.count() == 1

    sedex_service = carrier.create_service(
        'SEDEX',
        shop=get_default_shop(),
        enabled=True,
        tax_class=get_default_tax_class(),
        name="Correios SEDEX")
    assert sedex_service.behavior_components.count() == 1

    strange_service = carrier.create_service(
        'STRANGE',
        shop=get_default_shop(),
        enabled=True,
        tax_class=get_default_tax_class(),
        name="unknown")

    assert strange_service.behavior_components.count() == 0
Пример #2
0
def test_product_create(browser, admin_user, live_server, settings):
    activate("en")
    shop = get_default_shop()
    get_default_product_type()
    get_default_sales_unit()
    get_default_tax_class()
    configuration.set(None, "shuup_product_tour_complete", True)
    object_created.connect(_add_custom_product_created_message, sender=Product, dispatch_uid="object_created_signal_test")
    initialize_admin_browser_test(browser, live_server, settings)

    url = reverse("shuup_admin:shop_product.new")
    browser.visit("%s%s" % (live_server, url))
    sku = "testsku"
    name = "Some product name"
    price_value = 10
    short_description = "short but gold"

    browser.fill("base-sku", sku)
    browser.fill("base-name__en", name)
    browser.fill("base-short_description__en", short_description)
    browser.fill("shop%s-default_price_value" % shop.pk, price_value)

    configuration.set(None, "shuup_category_tour_complete", True)
    _add_primary_category(browser, shop)
    _add_additional_category(browser, shop)

    click_element(browser, "button[form='product_form']")
    wait_until_appeared(browser, "div[class='message success']")
    product = Product.objects.filter(sku=sku).first()
    assert product.log_entries.filter(identifier=OBJECT_CREATED_LOG_IDENTIFIER).count() == 1
    object_created.disconnect(sender=Product, dispatch_uid="object_created_signal_test")
    shop_product = product.get_shop_instance(shop)
    assert shop_product.categories.count() == 2
Пример #3
0
def test_refunds_report(rf):
    shop = get_default_shop()
    get_default_tax_class()
    creator = OrderCreator()

    source1 = seed_source()
    source2 = seed_source()
    source3 = seed_source()
    source4 = seed_source()

    order1 = creator.create_order(source1)
    order2 = creator.create_order(source2)
    order3 = creator.create_order(source3)
    order4 = creator.create_order(source4)

    # pay orders
    [o.create_payment(o.taxful_total_price) for o in Order.objects.all()]

    order1.create_full_refund()
    order2.create_refund(
        [{"line": order2.lines.first(), "amount": order2.taxful_total_price.amount * Decimal(0.5), "quantity": 1}]
    )
    order3.create_refund(
        [{"line": order3.lines.first(), "amount": order3.taxful_total_price.amount * Decimal(0.3), "quantity": 1}]
    )
    order4.create_refund(
        [{"line": order4.lines.first(), "amount": order4.taxful_total_price.amount * Decimal(0.1), "quantity": 1}]
    )

    total_refunded = (order1.get_total_refunded_amount() +
                      order2.get_total_refunded_amount() +
                      order3.get_total_refunded_amount() +
                      order4.get_total_refunded_amount())

    data = {
        "report": RefundedSalesReport.get_name(),
        "shop": shop.pk,
        "date_range": DateRangeChoices.ALL_TIME,
        "writer": "json",
        "force_download": 1,
    }
    report = RefundedSalesReport(**data)
    writer = get_writer_instance(data["writer"])
    response = writer.get_response(report=report)
    if hasattr(response, "render"):
        response.render()
    json_data = json.loads(response.content.decode("utf-8"))
    assert force_text(RefundedSalesReport.title) in json_data.get("heading")
    data = json_data.get("tables")[0].get("data")
    assert len(data) == 1
    data = data[0]

    expected_data = {
        "refunded_orders": "4",
        "total_refunded": str(total_refunded.value)
    }

    for k, v in expected_data.items():
        assert data[k] == v
Пример #4
0
def test_wizard_pane(rf, admin_user, settings):
    with override_settings(SHUUP_SETUP_WIZARD_PANE_SPEC=["shuup.admin.modules.service_providers.views.PaymentWizardPane"]):
        factories.get_default_shop()
        factories.get_default_tax_class()

        request = apply_request_middleware(rf.get("/"), user=admin_user)
        response = WizardView.as_view()(request)
        assert response.status_code == 200
Пример #5
0
def test_quick_add(browser, admin_user, live_server, settings):
    shop = get_default_shop()
    get_default_product_type()
    get_default_sales_unit()
    get_default_tax_class()
    initialize_admin_browser_test(browser, live_server, settings)

    url = reverse("shuup_admin:shop_product.new")
    browser.visit("%s%s" % (live_server, url))
    sku = "testsku"
    name = "Some product name"
    price_value = 10
    short_description = "short but gold"

    browser.fill("base-sku", sku)
    browser.fill("base-name__en", name)
    browser.fill("base-short_description__en", short_description)
    browser.fill("shop%s-default_price_value" % shop.pk, price_value)

    wait_until_appeared(browser, "#id_shop%d-primary_category ~ .quick-add-btn a.btn" % shop.id)
    click_element(browser, "#id_shop%d-primary_category ~ .quick-add-btn a.btn" % shop.id)
    wait_until_appeared(browser, "#create-object-iframe")

    with browser.get_iframe('create-object-iframe') as iframe:
        assert Category.objects.count() == 0
        wait_until_appeared(iframe, "input[name='base-name__en']")
        iframe.fill("base-name__en", "Test Category")
        time.sleep(3)  # Let's just wait here to the iFrame to open fully (for Chrome and headless)
        wait_until_appeared(iframe, "button[form='category_form']")
        click_element(browser, "button[form='category_form']")
        wait_until_condition(browser, condition=lambda x: Category.objects.count() == 1, timeout=20)

    assert Category.objects.first().name == "Test Category"

    # click to edit the button
    click_element(browser, "#id_shop%d-primary_category ~ .edit-object-btn a.btn" % shop.id)

    with browser.get_iframe('create-object-iframe') as iframe:
        wait_until_appeared(iframe, "input[name='base-name__en']")
        new_cat_name = "Changed Name"
        iframe.fill("base-name__en", new_cat_name)
        time.sleep(3)  # Let's just wait here to the iFrame to open fully (for Chrome and headless)
        wait_until_appeared(iframe, "button[form='category_form']")
        click_element(iframe, "button[form='category_form']")

    wait_until_condition(browser, condition=lambda x: Category.objects.first().name == new_cat_name, timeout=20)

    click_element(browser, "button[form='product_form']")
    wait_until_appeared(browser, "div[class='message success']")
Пример #6
0
def test_complex_import():
    filename = "complex_import.xlsx"
    activate("en")
    shop = get_default_shop()
    get_default_tax_class()
    get_default_product_type()
    get_default_supplier()
    get_default_sales_unit()

    path = os.path.join(os.path.dirname(__file__), "data", "product", filename)
    transformed_data = transform_file(filename.split(".")[1], path)
    importer = ProductImporter(transformed_data, shop, "en")
    importer.process_data()

    assert len(importer.unmatched_fields) == 0
    importer.do_import(ImportMode.CREATE_UPDATE)
    products = importer.new_objects
    assert len(products) == 6
    assert ShopProduct.objects.count() == 6
    assert Category.objects.count() == 11
    assert Manufacturer.objects.count() == 4

    for idx, product in enumerate(Product.objects.all().order_by("sku")):
        shop_product = product.get_shop_instance(shop)

        data = PRODUCT_DATA[idx]
        assert product.sku == data["sku"]
        assert product.name == data["name"]

        assert shop_product.default_price_value == Decimal(data["price"])
        assert product.description == data["description"]

        if data.get("categories"):
            all_cats = set(data["categories"])
            all_cats.add(data["category"])

            for cat in shop_product.categories.all():
                assert cat.name in all_cats
            assert shop_product.categories.count() == len(all_cats)  # also add primary category

        if data.get("category"):
            assert shop_product.primary_category.name == data["category"]

        assert force_text(shop_product.visibility.label) == data["visibility"].lower()
        assert product.tax_class.name == data["tax_class"]

        if data.get("manufacturer"):
            assert product.manufacturer.name == data["manufacturer"]
Пример #7
0
def _get_template_engine_and_context():
    engine = django.template.engines['jinja2']
    assert isinstance(engine, django_jinja.backend.Jinja2)

    shop = get_default_shop()
    shop.currency = 'USD'
    shop.prices_include_tax = False
    shop.save()

    request = RequestFactory().get('/')
    request.shop = shop
    request.customer = AnonymousContact()
    request.person = request.customer
    PriceDisplayOptions(include_taxes=False).set_for_request(request)
    tax = get_default_tax()
    create_default_tax_rule(tax)
    tax_class = get_default_tax_class()
    order, order_line = _get_order_and_order_line(request)

    product = create_product(sku='6.0745', shop=shop, tax_class=tax_class)

    context = {
        'request': request,
        'prod': product,
        # TODO: Test also with variant products
        'sline': _get_source_line(request),
        'bline': _get_basket_line(request),
        'oline': order_line,
        'order': order
    }

    return (engine, context)
def test_custom_payment_processor_cash_service(choice_identifier, expected_payment_status):
    shop = get_default_shop()
    product = get_default_product()
    supplier = get_default_supplier()
    processor = CustomPaymentProcessor.objects.create()
    payment_method = PaymentMethod.objects.create(
        shop=shop,
        payment_processor=processor,
        choice_identifier=choice_identifier,
        tax_class=get_default_tax_class())

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

    assert order.payment_status == PaymentStatus.NOT_PAID
    processor.process_payment_return_request(choice_identifier, order, None)
    assert order.payment_status == expected_payment_status
    processor.process_payment_return_request(choice_identifier, order, None)
    assert order.payment_status == expected_payment_status
Пример #9
0
def test_stripe_checkout_phase_with_saved_card(rf, stripe_payment_processor):
    shop = factories.get_default_shop()
    user = factories.create_random_user()
    contact = get_person_contact(user)
    request = apply_request_middleware(rf.post("/"), shop=shop, customer=contact)

    def return_stripe_mock_data(*args, **kwargs):
        return StripedData(**CUSTOMER_MOCK_DATA)

    with mock.patch("stripe.Customer.retrieve", new=return_stripe_mock_data):
        service = stripe_payment_processor.create_service(
            "stripe", shop=request.shop, tax_class=factories.get_default_tax_class(), enabled=True)

        StripeCustomer.objects.create(contact=contact, customer_token="123")
        checkout_phase = StripeCheckoutPhase(request=request, service=service)
        assert not checkout_phase.is_valid()
        context = checkout_phase.get_context_data()
        assert context["stripe"]
        request.method = "POST"
        request.POST = {
            "stripeCustomer": "1234"
        }
        checkout_phase.get_success_url = lambda: reverse("shuup_admin:home")
        checkout_phase.post(request)
        assert checkout_phase.is_valid()  # We should be valid now
        assert request.session  # And things should've been saved into the session
        checkout_phase.process()  # And this should do things to the basket
        assert request.basket.payment_data["stripe"]["customer"]
Пример #10
0
def test_process_payment_return_request(rf):
    """
    Order payment with default payment method with ``CustomPaymentProcessor``
    should be deferred.

    Payment can't be processed if method doesn't have provider or provider
    is not enabled or payment method is not enabled.
    """
    pm = PaymentMethod.objects.create(
        shop=get_default_shop(), name="Test method", enabled=False, tax_class=get_default_tax_class())
    order = create_empty_order()
    order.payment_method = pm
    order.save()
    assert order.payment_status == PaymentStatus.NOT_PAID
    with pytest.raises(ValueError):  # Can't process payment with unusable method
        order.payment_method.process_payment_return_request(order, rf.get("/"))
    assert order.payment_status == PaymentStatus.NOT_PAID
    pm.payment_processor = get_custom_payment_processor()
    pm.payment_processor.enabled = False
    pm.save()

    with pytest.raises(ValueError):  # Can't process payment with unusable method
        order.payment_method.process_payment_return_request(order, rf.get("/"))
    assert order.payment_status == PaymentStatus.NOT_PAID
    pm.payment_processor.enabled = True
    pm.save()

    with pytest.raises(ValueError):  # Can't process payment with unusable method
        order.payment_method.process_payment_return_request(order, rf.get("/"))
    assert order.payment_status == PaymentStatus.NOT_PAID
    pm.enabled = True
    pm.save()

    order.payment_method.process_payment_return_request(order, rf.get("/"))
    assert order.payment_status == PaymentStatus.DEFERRED
Пример #11
0
def test_stripe_checkout_phase(rf, stripe_payment_processor):
    request = rf.get("/")
    request.shop = get_default_shop()
    request.session = {}
    request.basket = get_basket(request)
    service = stripe_payment_processor.create_service(
        None, shop=request.shop, tax_class=get_default_tax_class(),
        enabled=True)
    checkout_phase = StripeCheckoutPhase(
        request=request, service=service)
    assert not checkout_phase.is_valid()  # We can't be valid just yet
    context = checkout_phase.get_context_data()
    assert context["stripe"]
    request.method = "POST"
    token = get_stripe_token(stripe_payment_processor)
    request.POST = {
        "stripeToken": token["id"],
        "stripeTokenType": token["type"],
        "stripeTokenEmail": token.get("email"),
    }
    checkout_phase.post(request)
    assert checkout_phase.is_valid()  # We should be valid now
    assert request.session  # And things should've been saved into the session
    checkout_phase.process()  # And this should do things to the basket
    assert request.basket.payment_data.get("stripe")
Пример #12
0
def test_method_creation(rf, admin_user, view, model, service_provider_attr, get_provider):
    """
    To make things little bit more simple let's use only english as
    an language.
    """
    with override_settings(LANGUAGES=[("en", "en")]):
        view = view.as_view()
        service_provider_field = "base-%s" % service_provider_attr
        data = {
            service_provider_field: get_provider().id,
            "base-choice_identifier": "manual",
            "base-name__en": "Custom method",
            "base-shop": get_default_shop().id,
            "base-tax_class": get_default_tax_class().id,
            "base-enabled": True,
        }
        # Default provider CustomCarrier/CustomPaymentProcessor should be set in form init
        methods_before = model.objects.count()
        url = "/?provider=%s" % get_provider().id
        request = apply_request_middleware(rf.post(url, data=data), user=admin_user)
        response = view(request, pk=None)
        if hasattr(response, "render"):
            response.render()
        assert response.status_code in [200, 302]
        assert model.objects.count() == (methods_before + 1)
Пример #13
0
def get_correios_carrier_2():
    carrier = CorreiosCarrier.objects.create(name="Correios C2")

    pac_service2 = carrier.create_service(
        'PAC',
        shop=get_default_shop(),
        enabled=True,
        tax_class=get_default_tax_class(),
        name="Correios - PAC #2")

    pac_service_bc2 = pac_service2.behavior_components.first()
    pac_service_bc2.cep_origem = '88220000'
    pac_service_bc2.max_weight = Decimal(40000.0)
    pac_service_bc2.max_width = Decimal(800.0)
    pac_service_bc2.max_length = Decimal(600.0)
    pac_service_bc2.max_height = Decimal(400.0)
    pac_service_bc2.min_width = Decimal(90.0)
    pac_service_bc2.min_length = Decimal(60.0)
    pac_service_bc2.min_height = Decimal(50.0)
    pac_service_bc2.max_edges_sum = Decimal(2000.0)
    pac_service_bc2.mao_propria = True
    pac_service_bc2.valor_declarado = True
    pac_service_bc2.aviso_recebimento = True
    pac_service_bc2.additional_delivery_time = 2
    pac_service_bc2.additional_price = Decimal(13.3)
    pac_service_bc2.save()

    return carrier
Пример #14
0
def test_stripe_checkout_phase_with_saved_card_exception(rf, stripe_payment_processor):
    shop = factories.get_default_shop()
    user = factories.create_random_user()
    contact = get_person_contact(user)
    request = apply_request_middleware(rf.post("/"), shop=shop, customer=contact)

    def raise_stripe_exc(*args, **kwargs):
        raise stripe.StripeError("DUMMY")

    with mock.patch("stripe.Customer.retrieve", new=raise_stripe_exc):
        service = stripe_payment_processor.create_service(
            "stripe", shop=request.shop, tax_class=factories.get_default_tax_class(), enabled=True)

        StripeCustomer.objects.create(contact=contact, customer_token="123")
        checkout_phase = StripeCheckoutPhase(request=request, service=service)
        assert not checkout_phase.is_valid()
        context = checkout_phase.get_context_data()
        assert context["stripe"]
        assert not context.get("stripe_customer_data")

        request.method = "POST"
        request.POST = {}
        checkout_phase.get_success_url = lambda: reverse("shuup_admin:home")
        checkout_phase.post(request)
        assert not checkout_phase.is_valid()
Пример #15
0
def test_order_package_children_taxes():
    """
    Test OrderCreator creates package parent links for child lines.
    """
    tax_class = get_default_tax_class()
    tax = Tax.objects.create(rate='0.25', name="Da Tax")
    TaxRule.objects.create(tax=tax).tax_classes.add(tax_class)

    source = get_order_source_with_a_package()
    assert source.get_lines()[0].tax_class == tax_class

    order = OrderCreator().create_order(source)

    lines_and_taxes = []
    for line in order.lines.all():
        lines_and_taxes.append(prettify_order_line(line))
        for line_tax in line.taxes.all():
            lines_and_taxes.append('  %s' % (line_tax,))
    assert lines_and_taxes == [
        '#0 10 x PackageParent',
        '  Da Tax: 20.000000000 EUR on 80.000000000 EUR',
        '#1   10 x PackageChild-0, child of #0',
        '#2   20 x PackageChild-1, child of #0',
        '#3   30 x PackageChild-2, child of #0',
        '#4   40 x PackageChild-3, child of #0',
    ]
Пример #16
0
def test_sample_import_all_match(filename):
    activate("en")
    shop = get_default_shop()
    tax_class = get_default_tax_class()
    product_type = get_default_product_type()

    path = os.path.join(os.path.dirname(__file__), "data", "product", filename)
    transformed_data = transform_file(filename.split(".")[1], path)
    importer = ProductImporter(transformed_data, shop, "en")
    importer.process_data()
    assert len(importer.unmatched_fields) == 0
    importer.do_import(ImportMode.CREATE_UPDATE)
    products = importer.new_objects
    assert len(products) == 2
    for product in products:
        shop_product = product.get_shop_instance(shop)
        assert shop_product.pk
        assert shop_product.pk == product.pk
        assert shop_product.default_price_value == 150
        assert shop_product.default_price == shop.create_price(150)
        assert product.type == product_type  # product type comes from importer defaults
        if product.pk == 1:
            assert product.tax_class.pk == 2  # new was created
            assert product.name == "Product English"
            assert product.description == "Description English"
        else:
            assert product.tax_class.pk == tax_class.pk  # old was found as should
            assert product.name == "Product 2 English"
            assert product.description == "Description English 2"
        assert shop_product.primary_category.pk == 1
        assert [c.pk for c in shop_product.categories.all()] == [1,2]
Пример #17
0
def test_method_creation_with_labels(rf, admin_user, view, model, service_provider_attr, get_provider):
    """
    To make things little bit more simple let's use only english as
    an language.
    """
    with override_settings(LANGUAGES=[("en", "en")]):
        for identifier, name in [("pickup", "Pickup"), ("delivery", "Delivery"), ("airmail", "Airmail")]:
            label = Label.objects.create(identifier=identifier, name=name)
            assert label.name == name
            assert "%s" % label == name

        view = view.as_view()
        service_provider_field = "base-%s" % service_provider_attr
        data = {
            service_provider_field: get_provider().id,
            "base-choice_identifier": "manual",
            "base-name__en": "Custom method",
            "base-shop": get_default_shop().id,
            "base-tax_class": get_default_tax_class().id,
            "base-enabled": True,
            "base-labels": Label.objects.values_list("pk", flat=True)
        }
        # Default provider CustomCarrier/CustomPaymentProcessor should be set in form init
        methods_before = model.objects.count()
        url = "/?provider=%s" % get_provider().id
        request = apply_request_middleware(rf.post(url, data=data), user=admin_user)
        response = view(request, pk=None)
        if hasattr(response, "render"):
            response.render()
        assert response.status_code in [200, 302]
        assert model.objects.count() == (methods_before + 1)
        assert model.objects.last().labels.count() == Label.objects.count()
Пример #18
0
def test_sample_ignore_column():
    activate("en")
    shop = get_default_shop()
    get_default_tax_class()
    get_default_product_type()
    get_default_sales_unit()

    path = os.path.join(os.path.dirname(__file__), "data", "product", "sample_import_ignore.csv")
    transformed_data = transform_file("csv", path)
    importer = ProductImporter(transformed_data, shop, "en")
    importer.process_data()

    assert len(importer.unmatched_fields) == 0
    importer.do_import(ImportMode.CREATE_UPDATE)
    products = importer.new_objects
    assert len(products) == 2
Пример #19
0
def test_sample_data_wizard_pane(rf, admin_user, settings):
    settings.SHUUP_SETUP_WIZARD_PANE_SPEC = [
        "shuup.testing.modules.sample_data.views.SampleObjectsWizardPane"
    ]

    shop = get_default_shop()
    get_default_tax_class()

    data = {
        'pane_id': 'sample',
        'sample-business_segment': 'default',
        'sample-categories': True,
        'sample-products': True,
        'sample-carousel': True
    }

    request = apply_request_middleware(rf.post("/", data=data), user=admin_user)
    response = WizardView.as_view()(request)
    assert response.status_code == 200

    assert Product.objects.count() == len(BUSINESS_SEGMENTS["default"]["products"])
    anon_contact = AnonymousContact()
    supplier = get_default_supplier()

    # check for the injected plugin using the carousel
    assert Carousel.objects.count() == 1
    carousel = Carousel.objects.first()
    assert Slide.objects.count() == len(BUSINESS_SEGMENTS["default"]["carousel"]["slides"])
    svc = SavedViewConfig.objects.first()
    assert svc.view_name == "IndexView"
    layout = svc.get_layout_data("front_content")
    assert layout['rows'][0]['cells'][0]['config']['carousel'] == carousel.pk
    assert layout['rows'][0]['cells'][0]['plugin'] == CarouselPlugin.identifier

    for product in Product.objects.all():
        # all products must be orderable and have images
        assert product.get_shop_instance(shop).is_orderable(supplier=supplier,
                                                            customer=anon_contact,
                                                            quantity=1)
        assert product.primary_image is not None

    assert Category.objects.count() == len(BUSINESS_SEGMENTS["default"]["categories"])

    request = apply_request_middleware(rf.get("/"), user=admin_user)
    response = WizardView.as_view()(request)
    assert response.status_code == 302
    assert response["Location"] == reverse("shuup_admin:dashboard")
Пример #20
0
def test_sample_import_no_match(stock_managed):
    filename = "sample_import_nomatch.xlsx"
    if "shuup.simple_supplier" not in settings.INSTALLED_APPS:
        pytest.skip("Need shuup.simple_supplier in INSTALLED_APPS")
    from shuup_tests.simple_supplier.utils import get_simple_supplier

    activate("en")
    shop = get_default_shop()
    tax_class = get_default_tax_class()
    product_type = get_default_product_type()
    supplier = get_simple_supplier(stock_managed)
    sales_unit = get_default_sales_unit()

    Manufacturer.objects.create(name="manufctr")
    path = os.path.join(os.path.dirname(__file__), "data", "product", filename)
    transformed_data = transform_file(filename.split(".")[1], path)

    importer = ProductImporter(transformed_data, shop, "en")
    importer.process_data()
    assert len(importer.unmatched_fields) == 1
    assert "gtiin" in importer.unmatched_fields
    importer.manually_match("gtiin", "shuup.core.models.Product:gtin")
    importer.do_remap()
    assert len(importer.unmatched_fields) == 0
    importer.do_import(ImportMode.CREATE_UPDATE)
    products = importer.new_objects
    assert len(products) == 2

    for product in products:
        assert product.gtin == "1280x720"
        shop_product = product.get_shop_instance(shop)
        assert shop_product.pk
        assert shop_product.default_price_value == 150
        assert shop_product.default_price == shop.create_price(150)
        assert product.type == product_type  # product type comes from importer defaults
        assert product.sales_unit == sales_unit
        if product.pk == 1:
            assert product.tax_class.pk == 2  # new was created
            assert product.name == "Product English"
            assert product.description == "Description English"
        else:
            assert product.tax_class.pk == tax_class.pk  # old was found as should
            assert product.name == "Product 2 English"
            assert product.description == "Description English 2"
        assert shop_product.primary_category.pk == 1
        assert [c.pk for c in shop_product.categories.all()] == [1,2]

    # stock was not managed since supplier doesn't like that
    for msg in importer.other_log_messages:
        assert "please set Stock Managed on" in msg

    supplier.stock_managed = True
    supplier.save()
    importer.do_import("create,update")

    assert len(importer.other_log_messages) == 0
    for sa in StockAdjustment.objects.all():
        assert sa.product.pk
        assert sa.delta == 20
Пример #21
0
def test_custom_payment_processor_defaults(choice_identifier, default_behavior_components):
    shop = get_default_shop()
    processor = CustomPaymentProcessor.objects.create()
    service = processor.create_service(choice_identifier, shop=shop, tax_class=get_default_tax_class())

    assert service.behavior_components.count() == len(default_behavior_components)
    for behavior in default_behavior_components:
        assert ServiceBehaviorComponent.objects.instance_of(behavior).count() == 1
Пример #22
0
def test_service_methods_with_long_name(rf):
    """
    Make sure that service methods with long names (up to the max length of
    shipping or payment method names) don't cause exceptions when creating
    an order.
    """
    MAX_LENGTH = 100
    long_name = "X" * MAX_LENGTH
    assert len(long_name) == MAX_LENGTH
    sm = ShippingMethod.objects.language("en").create(
        shop=get_default_shop(), name=long_name, enabled=True, tax_class=get_default_tax_class())
    pm = PaymentMethod.objects.language("en").create(
        shop=get_default_shop(), name=long_name, enabled=True, tax_class=get_default_tax_class())
    order = create_empty_order()
    order.shipping_method = sm
    order.payment_method = pm
    order.full_clean()
    order.save()
Пример #23
0
def test_payment_method_wizard_pane(rf, admin_user, settings):
    settings.SHUUP_SETUP_WIZARD_PANE_SPEC = [
        "shuup.admin.modules.service_providers.views.PaymentWizardPane"
    ]
    shop = get_default_shop()
    get_default_tax_class()
    fields = _extract_fields(rf, admin_user)
    fields["payment_method_base-providers"] = "manual_payment"
    fields["manual_payment-service_name"] = "test"

    request = apply_request_middleware(rf.post("/", data=fields), user=admin_user)
    response = WizardView.as_view()(request)
    assert response.status_code == 200
    assert ServiceProvider.objects.count() == 1
    assert CustomPaymentProcessor.objects.count() == 1
    assert CustomPaymentProcessor.objects.first().name == "Manual"
    assert PaymentMethod.objects.count() == 1
    assert PaymentMethod.objects.first().name == "test"
    assert_redirect_to_dashboard(rf, admin_user, shop)
Пример #24
0
def test_shipping_method_wizard_pane(rf, admin_user, settings):
    settings.SHUUP_SETUP_WIZARD_PANE_SPEC = [
        "shuup.admin.modules.service_providers.views.CarrierWizardPane"
    ]
    shop = get_default_shop()
    get_default_tax_class()
    fields = _extract_fields(rf, admin_user)
    fields["shipping_method_base-providers"] = "manual_shipping"
    fields["manual_shipping-service_name"] = "test"

    request = rf.post("/", data=fields)
    response = WizardView.as_view()(request)
    assert response.status_code == 200
    assert ServiceProvider.objects.count() == 1
    assert CustomCarrier.objects.count() == 1
    assert CustomCarrier.objects.first().name == "Manual"
    assert ShippingMethod.objects.count() == 1
    assert ShippingMethod.objects.first().name == "test"
    assert_redirect_to_dashboard(rf)
Пример #25
0
def test_product_create(browser, admin_user, live_server, settings):
    activate("en")
    shop = get_default_shop()
    get_default_product_type()
    get_default_sales_unit()
    get_default_tax_class()
    object_created.connect(_add_custom_product_created_message, sender=Product, dispatch_uid="object_created_signal_test")
    initialize_admin_browser_test(browser, live_server, settings)

    url = reverse("shuup_admin:shop_product.new")
    browser.visit("%s%s" % (live_server, url))
    wait_until_condition(browser, condition=lambda x: x.is_text_present("New shop product"))

    sku = "testsku"
    name = "Some product name"
    price_value = 10
    short_description = "short but gold"
    move_to_element(browser, "#id_base-sku")
    browser.fill("base-sku", sku)
    browser.fill("base-name__en", name)
    browser.fill("base-short_description__en", short_description)
    browser.fill("shop%s-default_price_value" % shop.pk, price_value)

    _add_primary_category(browser, shop)
    _add_additional_category(browser, shop)

    move_to_element(browser, "button[form='product_form']")
    try:
        click_element(browser, "button[form='product_form']")
        wait_until_appeared(browser, "div[class='message success']")
    except selenium.common.exceptions.WebDriverException as e:
        # TODO: Revise!
        # Give a product save second chance it seems that the save can
        # lag a little and the success message doesn't happen fast
        # enough every single time.
        click_element(browser, "button[form='product_form']")
        wait_until_appeared(browser, "div[class='message success']")
    product = Product.objects.filter(sku=sku).first()
    assert product.log_entries.filter(identifier=OBJECT_CREATED_LOG_IDENTIFIER).count() == 1
    object_created.disconnect(sender=Product, dispatch_uid="object_created_signal_test")
    shop_product = product.get_shop_instance(shop)
    assert shop_product.categories.count() == 2
Пример #26
0
def _get_shipping_method_with_phase():
    carrier = CarrierWithCheckoutPhase.objects.create(
        identifier="carrier_with_phase", enabled=True)
    assert isinstance(carrier, CarrierWithCheckoutPhase)
    return carrier.create_service(
        None,
        identifier="carrier_with_phase",
        shop=get_default_shop(),
        name="Test method with phase",
        enabled=True,
        tax_class=get_default_tax_class())
Пример #27
0
def test_admin(rf, admin_user):
    activate("en")
    shop = get_default_shop()
    shop.staff_members.add(admin_user)
    get_default_tax_class()
    get_default_product_type()
    get_default_sales_unit()

    client = do_importing("123", "test", "en", shop)
    # change import language and update product
    client = do_importing("123", "test-fi", "fi", shop, client=client)

    # update name in english
    client = do_importing("123", "test-en", "en", shop, client=client)

    # cannot update
    client = do_importing("123", "test", "en", shop, import_mode=ImportMode.CREATE, client=client)

    # can update
    do_importing("123", "test", "en", shop, import_mode=ImportMode.UPDATE, client=client)
Пример #28
0
def _get_payment_method_with_phase():
    processor = PaymentWithCheckoutPhase.objects.create(
        identifier="processor_with_phase", enabled=True)
    assert isinstance(processor, PaymentWithCheckoutPhase)
    return processor.create_service(
        None,
        identifier="payment_with_phase",
        shop=get_default_shop(),
        name="Test method with phase",
        enabled=True,
        tax_class=get_default_tax_class())
Пример #29
0
def test_weight_limits():
    carrier = CustomCarrier.objects.create()
    sm = carrier.create_service(
        None, shop=get_default_shop(), enabled=True,
        tax_class=get_default_tax_class())
    sm.behavior_components.add(
        WeightLimitsBehaviorComponent.objects.create(
            min_weight=100, max_weight=500))
    source = BasketishOrderSource(get_default_shop())
    assert any(ve.code == "min_weight" for ve in sm.get_unavailability_reasons(source))
    source.add_line(type=OrderLineType.PRODUCT, weight=600)
    assert any(ve.code == "max_weight" for ve in sm.get_unavailability_reasons(source))
Пример #30
0
def get_expensive_sweden_shipping_method():
    carrier = CustomCarrier.objects.create(name="Sveede Sheep")
    sm = carrier.create_service(
        None, shop=get_default_shop(), enabled=True,
        tax_class=get_default_tax_class(),
        name="Expenseefe-a Svedee Sheepping")
    sm.behavior_components.add(
        ExpensiveSwedenBehaviorComponent.objects.create(),
        WeightLimitsBehaviorComponent.objects.create(
            min_weight="0.11", max_weight="3"),
    )
    return sm
Пример #31
0
def test_views(rf):
    initialize()
    c = SmartClient()
    default_product = get_default_product()
    basket_path = reverse("shuup:basket")
    c.post(basket_path,
           data={
               "command": "add",
               "product_id": default_product.pk,
               "quantity": 1,
               "supplier": get_default_supplier().pk
           })

    shipping_method = get_default_shipping_method()
    processor = get_payment_provider()
    payment_method = processor.create_service(
        PagSeguroPaymentMethod.ONLINE_DEBIT.value,
        identifier="pagseguro_debit",
        shop=get_default_shop(),
        name="debit",
        enabled=True,
        tax_class=get_default_tax_class())

    addresses_path = reverse("shuup:checkout", kwargs={"phase": "addresses"})
    methods_path = reverse("shuup:checkout", kwargs={"phase": "methods"})
    payment_path = reverse("shuup:checkout", kwargs={"phase": "payment"})
    confirm_path = reverse("shuup:checkout", kwargs={"phase": "confirm"})

    addresses_soup = c.soup(addresses_path)
    inputs = fill_address_inputs(addresses_soup, with_company=False)
    c.post(addresses_path, data=inputs)
    c.post(methods_path,
           data={
               "payment_method": payment_method.pk,
               "shipping_method": shipping_method.pk
           })
    c.get(confirm_path)
    c.soup(payment_path)
    c.post(
        payment_path, {
            "paymentMethod":
            PagSeguroPaymentMethodIdentifier.Debito,
            "bankOption":
            "{0}".format(PagSeguroPaymentMethodCode.DebitoOnlineBB.value),
            "senderHash":
            "J7E98Y37WEIRUHDIAI9U8RYE7UQE"
        })

    transaction_code = "38490248UEHBU90-2342-324502221-442"

    confirm_soup = c.soup(confirm_path)
    c.post(confirm_path, data=extract_form_fields(confirm_soup))
    order = Order.objects.filter(payment_method=payment_method).first()
    payment = PagSeguroPayment.objects.create(
        order=order,
        code=transaction_code,
        data={"transaction": {
            "status": "1"
        }})
    payment.save()
    order.payment_data['pagseguro']['code'] = payment.code
    order.save()

    # Verifica: pagseguro_payment_return
    response = c.get(reverse("shuup:pagseguro_payment_return"))
    assert response.status_code == 302
    assert reverse("shuup:checkout", kwargs={"phase":
                                             "payment"}) in response.url

    notify_path = reverse("shuup:pagseguro_notification")

    # Erro: notificationCode nao informado
    response = c.post(notify_path)
    assert response.status_code == 200
    assert len(response.content.decode("utf-8")) == 0
    assert response[
        "Access-Control-Allow-Origin"] == 'https://sandbox.pagseguro.uol.com.br'

    # Sucesso 1
    transaction_info = xmltodict.parse("""
        <?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>
        <transaction>
            <status>2</status>
            <code>{0}</code>
        </transaction>
    """.format(transaction_code).strip())

    # altera retorno do get_notification_info
    with patch.object(PagSeguro,
                      'get_notification_info',
                      return_value=transaction_info):
        response = c.post(notify_path,
                          {"notificationCode": "it-does-not-mattter"})
        assert response.status_code == 200
        assert response[
            "Access-Control-Allow-Origin"] == 'https://sandbox.pagseguro.uol.com.br'

        payment.refresh_from_db()
        order.refresh_from_db()
        assert payment.data['transaction']['status'] == "2"
        assert payment.data['transaction']['code'] == transaction_code
        assert order.payment_status == PaymentStatus.NOT_PAID

    # Sucesso 2 - PAGO, emite notificacao e bota o pedido como pago
    transaction_info = xmltodict.parse("""
        <?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>
        <transaction>
            <status>3</status>
            <code>{0}</code>
        </transaction>
    """.format(transaction_code).strip())
    with patch.object(PagSeguro,
                      'get_notification_info',
                      return_value=transaction_info):
        response = c.post(notify_path,
                          {"notificationCode": "it-does-not-mattter"})
        assert response.status_code == 200

        payment.refresh_from_db()
        order.refresh_from_db()

        assert payment.data['transaction']['status'] == "3"
        assert order.payment_status == PaymentStatus.FULLY_PAID

    # volta o pedido ao estado de não pago
    order.payment_status = PaymentStatus.NOT_PAID
    order.save()

    # Sucesso 3 - CANCELADO, emite notificacao e bota o pedido como cancelado
    transaction_info = xmltodict.parse("""
        <?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>
        <transaction>
            <status>7</status>
            <code>{0}</code>
        </transaction>
    """.format(transaction_code).strip())
    with patch.object(PagSeguro,
                      'get_notification_info',
                      return_value=transaction_info):
        response = c.post(notify_path,
                          {"notificationCode": "it-does-not-mattter"})
        assert response.status_code == 200

        payment.refresh_from_db()
        order.refresh_from_db()

        assert payment.data['transaction']['status'] == "7"
        assert order.status.role == OrderStatusRole.CANCELED
Пример #32
0
def test_pagseguro():
    initialize()
    c = SmartClient()
    default_product = get_default_product()
    basket_path = reverse("shuup:basket")
    c.post(basket_path,
           data={
               "command": "add",
               "product_id": default_product.pk,
               "quantity": 1,
               "supplier": get_default_supplier().pk
           })

    shipping_method = get_default_shipping_method()
    processor = get_payment_provider()
    payment_method = processor.create_service(
        PagSeguroPaymentMethod.ONLINE_DEBIT.value,
        identifier="pagseguro_debit",
        shop=get_default_shop(),
        name="debit",
        enabled=True,
        tax_class=get_default_tax_class())

    addr = MutableAddress.from_data(
        dict(
            name=u"Dog Hello",
            suffix=", Esq.",
            postal_code="89999-999",
            street="Woof Ave.",
            city="Dog Fort",
            country="GB",
            phone="47 98821-2231",
        ))
    patch("shuup.testing.factories.get_address", new_callable=lambda: addr)

    addresses_path = reverse("shuup:checkout", kwargs={"phase": "addresses"})
    methods_path = reverse("shuup:checkout", kwargs={"phase": "methods"})
    payment_path = reverse("shuup:checkout", kwargs={"phase": "payment"})
    confirm_path = reverse("shuup:checkout", kwargs={"phase": "confirm"})

    addresses_soup = c.soup(addresses_path)
    inputs = fill_address_inputs(addresses_soup, with_company=False)
    c.post(addresses_path, data=inputs)
    c.post(methods_path,
           data={
               "payment_method": payment_method.pk,
               "shipping_method": shipping_method.pk
           })
    c.get(confirm_path)
    c.soup(payment_path)
    c.post(
        payment_path, {
            "paymentMethod":
            PagSeguroPaymentMethodIdentifier.Debito,
            "bankOption":
            "{0}".format(PagSeguroPaymentMethodCode.DebitoOnlineBB.value),
            "senderHash":
            "J7E98Y37WEIRUHDIAI9U8RYE7UQE"
        })

    confirm_soup = c.soup(confirm_path)
    c.post(confirm_path, data=extract_form_fields(confirm_soup))
    order = Order.objects.filter(payment_method=payment_method).first()
    USER_MODEL = get_user_model()

    order.phone = "47 98821-2231"
    order.creator = get_user_model().objects.create_user(
        **{
            USER_MODEL.USERNAME_FIELD: "*****@*****.**",
            "password": "******"
        })
    order.save()

    pagseguro = PagSeguro.create_from_config(get_pagseguro_config())

    # unpatch methods
    patch.stopall()

    # Test: get_session_id - SUCCESS
    session_xml_fake = """<session><id>WOEIFJE9IUREI29RU8</id></session>"""
    response = Mock()
    response.status_code = 200
    response.content = session_xml_fake
    with patch.object(requests, 'post', return_value=response):
        session_id = xmltodict.parse(session_xml_fake)['session']['id']
        assert pagseguro.get_session_id() == session_id

    # Test: get_session_id - EXCEPTION
    response = Mock()
    response.status_code = 500
    response.content = ERROR_XML
    with patch.object(requests, 'post', return_value=response):
        with pytest.raises(PagSeguroException) as exc:
            pagseguro.get_session_id()
        assert exc.value.status_code == 500
        assert exc.value.error == ERROR_XML

    # Test: get_notification_info - SUCCESS
    transaction_xml_fake = """<transaction><date>WOEIFJE9IUREI29RU8</date></transaction>"""
    response = Mock()
    response.status_code = 200
    response.content = transaction_xml_fake
    with patch.object(requests, 'get', return_value=response):
        assert pagseguro.get_notification_info("XXXX") == xmltodict.parse(
            transaction_xml_fake)

    # Test: get_notification_info - EXCEPTION
    response = Mock()
    response.status_code = 500
    response.content = ERROR_XML
    with patch.object(requests, 'get', return_value=response):
        with pytest.raises(PagSeguroException) as exc:
            pagseguro.get_notification_info("ZZZZ")
        assert exc.value.status_code == 500
        assert exc.value.error == ERROR_XML

    # Test: get_transaction_info - SUCCESS
    transaction_xml_fake = """<transaction><date>WOEIFJE9IUREI29RU8</date></transaction>"""
    response = Mock()
    response.status_code = 200
    response.content = transaction_xml_fake
    with patch.object(requests, 'get', return_value=response):
        assert pagseguro.get_transaction_info("XXXX") == xmltodict.parse(
            transaction_xml_fake)

    # Test: get_transaction_info - EXCEPTION
    response = Mock()
    response.status_code = 500
    response.content = ERROR_XML
    with patch.object(requests, 'get', return_value=response):
        with pytest.raises(PagSeguroException) as exc:
            pagseguro.get_transaction_info("ZZZZ")
        assert exc.value.status_code == 500
        assert exc.value.error == ERROR_XML

    # Test: pay - SUCCESS
    response = Mock()
    response.status_code = 200
    response.content = TRANSACTION_XML
    with patch.object(requests, 'post', return_value=response):
        parsed_xml = xmltodict.parse(TRANSACTION_XML)
        result = pagseguro.pay(payment_method, order)
        assert isinstance(result, PagSeguroPaymentResult)
        assert result.error is False
        assert result._data == parsed_xml
        assert result.code == parsed_xml['transaction']['code']
        assert result.payment_link == parsed_xml['transaction']['paymentLink']

    # Test: pay - ERROR
    response = Mock()
    response.status_code = 400
    response.content = ERROR_XML
    with patch.object(requests, 'post', return_value=response):
        parsed_xml = xmltodict.parse(ERROR_XML)
        result = pagseguro.pay(payment_method, order)
        assert isinstance(result, PagSeguroPaymentResult)
        assert result.error is True
        assert result._data == parsed_xml
        assert result.errors == parsed_xml['errors']

    # Test: pay - EXCEPTION
    response = Mock()
    response.status_code = 500
    response.content = "A BIG MISTAKE"
    with patch.object(requests, 'post', return_value=response):
        with pytest.raises(PagSeguroException) as exc:
            pagseguro.pay(payment_method, order)
        assert exc.value.status_code == 500
        assert exc.value.error == "A BIG MISTAKE"

    def get_only_nums(value):
        return "".join([c for c in value if c.isdigit()])

    # Test: _get_payment_xml with CPF
    order.creator.pf_person = PFPerson()
    payment_xml = xmltodict.parse(
        pagseguro._get_payment_xml(payment_method, order))

    assert payment_xml['payment']['currency'] == 'BRL'
    assert payment_xml['payment'][
        'method'] == PagSeguroPaymentMethodIdentifier.Debito
    assert payment_xml['payment']['sender']['documents']['document'][
        'type'] == 'CPF'
    assert payment_xml['payment']['sender']['documents']['document'][
        'value'] == get_only_nums(PFPerson().cpf)

    # Test: _get_payment_xml with CNPJ
    delattr(order.creator, 'pf_person')
    order.creator.pj_person = PJPerson()
    payment_xml = xmltodict.parse(
        pagseguro._get_payment_xml(payment_method, order))
    assert payment_xml['payment']['sender']['documents']['document'][
        'type'] == 'CNPJ'
    assert payment_xml['payment']['sender']['documents']['document'][
        'value'] == get_only_nums(PJPerson().cnpj)

    assert payment_xml['payment']['sender']['phone']['areaCode'] == "47"
    assert payment_xml['payment']['sender']['phone']['number'] == "988212231"
Пример #33
0
def test_tax_class_selector(admin_user):
    shop = get_default_shop()
    get_default_tax_class()
    assert get_object_selector_results(TaxClass, shop, admin_user, "Default")
def test_many_price_info_cache_bump(rf):
    initial_price = 10
    shop = factories.get_default_shop()
    tax = factories.get_default_tax()
    tax_class = factories.get_default_tax_class()
    product = factories.create_product(
        "product",
        shop=shop,
        supplier=factories.get_default_supplier(),
        default_price=initial_price
    )
    child1 = factories.create_product(
        "child1",
        shop=shop,
        supplier=factories.get_default_supplier(),
        default_price=5
    )
    child2 = factories.create_product(
        "child2",
        shop=shop,
        supplier=factories.get_default_supplier(),
        default_price=9
    )
    child1.link_to_parent(product, variables={"color": "red"})
    child2.link_to_parent(product, variables={"color": "blue"})

    request = apply_request_middleware(rf.get("/"))
    child1_pi = child1.get_price_info(request)
    child2_pi = child1.get_price_info(request)

    def assert_cache_products():
        cache_many_price_info(request, product, 1, [child1_pi, child2_pi])
        assert get_many_cached_price_info(request, product, 1)[0].price == child1_pi.price
        assert get_many_cached_price_info(request, product, 1)[1].price == child2_pi.price

    def assert_nothing_is_cached():
        # nothing is cached
        assert get_many_cached_price_info(request, product, 1) is None

    # cache the item
    assert_nothing_is_cached()
    assert_cache_products()

    # cache bumped - the cache should be dropped - then, cache again
    tax.save()
    assert_nothing_is_cached()
    assert_cache_products()

    # cache bumped - the cache should be dropped - then, cache again
    tax_class.save()
    assert_nothing_is_cached()
    assert_cache_products()

    # cache bumped - the cache should be dropped - then, cache again
    product.save()
    assert_nothing_is_cached()
    assert_cache_products()

    shop_product = product.get_shop_instance(shop)

    # cache bumped - the cache should be dropped - then, cache again
    shop_product.save()
    assert_nothing_is_cached()
    assert_cache_products()

    category = factories.get_default_category()

    # cache bumped - the cache should be dropped - then, cache again
    shop_product.categories.add(category)
    assert_nothing_is_cached()
    assert_cache_products()
Пример #35
0
def test_payment_refresh():
    """ Testa pagamentos """

    initialize()
    c = SmartClient()
    default_product = get_default_product()
    basket_path = reverse("shuup:basket")
    c.post(basket_path,
           data={
               "command": "add",
               "product_id": default_product.pk,
               "quantity": 1,
               "supplier": get_default_supplier().pk
           })

    shipping_method = get_default_shipping_method()
    processor = get_payment_provider()
    payment_method = processor.create_service(
        PagSeguroPaymentMethod.ONLINE_DEBIT.value,
        identifier="pagseguro_debit",
        shop=get_default_shop(),
        name="debit",
        enabled=True,
        tax_class=get_default_tax_class())

    service_choices = processor.get_service_choices()
    assert len(service_choices) == 2
    assert service_choices[0].identifier == PagSeguroPaymentMethod.BOLETO.value
    assert service_choices[
        1].identifier == PagSeguroPaymentMethod.ONLINE_DEBIT.value

    addresses_path = reverse("shuup:checkout", kwargs={"phase": "addresses"})
    methods_path = reverse("shuup:checkout", kwargs={"phase": "methods"})
    payment_path = reverse("shuup:checkout", kwargs={"phase": "payment"})
    confirm_path = reverse("shuup:checkout", kwargs={"phase": "confirm"})

    addresses_soup = c.soup(addresses_path)
    inputs = fill_address_inputs(addresses_soup, with_company=False)
    c.post(addresses_path, data=inputs)
    c.post(methods_path,
           data={
               "payment_method": payment_method.pk,
               "shipping_method": shipping_method.pk
           })
    c.get(confirm_path)
    c.soup(payment_path)
    c.post(
        payment_path, {
            "paymentMethod":
            PagSeguroPaymentMethodIdentifier.Debito,
            "bankOption":
            "{0}".format(PagSeguroPaymentMethodCode.DebitoOnlineBB.value),
            "senderHash":
            "J7E98Y37WEIRUHDIAI9U8RYE7UQE"
        })

    confirm_soup = c.soup(confirm_path)
    c.post(confirm_path, data=extract_form_fields(confirm_soup))
    order = Order.objects.filter(payment_method=payment_method).first()
    process_payment_path = reverse("shuup:order_process_payment",
                                   kwargs={
                                       "pk": order.pk,
                                       "key": order.key
                                   })
    process_payment_return_path = reverse("shuup:order_process_payment_return",
                                          kwargs={
                                              "pk": order.pk,
                                              "key": order.key
                                          })
    order_complete_path = reverse("shuup:order_complete",
                                  kwargs={
                                      "pk": order.pk,
                                      "key": order.key
                                  })

    c.get(process_payment_path)
    c.get(process_payment_return_path)
    c.get(order_complete_path)

    # testa o refresh do pagamento
    payment = PagSeguroPayment.objects.get(order=order)

    transaction_info = xmltodict.parse("""
        <?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>
        <transaction>
            <status>2</status>
        </transaction>
    """.strip())

    # altera o estado da transacao
    with patch.object(PagSeguro,
                      'get_transaction_info',
                      return_value=transaction_info):
        assert payment.data['transaction']['status'] == "3"
        payment.refresh()
        assert payment.data['transaction']['status'] == "2"

    # format string
    "{0}".format(payment)
Пример #36
0
def test_sample_import_no_match(rf, stock_managed):
    filename = "sample_import_nomatch.xlsx"
    if "shuup.simple_supplier" not in settings.INSTALLED_APPS:
        pytest.skip("Need shuup.simple_supplier in INSTALLED_APPS")
    from shuup_tests.simple_supplier.utils import get_simple_supplier

    activate("en")
    shop = get_default_shop()
    tax_class = get_default_tax_class()
    product_type = get_default_product_type()
    supplier = get_simple_supplier(stock_managed)
    sales_unit = get_default_sales_unit()

    Manufacturer.objects.create(name="manufctr")
    path = os.path.join(os.path.dirname(__file__), "data", "product", filename)
    transformed_data = transform_file(filename.split(".")[1], path)

    importer = ProductImporter(
        transformed_data,
        ProductImporter.get_importer_context(rf.get("/"), shop=shop, language="en")
    )
    importer.process_data()
    assert len(importer.unmatched_fields) == 1
    assert "gtiin" in importer.unmatched_fields
    importer.manually_match("gtiin", "shuup.core.models.Product:gtin")
    importer.do_remap()
    assert len(importer.unmatched_fields) == 0
    importer.do_import(ImportMode.CREATE_UPDATE)
    products = importer.new_objects
    assert len(products) == 2

    for product in products:
        assert product.gtin == "1280x720"
        shop_product = product.get_shop_instance(shop)
        assert shop_product.pk
        assert shop_product.default_price_value == 150
        assert shop_product.default_price == shop.create_price(150)
        assert product.type == product_type  # product type comes from importer defaults
        assert product.sales_unit == sales_unit
        if product.pk == 1:
            assert product.tax_class.pk == 2  # new was created
            assert product.name == "Product English"
            assert product.description == "Description English"
        else:
            assert product.tax_class.pk == tax_class.pk  # old was found as should
            assert product.name == "Product 2 English"
            assert product.description == "Description English 2"
        assert shop_product.primary_category.pk == 1
        assert [c.pk for c in shop_product.categories.all()] == [1, 2]

    # stock was not managed since supplier doesn't like that
    for msg in importer.other_log_messages:
        assert "please set `Stock Managed` on" in msg

    supplier.stock_managed = True
    supplier.save()
    importer.do_import("create,update")

    assert len(importer.other_log_messages) == 0
    for sa in StockAdjustment.objects.all():
        assert sa.product.pk
        assert sa.delta == 20
Пример #37
0
def test_weight_limits():
    carrier = CustomCarrier.objects.create()
    sm = carrier.create_service(None, shop=get_default_shop(), enabled=True, tax_class=get_default_tax_class())
    sm.behavior_components.add(WeightLimitsBehaviorComponent.objects.create(min_weight=100, max_weight=500))
    source = BasketishOrderSource(get_default_shop())
    assert any(ve.code == "min_weight" for ve in sm.get_unavailability_reasons(source))
    source.add_line(type=OrderLineType.PRODUCT, weight=600)
    assert any(ve.code == "max_weight" for ve in sm.get_unavailability_reasons(source))
Пример #38
0
def test_remap(rf, admin_user):
    lang = "en"
    import_mode = ImportMode.CREATE_UPDATE
    sku = "123"
    name = "test"

    import_path = reverse("shuup_admin:importer.import")
    process_path = reverse("shuup_admin:importer.import_process")
    tax_class = get_default_tax_class()
    product_type = get_default_product_type()

    activate("en")
    shop = get_default_shop()
    shop.staff_members.add(admin_user)
    client = SmartClient()
    client.login(username="******", password="******")
    csv_content = str.encode("sku;name;gtiin\n%s;%s;111" % (sku, name))

    # show import view
    data = {
        "importer":
        "product_importer",
        "shop":
        shop.pk,
        "language":
        lang,
        "file":
        SimpleUploadedFile("file.csv", csv_content, content_type="text/csv")
    }
    response = client.post(import_path, data=data)
    assert response.status_code == 302
    query_string = urlparse(response["location"]).query
    query = parse_qs(query_string)

    data = {  # data with missing `n`
        "importer": "product_importer",
        "shop": shop.pk,
        "language": lang,
        "n": query.get("n")
    }
    soup = client.soup(process_path, data=data)
    assert "The following fields must be manually tied" in str(soup)

    for row in soup.findAll("tr"):
        first_td = row.find("td")
        if not first_td:
            continue

        tds = row.findAll("td")
        if len(tds) < 2:
            continue
        second_td = tds[1]
        if first_td.text.startswith("Connection"):
            # check that sku was connected
            badges = second_td.findAll("span", {"class": "badge"})
            assert len(badges) == 1
            assert badges[0].text == "sku"
        elif first_td.text.startswith("The following fields"):
            badges = second_td.findAll("span", {"class": "badge"})
            assert len(badges) == 2
            badge_texts = []
            for b in badges:
                badge_texts.append(b.text)
            badge_texts.sort()
            assert badge_texts[0] == "name"
            assert badge_texts[1] == "sku"

    data = {}
    data["import_mode"] = import_mode.value
    data["remap[gtiin]"] = "Product:gtin"  # map gtin
    process_submit_path = "%s?%s" % (process_path, query_string)
    client.soup(process_submit_path, data=data, method="post")
    assert Product.objects.count() == 1
    product = Product.objects.first()
    assert product.gtin == "111"
Пример #39
0
def test_invalid_file_type(rf, admin_user):
    lang = "en"
    import_mode = ImportMode.CREATE_UPDATE
    sku = "123"
    name = "test"

    import_path = reverse("shuup_admin:importer.import.new")
    process_path = reverse("shuup_admin:importer.import_process")
    get_default_tax_class()
    get_default_product_type()
    get_default_sales_unit()

    activate("en")
    shop = get_default_shop()
    shop.staff_members.add(admin_user)
    client = SmartClient()
    client.login(username="******", password="******")
    csv_content = str.encode("sku;name\n%s;%s" % (sku, name))

    # show import view
    data = {
        "importer":
        "product_importer",
        "shop":
        shop.pk,
        "language":
        lang,
        "file":
        SimpleUploadedFile("file.derp", csv_content, content_type="text/csv"),
    }
    response = client.post(import_path, data=data)
    assert response.status_code == 302
    query_string = urlparse(response["location"]).query

    data = {  # data with missing `n`
        "importer": "product_importer",
        "shop": shop.pk,
        "language": lang,
    }
    response, soup = client.response_and_soup(process_path, data=data)
    assert response.status_code == 400

    for row in soup.findAll("tr"):
        first_td = row.find("td")
        if not first_td:
            continue

        tds = row.findAll("td")
        if len(tds) < 2:
            continue
        second_td = tds[1]
        if first_td.text.startswith("Connection"):
            # check that sku was connected
            badges = second_td.findAll("span", {"class": "badge"})
            assert len(badges) == 1
            assert badges[0].text == "sku"
        elif first_td.text.startswith("The following fields"):
            badges = second_td.findAll("span", {"class": "badge"})
            assert len(badges) == 2
            badge_texts = []
            for b in badges:
                badge_texts.append(b.text)
            badge_texts.sort()
            assert badge_texts[0] == "name"
            assert badge_texts[1] == "sku"

    data = {}
    data["import_mode"] = import_mode.value
    process_submit_path = "%s?%s" % (process_path, query_string)
    response = client.post(process_submit_path, data=data)
    assert response.status_code == 302
Пример #40
0
def test_edit_button_no_permission(browser, admin_user, live_server, settings):
    shop = get_default_shop()

    manager_group = Group.objects.create(name="Managers")

    manager = create_random_user("en", is_staff=True)
    manager.username = "******"
    manager.set_password("password")
    manager.save()
    manager.groups.add(manager_group)
    shop.staff_members.add(manager)

    # add permissions for Product admin module
    manager_permissions = set(["dashboard", "Products", "shop_product.new"])
    set_permissions_for_group(manager_group, manager_permissions)

    get_default_product_type()
    get_default_sales_unit()
    get_default_tax_class()
    initialize_admin_browser_test(browser,
                                  live_server,
                                  settings,
                                  username=manager.username)

    url = reverse("shuup_admin:shop_product.new")
    browser.visit("%s%s" % (live_server, url))

    sku = "testsku"
    name = "Some product name"
    price_value = 10
    short_description = "short but gold"

    browser.fill("base-sku", sku)
    browser.fill("base-name__en", name)
    browser.fill("base-short_description__en", short_description)
    browser.fill("shop%s-default_price_value" % shop.pk, price_value)

    wait_until_appeared(
        browser,
        "#id_shop%d-primary_category ~ .quick-add-btn a.btn" % shop.id)
    click_element(
        browser,
        "#id_shop%d-primary_category ~ .quick-add-btn a.btn" % shop.id)
    wait_until_appeared(browser, "#create-object-iframe")

    # no permission to add category
    with browser.get_iframe('create-object-iframe') as iframe:
        error = "Can't view this page. You do not have the required permissions: category.new"
        wait_until_condition(iframe,
                             condition=lambda x: x.is_text_present(error))

    # close iframe
    click_element(browser, "#create-object-overlay a.close-btn")

    # add permission to add category
    manager_permissions.add("category.new")
    manager_permissions.add("category.edit")
    set_permissions_for_group(manager_group, manager_permissions)

    # click to add category again
    click_element(
        browser,
        "#id_shop%d-primary_category ~ .quick-add-btn a.btn" % shop.id)
    wait_until_appeared(browser, "#create-object-iframe")

    # add the category
    with browser.get_iframe('create-object-iframe') as iframe:
        assert Category.objects.count() == 0
        wait_until_appeared(iframe, "input[name='base-name__en']")
        iframe.fill("base-name__en", "Test Category")
        time.sleep(
            3
        )  # Let's just wait here to the iFrame to open fully (for Chrome and headless)
        wait_until_appeared(iframe, "button[form='category_form']")
        click_element(browser, "button[form='category_form']")
        wait_until_condition(browser,
                             condition=lambda x: Category.objects.count() == 1,
                             timeout=20)

    assert Category.objects.first().name == "Test Category"

    # remove the edit category permissions
    # add permission to add category
    manager_permissions.remove("category.edit")
    set_permissions_for_group(manager_group, manager_permissions)

    # click to edit the button
    click_element(
        browser,
        "#id_shop%d-primary_category ~ .edit-object-btn a.btn" % shop.id)

    # no permission to edit category
    with browser.get_iframe('create-object-iframe') as iframe:
        error = "Can't view this page. You do not have the required permission(s): category.edit"
        wait_until_condition(iframe,
                             condition=lambda x: x.is_text_present(error))

    # close iframe
    click_element(browser, "#create-object-overlay a.close-btn")

    manager_permissions.add("category.edit")
    set_permissions_for_group(manager_group, manager_permissions)

    click_element(
        browser,
        "#id_shop%d-primary_category ~ .edit-object-btn a.btn" % shop.id)
    wait_until_appeared(browser, "#create-object-iframe")

    new_cat_name = "Changed Name"
    with browser.get_iframe('create-object-iframe') as iframe:
        wait_until_appeared(iframe, "input[name='base-name__en']")
        iframe.fill("base-name__en", new_cat_name)
        time.sleep(
            3
        )  # Let's just wait here to the iFrame to open fully (for Chrome and headless)
        wait_until_appeared(iframe, "button[form='category_form']")
        click_element(browser, "button[form='category_form']")

    wait_until_condition(
        browser,
        condition=lambda x: Category.objects.first().name == new_cat_name,
        timeout=20)
Пример #41
0
def test_variatins_import(rf):
    filename = "product_sample_import_with_variations.xlsx"
    if "shuup.simple_supplier" not in settings.INSTALLED_APPS:
        pytest.skip("Need shuup.simple_supplier in INSTALLED_APPS")

    from shuup_tests.simple_supplier.utils import get_simple_supplier

    activate("en")
    shop = get_default_shop()
    product_type = get_default_product_type()
    sales_unit = get_default_sales_unit()
    tax_class = get_default_tax_class()

    # Create media
    _create_random_media_file(shop, "shirt1.jpeg")
    _create_random_media_file(shop, "shirt2.jpeg")
    _create_random_media_file(shop, "shirt3.jpeg")

    path = os.path.join(os.path.dirname(__file__), "data", "product", filename)
    transformed_data = transform_file(filename.split(".")[1], path)

    importer = ProductImporter(
        transformed_data,
        ProductImporter.get_importer_context(rf.get("/"),
                                             shop=shop,
                                             language="en"))
    importer.process_data()

    assert len(importer.unmatched_fields) == 0

    importer.do_import(ImportMode.CREATE_UPDATE)
    products = importer.new_objects

    assert len(products) == 42  # 2 parents 20 variations each

    supplier = Supplier.objects.first()
    assert supplier and supplier.stock_managed and supplier.module_identifier == "simple_supplier"
    assert ShopProduct.objects.filter(suppliers=supplier).count() == 42

    parent1 = Product.objects.filter(sku=1).first()
    assert parent1.mode == ProductMode.VARIABLE_VARIATION_PARENT
    assert parent1.variation_children.all().count() == 20

    # Check product names
    child1 = Product.objects.filter(sku=10).first()
    assert child1.name == "T-Shirt - Pink - S"

    child2 = Product.objects.filter(sku=11).first()
    assert child2.name == "T-Shirt - Pink - XS"

    # Check stock counts
    assert supplier.get_stock_status(child1.pk).logical_count == Decimal(5)
    assert supplier.get_stock_status(child2.pk).logical_count == Decimal(10)

    parent2 = Product.objects.filter(sku=22).first()
    assert parent1.mode == ProductMode.VARIABLE_VARIATION_PARENT
    assert parent1.variation_children.all().count() == 20

    # Check product names
    child1 = Product.objects.filter(sku=38).first()
    assert child1.name == "Custom T-Shirt - Black - XL"

    child2 = Product.objects.filter(sku=39).first()
    assert child2.name == "Custom T-Shirt - Black - L"

    # Check stock counts
    assert supplier.get_stock_status(child1.pk).logical_count == Decimal(5)
    assert supplier.get_stock_status(child2.pk).logical_count == Decimal(10)

    path = os.path.join(os.path.dirname(__file__), "data", "product",
                        "product_sample_import_with_variations_update.xlsx")
    transformed_data = transform_file(filename.split(".")[1], path)

    importer = ProductImporter(
        transformed_data,
        ProductImporter.get_importer_context(rf.get("/"),
                                             shop=shop,
                                             language="en"))
    importer.process_data()

    assert len(importer.unmatched_fields) == 0

    importer.do_import(ImportMode.CREATE_UPDATE)
    products = importer.new_objects

    assert len(products) == 0

    updated_products = importer.updated_objects

    assert len(updated_products) == 4

    # Check product names
    child1 = Product.objects.filter(sku=10).first()
    assert child1.name == "T-Shirt - Pink - S"

    child2 = Product.objects.filter(sku=11).first()
    assert child2.name == "Test"

    # Check stock counts
    assert supplier.get_stock_status(child1.pk).logical_count == Decimal(5)
    assert supplier.get_stock_status(child2.pk).logical_count == Decimal(
        20)  # Did not add 20 but made the logical to 20

    parent2 = Product.objects.filter(sku=22).first()
    assert parent1.mode == ProductMode.VARIABLE_VARIATION_PARENT
    assert parent1.variation_children.all().count() == 20

    # Check product names
    child1 = Product.objects.filter(sku=38).first()
    assert child1.name == "Custom T-Shirt - Black - XL"

    child2 = Product.objects.filter(sku=39).first()
    assert child2.name == "Custom T-Shirt - Black - L"

    # Check stock counts
    assert supplier.get_stock_status(child1.pk).logical_count == Decimal(15)
    assert supplier.get_stock_status(child2.pk).logical_count == Decimal(10)

    # Test file with missing variations
    path = os.path.join(
        os.path.dirname(__file__), "data", "product",
        "product_sample_import_with_variations_missing_variables.xlsx")
    transformed_data = transform_file(filename.split(".")[1], path)

    importer = ProductImporter(
        transformed_data,
        ProductImporter.get_importer_context(rf.get("/"),
                                             shop=shop,
                                             language="en"))
    importer.process_data()

    assert len(importer.unmatched_fields) == 0

    importer.do_import(ImportMode.CREATE_UPDATE)
    products = importer.new_objects

    assert len(products) == 0

    updated_products = importer.updated_objects

    assert len(updated_products) == 4

    for log_message in importer.log_messages:
        assert "Parent SKU set for the row, but no variation" in log_message[
            "messages"][0]

    # check that both variation products still looks correct
    parent1 = Product.objects.filter(sku=1).first()
    assert parent1.mode == ProductMode.VARIABLE_VARIATION_PARENT
    assert parent1.variation_children.all().count() == 20

    parent2 = Product.objects.filter(sku=22).first()
    assert parent1.mode == ProductMode.VARIABLE_VARIATION_PARENT
    assert parent1.variation_children.all().count() == 20
Пример #42
0
def test_quick_add(browser, admin_user, live_server, settings):
    shop = get_default_shop()
    get_default_product_type()
    get_default_sales_unit()
    get_default_tax_class()
    initialize_admin_browser_test(browser, live_server, settings)

    url = reverse("shuup_admin:shop_product.new")
    browser.visit("%s%s" % (live_server, url))
    sku = "testsku"
    name = "Some product name"
    price_value = 10
    short_description = "short but gold"

    browser.fill("base-sku", sku)
    browser.fill("base-name__en", name)
    browser.fill("base-short_description__en", short_description)
    browser.fill("shop%s-default_price_value" % shop.pk, price_value)

    wait_until_appeared(
        browser,
        "#id_shop%d-primary_category ~ .quick-add-btn a.btn" % shop.id)
    click_element(
        browser,
        "#id_shop%d-primary_category ~ .quick-add-btn a.btn" % shop.id)
    wait_until_appeared(browser, "#create-object-iframe")

    with browser.get_iframe('create-object-iframe') as iframe:
        assert Category.objects.count() == 0
        wait_until_appeared(iframe, "input[name='base-name__en']")
        iframe.fill("base-name__en", "Test Category")
        time.sleep(
            3
        )  # Let's just wait here to the iFrame to open fully (for Chrome and headless)
        wait_until_appeared(iframe, "button[form='category_form']")
        click_element(browser, "button[form='category_form']")
        wait_until_condition(browser,
                             condition=lambda x: Category.objects.count() == 1,
                             timeout=20)

    assert Category.objects.first().name == "Test Category"

    # click to edit the button
    click_element(
        browser,
        "#id_shop%d-primary_category ~ .edit-object-btn a.btn" % shop.id)

    with browser.get_iframe('create-object-iframe') as iframe:
        wait_until_appeared(iframe, "input[name='base-name__en']")
        new_cat_name = "Changed Name"
        iframe.fill("base-name__en", new_cat_name)
        time.sleep(
            3
        )  # Let's just wait here to the iFrame to open fully (for Chrome and headless)
        wait_until_appeared(iframe, "button[form='category_form']")
        click_element(iframe, "button[form='category_form']")

    wait_until_condition(
        browser,
        condition=lambda x: Category.objects.first().name == new_cat_name,
        timeout=20)

    click_element(browser, "button[form='product_form']")
    wait_until_appeared(browser, "div[class='message success']")
Пример #43
0
def test_postalcodeshipping(class_spec):

    with override_settings(SHIPPING_SIMULATOR_CLASS_SPEC=class_spec):
        get_default_shop()
        product = get_default_product()

        clear_load_cache()

        carrier = CustomCarrier.objects.create(name="Kustom Karrier")
        service = carrier.create_service(None, enabled=True,
                               shop=get_default_shop(),
                               tax_class=get_default_tax_class(),
                               name="A Kustom Cervise",
                               description="Nice!")

        path = reverse("shuup:simulate-product-shipping")
        client = Client()

        data = {
            "product_id": product.id,
            "command": "add",
            "quantity": "1",
        }

        if class_spec.endswith("PostalCodeShippingSimulator"):
            data["postal_code"] = "37128482"

        elif class_spec.endswith("CityStateCountryShippingSimulator"):
            data["city"] = "Plumenau"
            data["region"] = "SC"
            data["country"] = "BR"

        # First, the method does not return any price. it must be free
        cost = get_default_shop().create_price(0.00)
        response = client.post(path, data)
        json_response = json.loads(response.content.decode("utf-8"))
        method = json_response["methods"][0]
        assert method["name"] == service.name
        assert method["description"] == service.description
        assert method["cost"] == cost.value
        assert method["formatted_cost"] == format_money(cost)
        assert method.get("time") is None

        # now lets add some extra price and time behavior
        service.behavior_components.add(ExpensiveSwedenBehaviorComponent.objects.create())

        cost = get_default_shop().create_price(1.00)
        duration = DurationRange(timedelta(days=5))

        with patch.object(ExpensiveSwedenBehaviorComponent, 'get_costs', return_value=[ServiceCost(cost)]):
            with patch.object(ExpensiveSwedenBehaviorComponent, 'get_delivery_time', return_value=duration):
                response = client.post(path, data)
                json_response = json.loads(response.content.decode("utf-8"))
                method = json_response["methods"][0]

                assert method["name"] == service.name
                assert method["description"] == service.description
                assert method["cost"] == cost.value
                assert method["formatted_cost"] == format_money(cost)
                assert method["time"]["min"] == duration.min_duration.days
                assert not method["time"]["formatted"] is None
                assert method["time"].get("max") is None

        # now with duration range time
        cost = get_default_shop().create_price(3.0)
        duration = DurationRange(timedelta(days=2), timedelta(days=8))

        with patch.object(ExpensiveSwedenBehaviorComponent, 'get_delivery_time', return_value=duration):
            with patch.object(ExpensiveSwedenBehaviorComponent, 'get_costs', return_value=[ServiceCost(cost)]):
                response = client.post(path, data)
                json_response = json.loads(response.content.decode("utf-8"))
                method = json_response["methods"][0]

                assert method["name"] == service.name
                assert method["description"] == service.description
                assert method["cost"] == cost.value
                assert method["formatted_cost"] == format_money(cost)

                assert method["time"]["min"] == duration.min_duration.days
                assert method["time"]["max"] == duration.max_duration.days


        # with suppier id
        data["supplier_id"] = get_default_supplier().pk
        response = client.post(path, data)
        json_response = json.loads(response.content.decode("utf-8"))
        method = json_response["methods"][0]
        assert method["name"] == service.name

        # with fractional quantity - internal error
        data["quantity"] = "1.321"
        response = client.post(path, data)
        assert response.status_code == 400

        # invalid quantity - internal error
        data["quantity"] = "1.,32.,1"
        response = client.post(path, data)
        assert response.status_code == 400

        # negative quantity - internal error
        data["quantity"] = "-1"
        response = client.post(path, data)
        assert response.status_code == 400

        # invalid form
        data = {"produt_id": product.id}
        response = client.post(path, data)
        assert json.loads(response.content.decode("utf-8")) == {}
Пример #44
0
def test_refresh_transaction_view(rf, admin_user):
    initialize()

    c = SmartClient()
    default_product = get_default_product()
    ORDER_TOTAL = PRODUCT_PRICE * 1

    basket_path = reverse("shuup:basket")
    c.post(basket_path,
           data={
               "command": "add",
               "product_id": default_product.pk,
               "quantity": 1,
               "supplier": get_default_supplier().pk
           })

    # Create methods
    shipping_method = get_default_shipping_method()
    processor = get_payment_provider()

    payment_method = processor.create_service(
        CIELO_SERVICE_CREDIT,
        identifier="cielo_phase_cc",
        shop=get_default_shop(),
        name="credit card",
        enabled=True,
        tax_class=get_default_tax_class())

    # Resolve paths
    addresses_path = reverse("shuup:checkout", kwargs={"phase": "addresses"})
    methods_path = reverse("shuup:checkout", kwargs={"phase": "methods"})
    payment_path = reverse("shuup:checkout", kwargs={"phase": "payment"})
    confirm_path = reverse("shuup:checkout", kwargs={"phase": "confirm"})
    transaction_path = reverse("shuup:cielo_make_transaction")

    # Phase: Addresses
    addresses_soup = c.soup(addresses_path)
    inputs = fill_address_inputs(addresses_soup, with_company=False)
    c.post(addresses_path, data=inputs)
    c.post(methods_path,
           data={
               "payment_method": payment_method.pk,
               "shipping_method": shipping_method.pk
           })

    c.get(confirm_path)

    tid = uuid.uuid4().hex

    transacao = get_in_progress_transaction(
        numero=1,
        valor=decimal_to_int_cents(ORDER_TOTAL),
        produto=CieloProduct.Credit,
        bandeira=CieloCardBrand.Visa,
        parcelas=CC_VISA_1X_INFO['installments'],
        tid=tid)
    transacao = get_approved_transaction(transacao)

    with patch.object(CieloRequest, 'autorizar', return_value=transacao):
        with patch.object(CieloRequest, 'consultar', return_value=transacao):
            c.soup(payment_path)
            c.post(transaction_path, CC_VISA_1X_INFO)
            confirm_soup = c.soup(confirm_path)
            c.post(confirm_path, data=extract_form_fields(confirm_soup))
            order = Order.objects.filter(payment_method=payment_method).first()
            process_payment_path = reverse("shuup:order_process_payment",
                                           kwargs={
                                               "pk": order.pk,
                                               "key": order.key
                                           })
            process_payment_return_path = reverse(
                "shuup:order_process_payment_return",
                kwargs={
                    "pk": order.pk,
                    "key": order.key
                })
            c.get(process_payment_path)
            c.get(process_payment_return_path)

    order.refresh_from_db()
    cielo_transaction = CieloTransaction.objects.get(
        order_transaction__order=order)

    # transacao nao capturada
    assert cielo_transaction.tid == tid
    assert cielo_transaction.total_captured.value == Decimal()

    view = load("shuup_cielo.admin.views.RefreshTransactionView").as_view()
    request = apply_request_middleware(rf.post("/"), user=admin_user)

    # request sem parametro - bad request
    response = view(request)
    assert response.status_code == 500

    transacao = get_captured_transaction(transacao)
    with patch.object(CieloRequest, 'consultar', return_value=transacao):
        request = apply_request_middleware(rf.post(
            "/", {"id": cielo_transaction.pk}),
                                           user=admin_user)
        response = view(request)
        assert response.status_code == 200
        cielo_transaction.refresh_from_db()
        assert cielo_transaction.total_captured_value == order.taxful_total_price_value
def test_refunds_report(rf):
    shop = get_default_shop()
    get_default_tax_class()
    creator = OrderCreator()

    source1 = seed_source()
    source2 = seed_source()
    source3 = seed_source()
    source4 = seed_source()

    order1 = creator.create_order(source1)
    order2 = creator.create_order(source2)
    order3 = creator.create_order(source3)
    order4 = creator.create_order(source4)

    # pay orders
    [o.create_payment(o.taxful_total_price) for o in Order.objects.all()]

    order1.create_full_refund()
    order2.create_refund([{
        "line":
        order2.lines.first(),
        "amount":
        order2.taxful_total_price.amount * Decimal(0.5),
        "quantity":
        1
    }])
    order3.create_refund([{
        "line":
        order3.lines.first(),
        "amount":
        order3.taxful_total_price.amount * Decimal(0.3),
        "quantity":
        1
    }])
    order4.create_refund([{
        "line":
        order4.lines.first(),
        "amount":
        order4.taxful_total_price.amount * Decimal(0.1),
        "quantity":
        1
    }])

    total_refunded = (order1.get_total_refunded_amount() +
                      order2.get_total_refunded_amount() +
                      order3.get_total_refunded_amount() +
                      order4.get_total_refunded_amount())

    data = {
        "report": RefundedSalesReport.get_name(),
        "shop": shop.pk,
        "date_range": DateRangeChoices.ALL_TIME,
        "writer": "json",
        "force_download": 1,
    }
    report = RefundedSalesReport(**data)
    writer = get_writer_instance(data["writer"])
    response = writer.get_response(report=report)
    if hasattr(response, "render"):
        response.render()
    json_data = json.loads(response.content.decode("utf-8"))
    assert force_text(RefundedSalesReport.title) in json_data.get("heading")
    data = json_data.get("tables")[0].get("data")
    assert len(data) == 1
    data = data[0]

    expected_data = {
        "refunded_orders": "4",
        "total_refunded": str(total_refunded.value)
    }

    for k, v in expected_data.items():
        assert data[k] == v
def test_shipping_report(rf):
    shop = get_default_shop()
    tax_class = get_default_tax_class()
    creator = OrderCreator()

    carrier1 = CustomCarrier.objects.create(name="Carrier1")
    sm1 = carrier1.create_service(None,
                                  shop=get_default_shop(),
                                  enabled=True,
                                  tax_class=tax_class,
                                  name="SM #1")
    sm1.behavior_components.add(
        FixedCostBehaviorComponent.objects.create(price_value=Decimal(10)))
    sm2 = carrier1.create_service(None,
                                  shop=get_default_shop(),
                                  enabled=True,
                                  tax_class=tax_class,
                                  name="SM #2")
    sm2.behavior_components.add(
        FixedCostBehaviorComponent.objects.create(price_value=Decimal(99)))
    sm2.behavior_components.add(
        FixedCostBehaviorComponent.objects.create(price_value=Decimal(4)))

    carrier2 = CustomCarrier.objects.create(name="Carrier2")
    sm3 = carrier2.create_service(None,
                                  shop=get_default_shop(),
                                  enabled=True,
                                  tax_class=tax_class,
                                  name="SM #3")
    sm3.behavior_components.add(
        FixedCostBehaviorComponent.objects.create(price_value=Decimal(5)))

    source1 = seed_source(sm1)
    source2 = seed_source(sm1)
    source3 = seed_source(sm2)
    source4 = seed_source(sm3)

    creator.create_order(source1)
    creator.create_order(source2)
    creator.create_order(source3)
    creator.create_order(source4)

    # pay orders
    [o.create_payment(o.taxful_total_price) for o in Order.objects.all()]

    data = {
        "report": ShippingReport.get_name(),
        "shop": shop.pk,
        "date_range": DateRangeChoices.ALL_TIME,
        "writer": "json",
        "force_download": 1,
    }
    report = ShippingReport(**data)
    writer = get_writer_instance(data["writer"])
    response = writer.get_response(report=report)
    if hasattr(response, "render"):
        response.render()
    json_data = json.loads(response.content.decode("utf-8"))
    assert force_text(ShippingReport.title) in json_data.get("heading")
    data = json_data.get("tables")[0].get("data")
    assert len(data) == 3

    expected_result = [
        {
            "carrier":
            carrier1.name,
            "shipping_method":
            sm1.name,
            "order_count":
            2,
            "total_charged":
            sum([bc.price_value
                 for bc in sm1.behavior_components.all()]) * 2  # 2 orders
        },
        {
            "carrier":
            carrier1.name,
            "shipping_method":
            sm2.name,
            "order_count":
            1,
            "total_charged":
            sum([bc.price_value for bc in sm2.behavior_components.all()])
        },
        {
            "carrier":
            carrier2.name,
            "shipping_method":
            sm3.name,
            "order_count":
            1,
            "total_charged":
            sum([bc.price_value for bc in sm3.behavior_components.all()])
        }
    ]

    for ix, shipping in enumerate(data):
        assert shipping["carrier"] == expected_result[ix]["carrier"]
        assert shipping["shipping_method"] == expected_result[ix][
            "shipping_method"]
        assert shipping["order_count"] == str(
            expected_result[ix]["order_count"])
        assert shipping["total_charged"] == str(
            expected_result[ix]["total_charged"].quantize(Decimal("0.01")))
Пример #47
0
def test_coupons_usage_report(rf):
    shop = get_default_shop()
    tax_class = get_default_tax_class()
    creator = OrderCreator()

    coupon1 = Coupon.objects.create(code="coupon1", active=True)
    coupon2 = Coupon.objects.create(code="coupon2", active=True)

    campaign1 = get_default_campaign(coupon1, "10")
    campaign2 = get_default_campaign(coupon2, "25")

    source1 = seed_source(coupon1)
    source2 = seed_source(coupon1)
    source3 = seed_source(coupon1)
    source4 = seed_source(coupon2)

    creator.create_order(source1)
    creator.create_order(source2)
    creator.create_order(source3)
    creator.create_order(source4)

    # pay orders
    [o.create_payment(o.taxful_total_price) for o in Order.objects.all()]

    data = {
        "report": CouponsUsageReport.get_name(),
        "shop": shop.pk,
        "date_range": DateRangeChoices.ALL_TIME,
        "writer": "json",
        "force_download": 1,
    }
    report = CouponsUsageReport(**data)
    writer = get_writer_instance(data["writer"])
    response = writer.get_response(report=report)
    if hasattr(response, "render"):
        response.render()
    json_data = json.loads(response.content.decode("utf-8"))
    assert force_text(CouponsUsageReport.title) in json_data.get("heading")
    data = json_data.get("tables")[0].get("data")
    assert len(data) == Order.objects.count()

    expected_data = []

    orders = Order.objects.all().order_by("order_date")
    for order in orders:
        discount = order.shop.create_price(0)
        for dt in order.lines.discounts():
            discount += dt.taxful_price

        expected_data.append({
            "date":
            format_date(order.order_date, locale=get_current_babel_locale()),
            "coupon":
            order.codes[0],
            "order":
            str(order),
            "taxful_total":
            str(order.taxful_total_price.as_rounded().value),
            "taxful_subtotal":
            str((order.taxful_total_price - discount).as_rounded().value),
            "total_discount":
            str(discount.as_rounded().value)
        })

    assert len(expected_data) == len(data)

    for ix, d in enumerate(data):
        for k, v in d.items():
            assert expected_data[ix][k] == v
Пример #48
0
def test_sample_import_all_match(filename):
    activate("en")
    shop = get_default_shop()
    tax_class = get_default_tax_class()
    product_type = get_default_product_type()
    sales_unit = get_default_sales_unit()

    path = os.path.join(os.path.dirname(__file__), "data", "product", filename)
    if filename == bom_file:
        import codecs
        bytes = min(32, os.path.getsize(path))
        raw = open(path, 'rb').read(bytes)
        assert raw.startswith(codecs.BOM_UTF8)

    transformed_data = transform_file(filename.split(".")[1], path)
    importer = ProductImporter(transformed_data, shop, "en")
    importer.process_data()

    if filename == images_file:
        assert len(importer.unmatched_fields) == 2
        _create_random_media_file(shop, "image1.jpeg")
        _create_random_media_file(shop, "products/images/image2.jpeg")
        _create_random_media_file(shop, "products/images/image3.jpeg")
        _create_random_media_file(shop, "image4.jpeg")
        _create_random_media_file(shop, "products2/images/image5.jpeg")
        _create_random_media_file(shop, "product1.jpeg")
        _create_random_media_file(shop, "products/images/product2.jpeg")
        _create_random_media_file(shop, "products/images2/product2.jpeg")
    else:
        assert len(importer.unmatched_fields) == 0

    importer.do_import(ImportMode.CREATE_UPDATE)
    products = importer.new_objects

    if filename == images_file:
        assert len(products) == 3
    else:
        assert len(products) == 2

    for product in products:
        shop_product = product.get_shop_instance(shop)
        assert shop_product.pk
        assert shop_product.default_price_value == 150
        assert shop_product.default_price == shop.create_price(150)
        assert product.type == product_type  # product type comes from importer defaults
        assert product.sales_unit == sales_unit

        if product.pk == 1:
            assert product.tax_class.pk == 2  # new was created
            assert product.name == "Product English"
            assert product.description == "Description English"

            if filename == images_file:
                assert product.media.count() == 3
        elif product.pk == 2:
            assert product.tax_class.pk == tax_class.pk  # old was found as should
            assert product.name == "Product 2 English"
            assert product.description == "Description English 2"

            if filename == images_file:
                assert product.media.count() == 2
        elif product.pk == 3 and filename == images_file:
            assert product.media.count() == 3

        assert shop_product.primary_category.pk == 1
        assert [c.pk for c in shop_product.categories.all()] == [1, 2]