コード例 #1
0
def add_product_to_order(order,
                         supplier,
                         product,
                         quantity,
                         taxless_base_unit_price,
                         tax_rate=0,
                         pricing_context=None):
    if not pricing_context:
        pricing_context = _get_pricing_context(order.shop, order.customer)
    product_order_line = OrderLine(order=order)
    update_order_line_from_product(pricing_context,
                                   order_line=product_order_line,
                                   product=product,
                                   quantity=quantity,
                                   supplier=supplier)
    base_unit_price = order.shop.create_price(taxless_base_unit_price)
    if order.prices_include_tax:
        base_unit_price *= 1 + tax_rate
    product_order_line.base_unit_price = order.shop.create_price(
        base_unit_price)
    product_order_line.save()

    taxes = [get_test_tax(tax_rate)]
    price = quantity * base_unit_price
    taxed_price = stacked_value_added_taxes(price, taxes)
    order_line_tax = OrderLineTax.from_tax(
        taxes[0],
        taxed_price.taxless.amount,
        order_line=product_order_line,
    )
    order_line_tax.save(
    )  # Save order line tax before linking to order_line.taxes
    product_order_line.taxes.add(order_line_tax)
コード例 #2
0
ファイル: test_orders.py プロジェクト: rrosajp/shuup
def test_cannot_ship_basic_order_without_supplier_module():
    PRODUCTS_TO_SEND = 10
    product = get_default_product()
    supplier = get_default_supplier()
    supplier.supplier_modules.set([])
    supplier.stock_managed = False
    supplier.save()
    order = create_order_with_product(product,
                                      supplier=supplier,
                                      quantity=PRODUCTS_TO_SEND,
                                      taxless_base_unit_price=10,
                                      tax_rate=Decimal("0.5"))
    assert order.shop.prices_include_tax is False
    price = order.shop.create_price
    currency = order.currency

    discount_order_line = OrderLine(order=order,
                                    quantity=1,
                                    type=OrderLineType.OTHER)
    discount_order_line.discount_amount = price(30)
    assert discount_order_line.price == price(-30)
    discount_order_line.save()

    order.cache_prices()
    order.check_all_verified()
    order.save()
    assert order.taxful_total_price == TaxfulPrice(
        PRODUCTS_TO_SEND * (10 + 5) - 30, currency)
    with pytest.raises(SupplierHasNoSupplierModules):
        shipment = order.create_shipment_of_all_products(supplier=supplier)
コード例 #3
0
def test_rounding(prices):
    expected = 0
    for p in prices:
        expected += bankers_round(p, 2)

    order = create_empty_order(prices_include_tax=False)
    order.save()
    currency = order.shop.currency
    for x, price in enumerate(prices):
        ol = OrderLine(order=order,
                       type=OrderLineType.OTHER,
                       quantity=1,
                       text="Thing",
                       ordering=x,
                       base_unit_price=order.shop.create_price(price))
        ol.save()
    order.cache_prices()
    for x, order_line in enumerate(order.lines.all().order_by("ordering")):
        price = Decimal(prices[x]).quantize(Decimal(".1")**9)

        # make sure prices are in database with original precision
        assert order_line.base_unit_price == order.shop.create_price(price)

        # make sure the line taxless price is rounded
        assert order_line.taxless_price == order.shop.create_price(
            bankers_round(price, 2))

        # make sure the line price is rounded
        assert order_line.price == order.shop.create_price(price)

    # make sure order total is rounded
    assert order.taxless_total_price == order.shop.create_price(
        bankers_round(expected, 2))
コード例 #4
0
def add_product_to_order(order,
                         supplier,
                         product,
                         quantity,
                         taxless_base_unit_price,
                         tax_rate=0,
                         pricing_context=None):
    if not pricing_context:
        pricing_context = _get_pricing_context(order.shop, order.customer)
    product_order_line = OrderLine(order=order)
    update_order_line_from_product(pricing_context,
                                   order_line=product_order_line,
                                   product=product,
                                   quantity=quantity,
                                   supplier=supplier)
    base_unit_price = order.shop.create_price(taxless_base_unit_price)
    if order.prices_include_tax:
        base_unit_price *= (1 + tax_rate)
    product_order_line.base_unit_price = order.shop.create_price(
        base_unit_price)
    product_order_line.save()

    order_line_tax = OrderLineTax.from_tax(
        get_test_tax(tax_rate),
        Money(quantity * taxless_base_unit_price, order.currency),
        order_line=product_order_line,
    )
    order_line_tax.save(
    )  # Save order line tax before linking to order_line.taxes
    product_order_line.taxes.add(order_line_tax)
コード例 #5
0
ファイル: test_orders.py プロジェクト: myciek/shuup
def test_basic_order_without_supplier_module():
    PRODUCTS_TO_SEND = 10
    product = get_default_product()
    supplier = get_default_supplier()
    supplier.supplier_modules.set([])
    supplier.stock_managed = False
    supplier.save()
    order = create_order_with_product(product,
                                      supplier=supplier,
                                      quantity=PRODUCTS_TO_SEND,
                                      taxless_base_unit_price=10,
                                      tax_rate=Decimal("0.5"))
    assert order.shop.prices_include_tax is False
    price = order.shop.create_price
    currency = order.currency

    discount_order_line = OrderLine(order=order,
                                    quantity=1,
                                    type=OrderLineType.OTHER)
    discount_order_line.discount_amount = price(30)
    assert discount_order_line.price == price(-30)
    discount_order_line.save()

    order.cache_prices()
    order.check_all_verified()
    order.save()
    assert order.taxful_total_price == TaxfulPrice(
        PRODUCTS_TO_SEND * (10 + 5) - 30, currency)
    shipment = order.create_shipment_of_all_products(supplier=supplier)
    assert shipment.total_products == 0
    assert shipment.weight == 0
    assert PRODUCTS_TO_SEND == int(
        order.get_unshipped_products()[product.id]["unshipped"])

    order.create_payment(order.taxful_total_price)
    assert order.payments.exists(), "A payment was created"
    with pytest.raises(NoPaymentToCreateException):
        order.create_payment(Money(6, currency))
    assert order.is_paid(), "Order got paid"
    assert not order.can_set_complete(), "Finalization is possible"

    # Force to be complete
    order.change_status(next_status=OrderStatus.objects.get_default_complete(),
                        save=False)
    assert order.is_complete(), "Finalization done"

    summary = order.get_tax_summary()
    assert len(summary) == 2
    assert summary[0].tax_rate * 100 == 50
    assert summary[0].based_on == Money(100, currency)
    assert summary[0].tax_amount == Money(50, currency)
    assert summary[0].taxful == summary[0].based_on + summary[0].tax_amount
    assert summary[1].tax_id is None
    assert summary[1].tax_code == ""
    assert summary[1].tax_amount == Money(0, currency)
    assert summary[1].tax_rate == 0
    assert order.get_total_tax_amount() == Money(50, currency)
コード例 #6
0
def test_refunds_for_discounted_order_lines():
    shop = get_default_shop()
    supplier = get_default_supplier()
    product = create_product(
        "test-sku",
        shop=get_default_shop(),
        default_price=10,
        stock_behavior=StockBehavior.STOCKED
    )

    order = create_order_with_product(product, supplier, 2, 200, shop=shop)
    discount_line = OrderLine(type=OrderLineType.DISCOUNT, quantity=1, discount_amount_value=Decimal("0.54321"))
    order.lines.add(discount_line)

    product_line = order.lines.filter(type=OrderLineType.PRODUCT).first()
    product_line.discount_amount = TaxfulPrice(100, order.currency)
    product_line.save()
    taxful_price_with_discount = product_line.taxful_price
    order.cache_prices()
    order.save()

    assert product_line.base_price == TaxfulPrice(400, order.currency)
    assert taxful_price_with_discount == TaxfulPrice(300, order.currency)

    # try to refund only the product line - should fail since this would result in a negative total
    with pytest.raises(RefundExceedsAmountException):
        order.create_refund([{"line": product_line, "quantity": 2, "amount": taxful_price_with_discount.amount}])

    # try to refund the product line with a negative amount
    with pytest.raises(InvalidRefundAmountException):
        order.create_refund([{"line": product_line, "quantity": 1, "amount": -taxful_price_with_discount.amount}])
    # try to refund the discount line with a positive amount
    with pytest.raises(InvalidRefundAmountException):
        order.create_refund([{"line": discount_line, "quantity": 1, "amount": -discount_line.taxful_price.amount}])

    order.create_refund([
        {"line": discount_line, "quantity": 1, "amount": discount_line.taxful_price.amount},
        {"line": product_line, "quantity": 2, "amount": taxful_price_with_discount.amount}
    ])
    assert product_line.max_refundable_amount.value == 0
    assert discount_line.max_refundable_amount.value == 0
    assert order.taxful_total_price.value == 0

    order = create_order_with_product(product, supplier, 2, 200, shop=shop)
    discount_line = OrderLine(type=OrderLineType.DISCOUNT, quantity=1, discount_amount_value=Decimal("0.54321"))
    order.lines.add(discount_line)
    product_line = order.lines.filter(type=OrderLineType.PRODUCT).first()
    product_line.discount_amount = TaxfulPrice(100, order.currency)
    product_line.save()
    order.cache_prices()
    order.save()

    order.create_full_refund(restock_products=False)
    assert order.taxful_total_price.value == 0
コード例 #7
0
def test_broken_order_lines():
    with pytest.raises(ValidationError):
        OrderLine(type=OrderLineType.PRODUCT).save()

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

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

    with pytest.raises(ValidationError):
        OrderLine(product=get_default_product(), type=OrderLineType.OTHER, tax_rate=3).save()
コード例 #8
0
ファイル: test_orders.py プロジェクト: zorkhax/shuup
def test_basic_order():
    PRODUCTS_TO_SEND = 10
    product = get_default_product()
    supplier = get_default_supplier()
    order = create_order_with_product(product,
                                      supplier=supplier,
                                      quantity=PRODUCTS_TO_SEND,
                                      taxless_base_unit_price=10,
                                      tax_rate=Decimal("0.5"))
    assert order.shop.prices_include_tax is False
    price = order.shop.create_price
    currency = order.currency

    discount_order_line = OrderLine(order=order,
                                    quantity=1,
                                    type=OrderLineType.OTHER)
    discount_order_line.discount_amount = price(30)
    assert discount_order_line.price == price(-30)
    discount_order_line.save()

    order.cache_prices()
    order.check_all_verified()
    order.save()
    assert order.taxful_total_price == TaxfulPrice(
        PRODUCTS_TO_SEND * (10 + 5) - 30, currency)
    shipment = order.create_shipment_of_all_products(supplier=supplier)
    assert shipment.total_products == PRODUCTS_TO_SEND, "All products were shipped"
    assert shipment.weight == product.gross_weight * PRODUCTS_TO_SEND / 1000, "Gravity works"
    assert not order.get_unshipped_products(
    ), "Nothing was left in the warehouse"
    order.shipping_status = ShippingStatus.FULLY_SHIPPED
    order.create_payment(order.taxful_total_price)
    assert order.payments.exists(), "A payment was created"
    with pytest.raises(NoPaymentToCreateException):
        order.create_payment(Money(6, currency))
    assert order.is_paid(), "Order got paid"
    assert order.can_set_complete(), "Finalization is possible"
    order.status = OrderStatus.objects.get_default_complete()
    assert order.is_complete(), "Finalization done"

    summary = order.get_tax_summary()
    assert len(summary) == 2
    assert summary[0].tax_rate * 100 == 50
    assert summary[0].based_on == Money(100, currency)
    assert summary[0].tax_amount == Money(50, currency)
    assert summary[0].taxful == summary[0].based_on + summary[0].tax_amount
    assert summary[1].tax_id is None
    assert summary[1].tax_code == ''
    assert summary[1].tax_amount == Money(0, currency)
    assert summary[1].tax_rate == 0
    assert order.get_total_tax_amount() == Money(50, currency)
コード例 #9
0
ファイル: test_orders.py プロジェクト: ruqaiya/shuup
def test_basic_order():
    PRODUCTS_TO_SEND = 10
    product = get_default_product()
    supplier = get_default_supplier()
    order = create_order_with_product(
        product,
        supplier=supplier,
        quantity=PRODUCTS_TO_SEND,
        taxless_base_unit_price=10,
        tax_rate=Decimal("0.5")
    )
    assert order.shop.prices_include_tax is False
    price = order.shop.create_price
    currency = order.currency

    discount_order_line = OrderLine(order=order, quantity=1, type=OrderLineType.OTHER)
    discount_order_line.discount_amount = price(30)
    assert discount_order_line.price == price(-30)
    discount_order_line.save()

    order.cache_prices()
    order.check_all_verified()
    order.save()
    assert order.taxful_total_price == TaxfulPrice(PRODUCTS_TO_SEND * (10 + 5) - 30, currency)
    shipment = order.create_shipment_of_all_products(supplier=supplier)
    assert shipment.total_products == PRODUCTS_TO_SEND, "All products were shipped"
    assert shipment.weight == product.gross_weight * PRODUCTS_TO_SEND / 1000, "Gravity works"
    assert not order.get_unshipped_products(), "Nothing was left in the warehouse"
    order.shipping_status = ShippingStatus.FULLY_SHIPPED
    order.create_payment(order.taxful_total_price)
    assert order.payments.exists(), "A payment was created"
    with pytest.raises(NoPaymentToCreateException):
        order.create_payment(Money(6, currency))
    assert order.is_paid(), "Order got paid"
    assert order.can_set_complete(), "Finalization is possible"
    order.status = OrderStatus.objects.get_default_complete()
    assert order.is_complete(), "Finalization done"

    summary = order.get_tax_summary()
    assert len(summary) == 2
    assert summary[0].tax_rate * 100 == 50
    assert summary[0].based_on == Money(100, currency)
    assert summary[0].tax_amount == Money(50, currency)
    assert summary[0].taxful == summary[0].based_on + summary[0].tax_amount
    assert summary[1].tax_id is None
    assert summary[1].tax_code == ''
    assert summary[1].tax_amount == Money(0, currency)
    assert summary[1].tax_rate == 0
    assert order.get_total_tax_amount() == Money(50, currency)
コード例 #10
0
ファイル: factories.py プロジェクト: ahmadzai/shuup
def add_product_to_order(order, supplier, product, quantity, taxless_base_unit_price, tax_rate=0, pricing_context=None):
    if not pricing_context:
        pricing_context = _get_pricing_context(order.shop, order.customer)
    product_order_line = OrderLine(order=order)
    update_order_line_from_product(pricing_context,
                                   order_line=product_order_line,
                                   product=product, quantity=quantity,
                                   supplier=supplier)
    product_order_line.base_unit_price = order.shop.create_price(taxless_base_unit_price)
    product_order_line.save()
    product_order_line.taxes.add(OrderLineTax.from_tax(
        get_test_tax(tax_rate),
        product_order_line.taxless_price.amount,
        order_line=product_order_line,
    ))
コード例 #11
0
def test_order_refunds_with_other_lines(rf, admin_user):
    shop = get_default_shop()
    supplier = get_default_supplier()
    supplier.shops.add(shop)

    product = create_product("sku", shop=shop, default_price=10)
    shop_product = product.get_shop_instance(shop=shop)
    shop_product.suppliers = [supplier]

    order = create_empty_order(shop=shop)
    order.full_clean()
    order.save()

    add_product_to_order(order, supplier, product, 4, 5)

    # Lines without quantity shouldn't affect refunds
    other_line = OrderLine(order=order,
                           type=OrderLineType.OTHER,
                           text="This random line for textual information",
                           quantity=0)
    other_line.save()
    order.lines.add(other_line)

    # Lines with quantity again should be able to be refunded normally.
    other_line_with_quantity = OrderLine(order=order,
                                         type=OrderLineType.OTHER,
                                         text="Special service 100$/h",
                                         quantity=1,
                                         base_unit_price_value=100)
    other_line_with_quantity.save()
    order.lines.add(other_line_with_quantity)

    assert other_line_with_quantity.max_refundable_quantity == 1
    assert other_line_with_quantity.max_refundable_amount.value == 100

    order.cache_prices()
    order.create_payment(order.taxful_total_price)
    assert order.is_paid()
    assert order.taxful_total_price_value == 120  # 100 + 4 * 20

    def get_refund_view_content():
        request = apply_request_middleware(rf.get("/"), user=admin_user)
        view = OrderCreateRefundView.as_view()
        response = view(request, pk=order.pk)
        return BeautifulSoup(response.render().content)

    refund_soup = get_refund_view_content()
    refund_options = refund_soup.find(
        id="id_form-0-line_number").findAll("option")
    assert len(
        refund_options) == 4  # 1 empty line, 1 for arbitrary and 2 for lines
    assert len([
        option for option in refund_options
        if "Special service 100$/h" in force_text(option)
    ]) == 1
コード例 #12
0
ファイル: factories.py プロジェクト: hrayr-artunyan/shuup
def add_product_to_order(order, supplier, product, quantity, taxless_base_unit_price, tax_rate=0, pricing_context=None):
    if not pricing_context:
        pricing_context = _get_pricing_context(order.shop, order.customer)
    product_order_line = OrderLine(order=order)
    update_order_line_from_product(pricing_context,
                                   order_line=product_order_line,
                                   product=product, quantity=quantity,
                                   supplier=supplier)
    base_unit_price = order.shop.create_price(taxless_base_unit_price)
    if order.prices_include_tax:
        base_unit_price *= (1 + tax_rate)
    product_order_line.base_unit_price = order.shop.create_price(base_unit_price)
    product_order_line.save()
    product_order_line.taxes.add(OrderLineTax.from_tax(
        get_test_tax(tax_rate),
        Money(quantity * taxless_base_unit_price, order.currency),
        order_line=product_order_line,
    ))
コード例 #13
0
def _get_order_line(request):
    order = Order(
        shop=request.shop,
        currency=request.shop.currency,
        prices_include_tax=request.shop.prices_include_tax,
    )
    pi = _get_price_info(request.shop, Product(sku='6.0745'), quantity=2)
    return OrderLine(
        order=order,
        base_unit_price=pi.base_unit_price,
        discount_amount=pi.discount_amount,
        quantity=pi.quantity,
    )
コード例 #14
0
ファイル: test_orders.py プロジェクト: millujye/shuup
def test_line_discount():
    order = create_empty_order(prices_include_tax=False)
    order.save()
    currency = order.shop.currency
    ol = OrderLine(
        order=order,
        type=OrderLineType.OTHER,
        quantity=5,
        text="Thing"
    )
    ol.discount_amount = order.shop.create_price(50)
    ol.base_unit_price = order.shop.create_price(40)
    ol.save()
    ol.taxes.add(OrderLineTax.from_tax(
        get_default_tax(), ol.taxless_price.amount, order_line=ol))
    assert ol.taxless_discount_amount == order.shop.create_price(50)
    assert ol.taxful_discount_amount == TaxfulPrice(75, currency)
    assert ol.taxless_price == order.shop.create_price(150)
    assert ol.taxful_price == TaxfulPrice(150 + 75, currency)
    assert ol.taxless_base_unit_price == order.shop.create_price(40)
    assert ol.taxful_base_unit_price == TaxfulPrice(60, currency)
    assert "Thing" in six.text_type(ol)
コード例 #15
0
ファイル: test_orders.py プロジェクト: suutari/shoop
def test_refunds_for_discounted_order_lines():
    shop = get_default_shop()
    supplier = get_default_supplier()
    product = create_product(
        "test-sku",
        shop=get_default_shop(),
        default_price=10,
        stock_behavior=StockBehavior.STOCKED
    )

    order = create_order_with_product(product, supplier, 2, 200, shop=shop)
    discount_line = OrderLine(
        order_id=order.id, type=OrderLineType.DISCOUNT, quantity=1, discount_amount_value=Decimal("0.54321"))
    discount_line.save()
    order.lines.add(discount_line)

    product_line = order.lines.filter(type=OrderLineType.PRODUCT).first()
    product_line.discount_amount = TaxfulPrice(100, order.currency)
    product_line.save()
    taxful_price_with_discount = product_line.taxful_price
    order.cache_prices()
    order.save()

    assert product_line.base_price == TaxfulPrice(400, order.currency)
    assert taxful_price_with_discount == TaxfulPrice(300, order.currency)

    # try to refund only the product line - should fail since this would result in a negative total
    with pytest.raises(RefundExceedsAmountException):
        order.create_refund([{"line": product_line, "quantity": 2, "amount": taxful_price_with_discount.amount}])

    # try to refund the product line with a negative amount
    with pytest.raises(InvalidRefundAmountException):
        order.create_refund([{"line": product_line, "quantity": 1, "amount": -taxful_price_with_discount.amount}])
    # try to refund the discount line with a positive amount
    with pytest.raises(InvalidRefundAmountException):
        order.create_refund([{"line": discount_line, "quantity": 1, "amount": -discount_line.taxful_price.amount}])

    order.create_refund([
        {"line": discount_line, "quantity": 1, "amount": discount_line.taxful_price.amount},
        {"line": product_line, "quantity": 2, "amount": taxful_price_with_discount.amount}
    ])
    assert product_line.max_refundable_amount.value == 0
    assert discount_line.max_refundable_amount.value == 0
    assert order.taxful_total_price.value == 0

    order = create_order_with_product(product, supplier, 2, 200, shop=shop)
    discount_line = OrderLine(
        order_id=order.id, type=OrderLineType.DISCOUNT, quantity=1, discount_amount_value=Decimal("0.54321"))
    discount_line.save()
    order.lines.add(discount_line)
    product_line = order.lines.filter(type=OrderLineType.PRODUCT).first()
    product_line.discount_amount = TaxfulPrice(100, order.currency)
    product_line.save()
    order.cache_prices()
    order.save()

    order.create_full_refund(restock_products=False)
    assert order.taxful_total_price.value == 0
コード例 #16
0
ファイル: _creator.py プロジェクト: wsmoyer/shuup
    def create_package_children(self, order_line):
        order = order_line.order
        parent_product = order_line.product
        # :type parent_product: shuup.core.models.Product
        if not (parent_product and parent_product.is_package_parent()):
            return

        child_to_quantity = parent_product.get_package_child_to_quantity_map()
        for (child_product, child_quantity) in child_to_quantity.items():
            child_order_line = OrderLine(order=order, parent_line=order_line)
            update_order_line_from_product(
                pricing_context=None,  # Will use zero price
                order_line=child_order_line,
                product=child_product,
                quantity=(order_line.quantity * child_quantity),
            )
            # Package children are free
            assert child_order_line.base_unit_price.value == 0
            child_order_line.source_line = None
            child_order_line.parent_source_line = order_line.source_line
            child_order_line.supplier = order_line.supplier
            self._check_orderability(child_order_line)
            yield child_order_line
コード例 #17
0
ファイル: _creator.py プロジェクト: ruqaiya/shuup
    def create_package_children(self, order_line):
        order = order_line.order
        parent_product = order_line.product
        # :type parent_product: shuup.core.models.Product
        if not (parent_product and parent_product.is_package_parent()):
            return

        child_to_quantity = parent_product.get_package_child_to_quantity_map()
        for (child_product, child_quantity) in child_to_quantity.items():
            child_order_line = OrderLine(order=order, parent_line=order_line)
            update_order_line_from_product(
                pricing_context=None,  # Will use zero price
                order_line=child_order_line,
                product=child_product,
                quantity=(order_line.quantity * child_quantity),
            )
            # Package children are free
            assert child_order_line.base_unit_price.value == 0
            child_order_line.source_line = None
            child_order_line.parent_source_line = order_line.source_line
            child_order_line.supplier = order_line.supplier
            self._check_orderability(child_order_line)
            yield child_order_line
コード例 #18
0
ファイル: test_price_display.py プロジェクト: sid10on10/shuup
def _get_order_and_order_line(request):
    order = Order(
        shop=request.shop,
        currency=request.shop.currency,
        prices_include_tax=request.shop.prices_include_tax,
    )
    order.taxful_total_price = TaxfulPrice("100", request.shop.currency)
    order.taxless_total_price = TaxlessPrice("50", request.shop.currency)
    pi = _get_price_info(request.shop, Product(sku='6.0745'), quantity=2)
    return (order, OrderLine(
        order=order,
        base_unit_price=pi.base_unit_price,
        discount_amount=pi.discount_amount,
        quantity=pi.quantity,
    ))
コード例 #19
0
ファイル: test_rounding.py プロジェクト: ruqaiya/shuup
def test_rounding(prices):
    expected = 0
    for p in prices:
        expected += bankers_round(p, 2)

    order = create_empty_order(prices_include_tax=False)
    order.save()
    for x, price in enumerate(prices):
        ol = OrderLine(
            order=order,
            type=OrderLineType.OTHER,
            quantity=1,
            text="Thing",
            ordering=x,
            base_unit_price=order.shop.create_price(price)
        )
        ol.save()
    order.cache_prices()
    for x, order_line in enumerate(order.lines.all().order_by("ordering")):
        price = Decimal(prices[x]).quantize(Decimal(".1") ** 9)

        # make sure prices are in database with original precision
        assert order_line.base_unit_price == order.shop.create_price(price)

        # make sure the line taxless price is rounded
        assert order_line.taxless_price == order.shop.create_price(bankers_round(price, 2))

        # Check that total prices calculated from priceful parts still matches
        assert _get_taxless_price(order_line) == order_line.taxless_price
        assert _get_taxful_price(order_line) == order_line.taxful_price

        # make sure the line price is rounded
        assert order_line.price == order.shop.create_price(price)

    # make sure order total is rounded
    assert order.taxless_total_price == order.shop.create_price(bankers_round(expected, 2))
コード例 #20
0
ファイル: factories.py プロジェクト: dragonsg/shuup-1
def add_product_to_order(order,
                         supplier,
                         product,
                         quantity,
                         taxless_base_unit_price,
                         tax_rate=0,
                         pricing_context=None):
    if not pricing_context:
        pricing_context = _get_pricing_context(order.shop, order.customer)
    product_order_line = OrderLine(order=order)
    update_order_line_from_product(pricing_context,
                                   order_line=product_order_line,
                                   product=product,
                                   quantity=quantity,
                                   supplier=supplier)
    product_order_line.base_unit_price = order.shop.create_price(
        taxless_base_unit_price)
    product_order_line.save()
    product_order_line.taxes.add(
        OrderLineTax.from_tax(
            get_test_tax(tax_rate),
            product_order_line.taxless_price.amount,
            order_line=product_order_line,
        ))
コード例 #21
0
ファイル: factories.py プロジェクト: suutari-ai/shuup
def add_product_to_order(order, supplier, product, quantity, taxless_base_unit_price, tax_rate=0, pricing_context=None):
    if not pricing_context:
        pricing_context = _get_pricing_context(order.shop, order.customer)
    product_order_line = OrderLine(order=order)
    update_order_line_from_product(pricing_context,
                                   order_line=product_order_line,
                                   product=product, quantity=quantity,
                                   supplier=supplier)
    base_unit_price = order.shop.create_price(taxless_base_unit_price)
    if order.prices_include_tax:
        base_unit_price *= (1 + tax_rate)
    product_order_line.base_unit_price = order.shop.create_price(base_unit_price)
    product_order_line.save()

    taxes = [get_test_tax(tax_rate)]
    price = quantity * base_unit_price
    taxed_price = stacked_value_added_taxes(price, taxes)
    order_line_tax = OrderLineTax.from_tax(
        taxes[0],
        taxed_price.taxless.amount,
        order_line=product_order_line,
    )
    order_line_tax.save()  # Save order line tax before linking to order_line.taxes
    product_order_line.taxes.add(order_line_tax)
コード例 #22
0
def test_order_refunds_with_other_lines():
    shop = get_default_shop()
    supplier = Supplier.objects.create(identifier="1", name="supplier1")
    supplier.shops.add(shop)

    product = create_product("sku", shop=shop, default_price=10)
    shop_product = product.get_shop_instance(shop=shop)
    shop_product.suppliers.set([supplier])

    order = create_empty_order(shop=shop)
    order.full_clean()
    order.save()

    add_product_to_order(order, supplier, product, 4, 5)

    # Lines without quantity shouldn't affect refunds
    other_line = OrderLine(order=order,
                           type=OrderLineType.OTHER,
                           text="This random line for textual information",
                           quantity=0)
    other_line.save()
    order.lines.add(other_line)

    # Lines with quantity again should be able to be refunded normally.
    other_line_with_quantity = OrderLine(order=order,
                                         type=OrderLineType.OTHER,
                                         text="Special service 100$/h",
                                         quantity=1,
                                         base_unit_price_value=100)
    other_line_with_quantity.save()
    order.lines.add(other_line_with_quantity)

    assert other_line_with_quantity.max_refundable_quantity == 1
    assert other_line_with_quantity.max_refundable_amount.value == 100

    order.cache_prices()
    order.create_payment(order.taxful_total_price)
    assert order.is_paid()
    assert order.taxful_total_price_value == 120  # 100 + 4 * 20

    order.create_full_refund()
    assert order.taxful_total_price_value == 0
コード例 #23
0
def test_line_discount_more():
    order = create_empty_order()
    order.save()
    ol = OrderLine(order=order, type=OrderLineType.OTHER)
    ol.quantity = 5
    ol.base_unit_price = order.shop.create_price(30)
    ol.discount_amount = order.shop.create_price(50)
    ol.save()
    currency = order.shop.currency
    assert ol.taxless_base_unit_price == TaxlessPrice(30, currency)
    assert ol.taxless_discount_amount == TaxlessPrice(50, currency)
    assert ol.taxless_price == TaxlessPrice(5 * 30 - 50, currency)
    ol.taxes.add(OrderLineTax.from_tax(
        get_default_tax(), ol.taxless_price.amount, order_line=ol))
    assert ol.taxless_discount_amount == TaxlessPrice(50, currency)
    assert ol.taxful_discount_amount == TaxfulPrice(75, currency)
    assert ol.taxless_price == TaxlessPrice(100, currency)
    assert ol.taxful_price == TaxfulPrice(150, currency)
    assert ol.taxless_base_unit_price == TaxlessPrice(30, currency)
    assert ol.taxful_base_unit_price == TaxfulPrice(45, currency)
コード例 #24
0
ファイル: test_orders.py プロジェクト: millujye/shuup
def test_line_discount_more():
    order = create_empty_order()
    order.save()
    ol = OrderLine(order=order, type=OrderLineType.OTHER)
    ol.quantity = 5
    ol.base_unit_price = order.shop.create_price(30)
    ol.discount_amount = order.shop.create_price(50)
    ol.save()
    currency = order.shop.currency
    assert ol.taxless_base_unit_price == TaxlessPrice(30, currency)
    assert ol.taxless_discount_amount == TaxlessPrice(50, currency)
    assert ol.taxless_price == TaxlessPrice(5 * 30 - 50, currency)
    ol.taxes.add(OrderLineTax.from_tax(
        get_default_tax(), ol.taxless_price.amount, order_line=ol))
    assert ol.taxless_discount_amount == TaxlessPrice(50, currency)
    assert ol.taxful_discount_amount == TaxfulPrice(75, currency)
    assert ol.taxless_price == TaxlessPrice(100, currency)
    assert ol.taxful_price == TaxfulPrice(150, currency)
    assert ol.taxless_base_unit_price == TaxlessPrice(30, currency)
    assert ol.taxful_base_unit_price == TaxfulPrice(45, currency)
コード例 #25
0
def test_line_discount():
    order = create_empty_order(prices_include_tax=False)
    order.save()
    currency = order.shop.currency
    ol = OrderLine(
        order=order,
        type=OrderLineType.OTHER,
        quantity=5,
        text="Thing"
    )
    ol.discount_amount = order.shop.create_price(50)
    ol.base_unit_price = order.shop.create_price(40)
    ol.save()
    ol.taxes.add(OrderLineTax.from_tax(
        get_default_tax(), ol.taxless_price.amount, order_line=ol))
    assert ol.taxless_discount_amount == order.shop.create_price(50)
    assert ol.taxful_discount_amount == TaxfulPrice(75, currency)
    assert ol.taxless_price == order.shop.create_price(150)
    assert ol.taxful_price == TaxfulPrice(150 + 75, currency)
    assert ol.taxless_base_unit_price == order.shop.create_price(40)
    assert ol.taxful_base_unit_price == TaxfulPrice(60, currency)
    assert "Thing" in six.text_type(ol)
コード例 #26
0
ファイル: _creator.py プロジェクト: wsmoyer/shuup
    def source_line_to_order_lines(self, order, source_line):
        """
        Convert a source line into one or more order lines.

        Normally each source line will yield just one order line, but
        package products will yield a parent line and its child lines.

        :type order: shuup.core.models.Order
        :param order: The order
        :type source_line: shuup.core.order_creator.SourceLine
        :param source_line: The SourceLine
        :rtype: Iterable[OrderLine]
        """
        order_line = OrderLine(order=order)
        product = source_line.product
        quantity = Decimal(source_line.quantity)
        if product:
            order_line.product = product
            if product.sales_unit:
                quantized_quantity = bankers_round(quantity,
                                                   product.sales_unit.decimals)
                if quantized_quantity != quantity:
                    raise ValueError(
                        "Sales unit decimal conversion causes precision loss!")
        else:
            order_line.product = None

        def text(value):
            return force_text(value) if value is not None else ""

        order_line.quantity = quantity
        order_line.supplier = source_line.supplier
        order_line.sku = text(source_line.sku)
        order_line.text = (text(source_line.text))[:192]
        if source_line.base_unit_price:
            order_line.base_unit_price = source_line.base_unit_price
        if source_line.discount_amount:
            order_line.discount_amount = source_line.discount_amount
        order_line.type = (source_line.type if source_line.type is not None
                           else OrderLineType.OTHER)
        order_line.accounting_identifier = text(
            source_line.accounting_identifier)
        order_line.require_verification = bool(
            source_line.require_verification)
        order_line.verified = (not order_line.require_verification)
        order_line.source_line = source_line
        order_line.parent_source_line = source_line.parent_line
        extra_data = source_line.data.get("extra", {}) if hasattr(
            source_line, "data") else {}
        extra_data.update({"source_line_id": source_line.line_id})

        order_line.extra_data = extra_data
        self._check_orderability(order_line)

        yield order_line

        for child_order_line in self.create_package_children(order_line):
            yield child_order_line
コード例 #27
0
def test_order_arbitrary_refunds_with_multiple_suppliers():
    shop = get_default_shop()
    supplier1 = Supplier.objects.create(identifier="1", name="supplier1")
    supplier1.shops.add(shop)
    supplier2 = Supplier.objects.create(identifier="2")
    supplier2.shops.add(shop)
    supplier3 = Supplier.objects.create(identifier="3", name="s")
    supplier3.shops.add(shop)

    product1 = create_product("sku1", shop=shop, default_price=10)
    shop_product1 = product1.get_shop_instance(shop=shop)
    shop_product1.suppliers.set([supplier1, supplier2, supplier3])

    product2 = create_product("sku2", shop=shop, default_price=10)
    shop_product2 = product1.get_shop_instance(shop=shop)
    shop_product2.suppliers.set([supplier1, supplier2])

    product3 = create_product("sku3", shop=shop, default_price=10, shipping_mode=ShippingMode.NOT_SHIPPED)
    shop_product3 = product1.get_shop_instance(shop=shop)
    shop_product3.suppliers.set([supplier3])

    product_quantities = {
        supplier1: {product1: 5, product2: 6},
        supplier2: {product1: 3, product2: 13},
        supplier3: {product1: 1, product3: 50},
    }

    def get_quantity(supplier, product):
        return product_quantities[supplier.pk][product.pk]

    order = create_empty_order(shop=shop)
    order.full_clean()
    order.save()

    for supplier, product_data in six.iteritems(product_quantities):
        for product, quantity in six.iteritems(product_data):
            add_product_to_order(order, supplier, product, quantity, 5)

    # Lines without quantity shouldn't affect refunds
    other_line = OrderLine(
        order=order, type=OrderLineType.OTHER, text="This random line for textual information", quantity=0
    )
    other_line.save()
    order.lines.add(other_line)

    order.cache_prices()
    order.create_payment(order.taxful_total_price)
    assert order.is_paid()

    # All supplier should be able to refund the order
    assert order.can_create_refund()
    assert order.can_create_refund(supplier1)
    assert order.can_create_refund(supplier2)
    assert order.can_create_refund(supplier3)

    # Step by step refund lines for supplier1
    assert order.can_create_refund()
    assert order.get_total_unrefunded_amount(supplier1).value == Decimal("55")  # 11 * 5
    assert order.get_total_unrefunded_amount().value == Decimal("390")  # 55 + 80 + 255
    proudct1_line_for_supplier1 = order.lines.filter(supplier=supplier1, product=product1).first()
    supplier1_refund_data = [
        {
            "line": proudct1_line_for_supplier1,
            "quantity": proudct1_line_for_supplier1.quantity,
            "amount": order.shop.create_price(20).amount,  # Line total is 5 * 5 = 25
            "restock_products": True,
        }
    ]
    order.create_refund(supplier1_refund_data)
    assert order.get_total_unrefunded_amount(supplier1).value == Decimal("35")

    order.create_refund(
        [{"line": "amount", "quantity": 1, "amount": order.shop.create_price(30).amount}], supplier=supplier1
    )

    assert order.get_total_unrefunded_amount(supplier1).value == Decimal("5")

    order.create_refund(
        [{"line": "amount", "quantity": 1, "amount": order.shop.create_price(5).amount}], supplier=supplier1
    )

    assert order.get_total_unrefunded_amount(supplier1).value == Decimal("0")
    assert order.can_create_refund(supplier1)  # Some quantity still left to refund

    proudct2_line_for_supplier1 = order.lines.filter(supplier=supplier1, product=product2).first()
    supplier1_restock_refund_data = [
        {
            "line": proudct2_line_for_supplier1,
            "quantity": proudct2_line_for_supplier1.quantity,
            "amount": order.shop.create_price(0).amount,  # Line total is 5 * 5 = 25
            "restock_products": True,
        }
    ]
    order.create_refund(supplier1_restock_refund_data)
    assert not order.can_create_refund(supplier1)

    # Step by step refund lines for supplier2
    assert order.can_create_refund()
    assert order.get_total_unrefunded_amount(supplier2).value == Decimal("80")  # 16 * 5
    assert order.get_total_unrefunded_amount().value == Decimal("335")  # 80 + 255
    proudct2_line_for_supplier2 = order.lines.filter(supplier=supplier2, product=product2).first()
    supplier2_refund_data = [
        {
            "line": proudct2_line_for_supplier2,
            "quantity": 10,
            "amount": order.shop.create_price(50).amount,  # Line total is 13 * 5 = 65
            "restock_products": True,
        }
    ]
    order.create_refund(supplier2_refund_data)
    assert order.get_total_unrefunded_amount(supplier2).value == Decimal("30")

    order.create_refund(
        [{"line": "amount", "quantity": 1, "amount": order.shop.create_price(5).amount}], supplier=supplier2
    )

    assert order.get_total_unrefunded_amount(supplier2).value == Decimal("25")

    order.create_refund(
        [{"line": "amount", "quantity": 1, "amount": order.shop.create_price(25).amount}], supplier=supplier2
    )

    assert order.get_total_unrefunded_amount(supplier2).value == Decimal("0")
    assert order.can_create_refund(supplier2)  # Some quantity still left to refund

    supplier2_restock_refund_data = [
        {
            "line": proudct2_line_for_supplier2,
            "quantity": 3,
            "amount": order.shop.create_price(0).amount,  # Line total is 5 * 5 = 25
            "restock_products": True,
        }
    ]
    order.create_refund(supplier2_restock_refund_data)

    proudct1_line_for_supplier2 = order.lines.filter(supplier=supplier2, product=product1).first()
    supplier1_restock_refund_data = [
        {
            "line": proudct1_line_for_supplier2,
            "quantity": proudct1_line_for_supplier2.quantity,
            "amount": order.shop.create_price(0).amount,  # Line total is 5 * 5 = 25
            "restock_products": True,
        }
    ]
    order.create_refund(supplier1_restock_refund_data)
    assert not order.can_create_refund(supplier2)

    # Step by step refund lines for supplier3
    assert order.can_create_refund()
    assert order.get_total_unrefunded_amount(supplier3).value == Decimal("255")  # 51 * 5
    assert order.get_total_unrefunded_amount().value == Decimal("255")  # 255

    order.create_refund(
        [{"line": "amount", "quantity": 1, "amount": order.shop.create_price(55).amount}], supplier=supplier3
    )

    assert order.get_total_unrefunded_amount(supplier3).value == Decimal("200")

    proudct3_line_for_supplier3 = order.lines.filter(supplier=supplier3, product=product3).first()
    supplier3_refund_data = [
        {
            "line": proudct3_line_for_supplier3,
            "quantity": 50,
            "amount": order.shop.create_price(200).amount,  # Line total is 13 * 5 = 65
            "restock_products": True,
        }
    ]
    order.create_refund(supplier3_refund_data)
    assert order.get_total_unrefunded_amount(supplier2).value == Decimal("0")
    assert order.get_total_unrefunded_amount().value == Decimal("0")
    assert order.can_create_refund(supplier3)  # Some quantity still left to refund

    proudct1_line_for_supplier3 = order.lines.filter(supplier=supplier3, product=product1).first()
    supplier3_restock_refund_data = [
        {
            "line": proudct1_line_for_supplier3,
            "quantity": proudct1_line_for_supplier3.quantity,
            "amount": order.shop.create_price(0).amount,  # Line total is 5 * 5 = 25
            "restock_products": True,
        }
    ]
    order.create_refund(supplier3_restock_refund_data)
    assert not order.can_create_refund(supplier3)
    assert not order.can_create_refund()
コード例 #28
0
def create_order(request, creator, customer, product):
    billing_address = get_address().to_immutable()
    shipping_address = get_address(name="Shippy Doge").to_immutable()
    shipping_address.save()
    shop = request.shop
    order = Order(
        creator=creator,
        customer=customer,
        shop=shop,
        payment_method=get_default_payment_method(),
        shipping_method=get_default_shipping_method(),
        billing_address=billing_address,
        shipping_address=shipping_address,
        order_date=now(),
        status=get_initial_order_status(),
        currency=shop.currency,
        prices_include_tax=shop.prices_include_tax,
    )
    order.full_clean()
    order.save()
    supplier = get_default_supplier()
    product_order_line = OrderLine(order=order)
    update_order_line_from_product(pricing_context=request,
                                   order_line=product_order_line,
                                   product=product,
                                   quantity=5,
                                   supplier=supplier)

    assert product_order_line.text == product.safe_translation_getter("name")
    product_order_line.base_unit_price = shop.create_price(100)
    assert product_order_line.price.value > 0
    product_order_line.save()

    line_tax = get_line_taxes_for(product_order_line)[0]

    order_line_tax = OrderLineTax.from_tax(
        tax=line_tax.tax,
        base_amount=line_tax.base_amount,
        order_line=product_order_line,
    )
    order_line_tax.save(
    )  # Save order_line_tax before linking to order_line.tax
    product_order_line.taxes.add(order_line_tax)

    discount_order_line = OrderLine(order=order,
                                    quantity=1,
                                    type=OrderLineType.OTHER)
    discount_order_line.discount_amount = shop.create_price(30)
    assert discount_order_line.discount_amount.value == 30
    assert discount_order_line.price.value == -30
    assert discount_order_line.base_unit_price.value == 0
    discount_order_line.save()

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

    assert not order.can_set_complete()

    base = 5 * shop.create_price(100).amount
    discount = shop.create_price(30).amount
    tax_value = line_tax.amount
    if not order.prices_include_tax:
        assert order.taxless_total_price.amount == base - discount
        assert order.taxful_total_price.amount == base + tax_value - discount
    else:
        assert_almost_equal(order.taxless_total_price.amount,
                            base - tax_value - discount)
        assert_almost_equal(order.taxful_total_price.amount, base - discount)

    assert not order.is_fully_shipped()
    shipment = order.create_shipment_of_all_products(supplier=supplier)
    assert order.is_fully_shipped()

    assert shipment.total_products == 5, "All products were shipped"
    assert shipment.weight == product.gross_weight * 5 / 1000, "Gravity works"
    assert not order.get_unshipped_products(
    ), "Nothing was left in the warehouse"

    assert order.can_set_complete()

    order.create_payment(order.taxful_total_price)
    assert order.is_paid()
    assert Order.objects.paid().filter(
        pk=order.pk).exists(), "It was paid! Honestly!"
    assert order.has_products()
コード例 #29
0
def test_order_refunds_with_multiple_suppliers():
    shop = get_default_shop()
    supplier1 = Supplier.objects.create(identifier="1", name="supplier1")
    supplier1.shops.add(shop)
    supplier2 = Supplier.objects.create(identifier="2")
    supplier2.shops.add(shop)
    supplier3 = Supplier.objects.create(identifier="3", name="s")
    supplier3.shops.add(shop)

    product1 = create_product("sku1", shop=shop, default_price=10)
    shop_product1 = product1.get_shop_instance(shop=shop)
    shop_product1.suppliers.set([supplier1, supplier2, supplier3])

    product2 = create_product("sku2", shop=shop, default_price=10)
    shop_product2 = product1.get_shop_instance(shop=shop)
    shop_product2.suppliers.set([supplier1, supplier2])

    product3 = create_product("sku3", shop=shop, default_price=10, shipping_mode=ShippingMode.NOT_SHIPPED)
    shop_product3 = product1.get_shop_instance(shop=shop)
    shop_product3.suppliers.set([supplier3])

    product_quantities = {
        supplier1: {product1: 5, product2: 6},
        supplier2: {product1: 3, product2: 13},
        supplier3: {product1: 1, product3: 50},
    }

    def get_quantity(supplier, product):
        return product_quantities[supplier.pk][product.pk]

    order = create_empty_order(shop=shop)
    order.full_clean()
    order.save()

    for supplier, product_data in six.iteritems(product_quantities):
        for product, quantity in six.iteritems(product_data):
            add_product_to_order(order, supplier, product, quantity, 5)

    # Lines without quantity shouldn't affect refunds
    other_line = OrderLine(
        order=order, type=OrderLineType.OTHER, text="This random line for textual information", quantity=0
    )
    other_line.save()
    order.lines.add(other_line)

    order.cache_prices()
    order.create_payment(order.taxful_total_price)
    assert order.is_paid()

    # All supplier should be able to refund the order
    assert order.can_create_refund()
    assert order.can_create_refund(supplier1)
    assert order.can_create_refund(supplier2)
    assert order.can_create_refund(supplier3)

    assert order.get_total_unrefunded_amount(supplier1).value == Decimal("55")  # 11 * 5
    assert order.get_total_unrefunded_quantity(supplier1) == Decimal("11")  # 5 x product1 and 6 x product2

    with pytest.raises(RefundExceedsAmountException):
        order.create_refund(
            [{"line": "amount", "quantity": 1, "amount": order.shop.create_price(60)}], supplier=supplier1
        )

    # Supplier 1 refunds the order
    order.create_refund(_get_refund_data(order, supplier1))
    assert order.get_total_refunded_amount(supplier1).value == Decimal("55")  # 11 * 5
    assert order.get_total_unrefunded_amount(supplier1).value == Decimal("0")

    assert not order.can_create_refund(supplier1)
    assert order.can_create_refund()
    assert order.can_create_refund(supplier2)
    assert order.can_create_refund(supplier3)

    assert order.get_total_unrefunded_amount(supplier2).value == Decimal("80")  # 16 * 5
    assert order.get_total_unrefunded_quantity(supplier2) == Decimal("16")  # 3 x product1 and 13 x product2

    with pytest.raises(RefundExceedsAmountException):
        order.create_refund(
            [{"line": "amount", "quantity": 1, "amount": order.shop.create_price(81)}], supplier=supplier2
        )

    # Supplier 2 refunds the order
    order.create_refund(_get_refund_data(order, supplier2))
    assert order.get_total_refunded_amount(supplier2).value == Decimal("80")  # 11 * 5
    assert order.get_total_unrefunded_amount(supplier2).value == Decimal("0")
    assert not order.can_create_refund(supplier1)
    assert not order.can_create_refund(supplier2)
    assert order.can_create_refund()
    assert order.can_create_refund(supplier3)

    assert order.get_total_unrefunded_amount(supplier3).value == Decimal("255")  # 51 * 5
    assert order.get_total_unrefunded_quantity(supplier3) == Decimal("51")  # 3 x product1 and 13 x product2

    with override_settings(SHUUP_ALLOW_ARBITRARY_REFUNDS=False):
        with pytest.raises(RefundArbitraryRefundsNotAllowedException):
            order.create_refund(
                [{"line": "amount", "quantity": 1, "amount": order.shop.create_price(200)}], supplier=supplier3
            )

    order.create_refund([{"line": "amount", "quantity": 1, "amount": order.shop.create_price(200)}], supplier=supplier3)
    assert OrderLine.objects.filter(order=order, supplier=supplier3, type=OrderLineType.REFUND).exists()

    # Supplier 3 refunds the order
    order.create_refund(_get_refund_data(order, supplier3))
    assert order.get_total_refunded_amount(supplier3).value == Decimal("255")  # 11 * 5
    assert order.get_total_unrefunded_amount(supplier3).value == Decimal("0")
    assert not order.can_create_refund(supplier1)
    assert not order.can_create_refund(supplier2)
    assert not order.can_create_refund(supplier3)
    assert not order.can_create_refund()
コード例 #30
0
ファイル: test_basic_order.py プロジェクト: ruqaiya/shuup
def create_order(request, creator, customer, product):
    billing_address = get_address().to_immutable()
    shipping_address = get_address(name="Shippy Doge").to_immutable()
    shipping_address.save()
    default_pm = get_default_payment_method()
    default_sm = get_default_shipping_method()
    shop = request.shop
    order = Order(
        creator=creator,
        customer=customer,
        shop=shop,
        payment_method=default_pm,
        shipping_method=default_sm,
        billing_address=billing_address,
        shipping_address=shipping_address,
        order_date=now(),
        status=get_initial_order_status(),
        currency=shop.currency,
        prices_include_tax=shop.prices_include_tax,
    )
    order.full_clean()
    order.save()
    supplier = get_default_supplier()
    product_order_line = OrderLine(order=order)
    update_order_line_from_product(
        pricing_context=request,
        order_line=product_order_line,
        product=product,
        quantity=5,
        supplier=supplier)

    assert product_order_line.text == product.safe_translation_getter("name")
    product_order_line.base_unit_price = shop.create_price(100)
    assert product_order_line.price.value > 0
    product_order_line.save()

    line_tax = get_line_taxes_for(product_order_line)[0]

    order_line_tax = OrderLineTax.from_tax(
        tax=line_tax.tax,
        base_amount=line_tax.base_amount,
        order_line=product_order_line,
    )
    order_line_tax.save()  # Save order_line_tax before linking to order_line.tax
    product_order_line.taxes.add(order_line_tax)

    discount_order_line = OrderLine(order=order, quantity=1, type=OrderLineType.OTHER)
    discount_order_line.discount_amount = shop.create_price(30)
    assert discount_order_line.discount_amount.value == 30
    assert discount_order_line.price.value == -30
    assert discount_order_line.base_unit_price.value == 0
    discount_order_line.save()

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

    assert not order.can_set_complete()

    base = 5 * shop.create_price(100).amount
    discount = shop.create_price(30).amount
    tax_value = line_tax.amount
    if not order.prices_include_tax:
        assert order.taxless_total_price.amount == base - discount
        assert order.taxful_total_price.amount == base + tax_value - discount
    else:
        assert_almost_equal(order.taxless_total_price.amount, base - tax_value - discount)
        assert_almost_equal(order.taxful_total_price.amount, base - discount)

    assert not order.is_fully_shipped()
    shipment = order.create_shipment_of_all_products(supplier=supplier)
    assert order.is_fully_shipped()

    assert shipment.total_products == 5, "All products were shipped"
    assert shipment.weight == product.gross_weight * 5 / 1000, "Gravity works"
    assert not order.get_unshipped_products(), "Nothing was left in the warehouse"

    assert order.can_set_complete()

    order.create_payment(order.taxful_total_price)
    assert order.is_paid()
    assert Order.objects.paid().filter(pk=order.pk).exists(), "It was paid! Honestly!"
    assert order.has_products()

    assert order.get_available_shipping_methods()
    assert order.get_available_payment_methods()

    assert default_sm in order.get_available_shipping_methods()
    assert default_pm in order.get_available_payment_methods()
コード例 #31
0
ファイル: _creator.py プロジェクト: ruqaiya/shuup
    def source_line_to_order_lines(self, order, source_line):
        """
        Convert a source line into one or more order lines.

        Normally each source line will yield just one order line, but
        package products will yield a parent line and its child lines.

        :type order: shuup.core.models.Order
        :param order: The order
        :type source_line: shuup.core.order_creator.SourceLine
        :param source_line: The SourceLine
        :rtype: Iterable[OrderLine]
        """
        order_line = OrderLine(order=order)
        product = source_line.product
        quantity = Decimal(source_line.quantity)
        if product:
            order_line.product = product
            if product.sales_unit:
                quantized_quantity = bankers_round(quantity, product.sales_unit.decimals)
                if quantized_quantity != quantity:
                    raise ValueError("Sales unit decimal conversion causes precision loss!")
        else:
            order_line.product = None

        def text(value):
            return force_text(value) if value is not None else ""

        order_line.quantity = quantity
        order_line.supplier = source_line.supplier
        order_line.sku = text(source_line.sku)
        order_line.text = (text(source_line.text))[:192]
        if source_line.base_unit_price:
            order_line.base_unit_price = source_line.base_unit_price
        if source_line.discount_amount:
            order_line.discount_amount = source_line.discount_amount
        order_line.type = (source_line.type if source_line.type is not None
                           else OrderLineType.OTHER)
        order_line.accounting_identifier = text(source_line.accounting_identifier)
        order_line.require_verification = bool(source_line.require_verification)
        order_line.verified = (not order_line.require_verification)
        order_line.source_line = source_line
        order_line.parent_source_line = source_line.parent_line
        extra_data = source_line.data.get("extra", {}) if hasattr(source_line, "data") else {}
        extra_data.update({"source_line_id": source_line.line_id})

        order_line.extra_data = extra_data
        self._check_orderability(order_line)

        yield order_line

        for child_order_line in self.create_package_children(order_line):
            yield child_order_line