Пример #1
0
    def from_line_taxes(cls, line_taxes, untaxed):
        """
        Create TaxSummary from LineTaxes.

        :param line_taxes: List of line taxes to summarize
        :type line_taxes: list[LineTax]
        :param untaxed: Sum of taxless prices that have no taxes added
        :type untaxed: shuup.core.pricing.TaxlessPrice
        """
        zero_amount = Money(0, untaxed.currency)
        tax_amount_by_tax = defaultdict(lambda: zero_amount)
        raw_base_amount_by_tax = defaultdict(lambda: zero_amount)
        base_amount_by_tax = defaultdict(lambda: zero_amount)
        for line_tax in line_taxes:
            assert isinstance(line_tax, LineTax)
            tax_amount_by_tax[line_tax.tax] += line_tax.amount
            raw_base_amount_by_tax[line_tax.tax] += line_tax.base_amount
            base_amount_by_tax[line_tax.tax] += bankers_round(line_tax.base_amount, 2)

        lines = [
            TaxSummaryLine.from_tax(tax, base_amount_by_tax[tax], raw_base_amount_by_tax[tax], tax_amount)
            for (tax, tax_amount) in tax_amount_by_tax.items()
        ]
        if untaxed:
            lines.append(
                TaxSummaryLine(
                    tax_id=None, tax_code='', tax_name=_("Untaxed"),
                    tax_rate=Decimal(0), based_on=bankers_round(untaxed.amount, 2),
                    raw_based_on=untaxed.amount, tax_amount=zero_amount))
        return cls(sorted(lines, key=TaxSummaryLine.get_sort_key))
Пример #2
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))
Пример #3
0
 def __get__(self, instance, type=None):
     if instance is None:
         return self
     taxful = self.params.get("includes_tax", instance.prices_include_tax)
     zero = (TaxfulPrice if taxful else TaxlessPrice)(0, instance.currency)
     lines = getattr(instance, self.line_getter)()
     return sum((bankers_round(getattr(x, self.field), 2) for x in lines), zero)
Пример #4
0
    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 lines for both the parent and its children products.

        :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(
                        "Error! 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
Пример #5
0
 def __get__(self, instance, type=None):
     if instance is None:
         return self
     taxful = self.params.get('includes_tax', instance.prices_include_tax)
     zero = (TaxfulPrice if taxful else TaxlessPrice)(0, instance.currency)
     lines = getattr(instance, self.line_getter)()
     return sum((bankers_round(getattr(x, self.field), 2) for x in lines),
                zero)
Пример #6
0
 def taxful_price(self):
     """
     :rtype: TaxfulPrice
     """
     price = self.price
     return bankers_round(
         (price if price.includes_tax else TaxfulPrice(price.amount +
                                                       self.tax_amount)), 2)
Пример #7
0
 def taxless_price(self):
     """
     :rtype: TaxlessPrice
     """
     price = self.price
     return bankers_round(
         (TaxlessPrice(price.amount -
                       self.tax_amount) if price.includes_tax else price),
         2)
Пример #8
0
 def __init__(self, tax_id, tax_code, tax_name, tax_rate,
              based_on, raw_based_on, tax_amount):
     self.tax_id = tax_id
     self.tax_code = tax_code
     self.tax_name = tax_name
     self.tax_rate = tax_rate
     self.raw_based_on = ensure_decimal_places(raw_based_on)
     self.based_on = ensure_decimal_places(based_on)
     self.tax_amount = ensure_decimal_places(tax_amount)
     self.taxful = bankers_round(self.raw_based_on + tax_amount, 2)
Пример #9
0
def _check_taxful_price(source):
    for line in source.get_lines():
        from_components = bankers_round(line.taxful_base_unit_price*line.quantity - line.taxful_discount_amount, 2)
        assert from_components == line.taxful_price
        assert line.price == line.base_unit_price * line.quantity - line.discount_amount
        assert line.discount_amount == line.base_price - line.price
        if line.base_price:
            assert line.discount_rate == (1 - (line.price / line.base_price))
            assert line.discount_percentage == 100 * (1 - (line.price / line.base_price))
        if line.quantity:
            assert line.unit_discount_amount == line.discount_amount / line.quantity
Пример #10
0
def _check_taxful_price(source):
    for line in source.get_lines():
        from_components = bankers_round(line.taxful_base_unit_price*line.quantity - line.taxful_discount_amount, 2)
        assert from_components == line.taxful_price
        assert line.price == line.base_unit_price * line.quantity - line.discount_amount
        assert line.discount_amount == line.base_price - line.price
        if line.base_price:
            assert line.discount_rate == (1 - (line.price / line.base_price))
            assert line.discount_percentage == 100 * (1 - (line.price / line.base_price))
        if line.quantity:
            assert line.unit_discount_amount == line.discount_amount / line.quantity
Пример #11
0
    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
Пример #12
0
def test_order_source_rounding(prices):
    shop = Shop.objects.create(name="test",
                               identifier="test",
                               status=ShopStatus.ENABLED,
                               public_name="test",
                               prices_include_tax=False)
    expected = 0
    for p in prices:
        expected += bankers_round(p, 2)

    source = BasketishOrderSource(shop)
    for x, price in enumerate(prices):
        source.add_line(
            type=OrderLineType.OTHER,
            quantity=1,
            text=x,
            base_unit_price=source.create_price(price),
            ordering=x,
        )

    for x, order_source in enumerate(source.get_lines()):
        price = Decimal(prices[x]).quantize(Decimal(".1")**9)

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

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

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

        # make sure the line price is rounded
        assert order_source.price == source.shop.create_price(price)

    # make sure order total is rounded
    assert source.taxless_total_price == source.shop.create_price(
        bankers_round(expected, 2))
Пример #13
0
def test_order_source_rounding(prices):
    shop = Shop.objects.create(
        name="test",
        identifier="test",
        status=ShopStatus.ENABLED,
        public_name="test",
        prices_include_tax=False
    )
    expected = 0
    for p in prices:
        expected += bankers_round(p, 2)

    source = BasketishOrderSource(shop)
    for x, price in enumerate(prices):
        source.add_line(
            type=OrderLineType.OTHER,
            quantity=1,
            text=x,
            base_unit_price=source.create_price(price),
            ordering=x,
        )

    for x, order_source in enumerate(source.get_lines()):
        price = Decimal(prices[x]).quantize(Decimal(".1") ** 9)

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

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

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

        # make sure the line price is rounded
        assert order_source.price == source.shop.create_price(price)

    # make sure order total is rounded
    assert source.taxless_total_price == source.shop.create_price(bankers_round(expected, 2))
Пример #14
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()
    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))
Пример #15
0
 def get_chart(self):
     orders = get_orders_by_currency(self.currency)
     aggregate_data = group_by_period(
         orders.valid().since(days=365), "order_date", "month", sum=Sum("taxful_total_price_value")
     )
     locale = get_current_babel_locale()
     bar_chart = BarChart(
         title=_("Sales per Month (last year)"),
         labels=[format_date(k, format=get_year_and_month_format(locale), locale=locale) for k in aggregate_data],
     )
     bar_chart.add_data(
         _("Sales (%(currency)s)") % {"currency": self.currency},
         [bankers_round(v["sum"], 2) for v in aggregate_data.values()],  # TODO: To be fixed in SHUUP-1912
     )
     return bar_chart
Пример #16
0
 def get_chart(self):
     orders = get_orders_by_currency(self.currency)
     aggregate_data = group_by_period(orders.valid().since(days=365),
                                      "order_date",
                                      "month",
                                      sum=Sum("taxful_total_price_value"))
     locale = get_current_babel_locale()
     bar_chart = BarChart(title=_("Sales per Month (last year)"),
                          labels=[
                              format_date(
                                  k,
                                  format=get_year_and_month_format(locale),
                                  locale=locale) for k in aggregate_data
                          ])
     bar_chart.add_data(
         _("Sales (%(currency)s)") % {"currency": self.currency},
         [
             bankers_round(v["sum"], 2)  # TODO: To be fixed in SHUUP-1912
             for v in aggregate_data.values()
         ])
     return bar_chart
Пример #17
0
def test_basket_with_package_product(admin_user):
    with override_settings(**REQUIRED_SETTINGS):
        shop = factories.get_default_shop()
        factories.get_default_shipping_method()
        factories.get_default_payment_method()
        OrderStatusManager().ensure_default_statuses()

        client = get_client(admin_user)
        response = client.post("/api/shuup/basket/new/", format="json", data={"shop": shop.pk})
        assert response.status_code == status.HTTP_201_CREATED
        basket_uuid = response.data["uuid"]

        supplier = factories.get_supplier(SimpleSupplierModule.identifier, shop=shop, stock_managed=True)

        # base product - 1kg of sand
        base_sand_product = factories.create_product(
            "Sand",
            shop=shop,
            supplier=supplier,
            default_price="15.2",
            net_weight=Decimal(1)
        )

        # 10kg bag of sand - package made by 10kg of sand
        sand_bag_10kg_product = factories.create_product(
            "Sand-bag-10-kg",
            shop=shop,
            supplier=supplier,
            default_price="149.9",
            net_weight=Decimal(10000)
        )
        sand_bag_10kg_product.make_package({
            base_sand_product: 10
        })
        sand_bag_10kg_product.save()

        # 18.45kg bag of sand - package made by 18.45kg of sand
        sand_bag_1845kg_product = factories.create_product(
            "Sand-bag-1845-kg",
            shop=shop,
            supplier=supplier,
            default_price="179.9",
            net_weight=Decimal(18450)
        )
        sand_bag_1845kg_product.make_package({
            base_sand_product: 18.45
        })
        sand_bag_1845kg_product.save()

        # 25kg bag of sand - package made by 25kg of sand
        sand_bag_25kg_product = factories.create_product(
            "Sand-bag-25-kg",
            shop=shop,
            supplier=supplier,
            default_price="2450.25",
            net_weight=Decimal(25000)
        )
        sand_bag_25kg_product.make_package({
            base_sand_product: 25
        })
        sand_bag_25kg_product.save()

        initial_stock = 55

        # put 55 sands (55kg) in stock
        supplier.adjust_stock(base_sand_product.id, initial_stock)
        stock_status = supplier.get_stock_status(base_sand_product.id)
        assert stock_status.physical_count == initial_stock
        assert stock_status.logical_count == initial_stock

        # zero stock for packages
        assert supplier.get_stock_status(sand_bag_10kg_product.id).logical_count == 0
        assert supplier.get_stock_status(sand_bag_1845kg_product.id).logical_count == 0
        assert supplier.get_stock_status(sand_bag_25kg_product.id).logical_count == 0

        # add all the 3 packages to the basket, this will require (10 + 18.45 + 25 = 53.45 Sands)
        for product in [sand_bag_10kg_product, sand_bag_1845kg_product, sand_bag_25kg_product]:
            response = client.post("/api/shuup/basket/{}/add/".format(basket_uuid), format="json", data={
                "shop": shop.pk,
                "product": product.id
            })
            assert response.status_code == status.HTTP_200_OK

        # get the basket
        response = client.get("/api/shuup/basket/{}/".format(basket_uuid))
        assert response.status_code == status.HTTP_200_OK
        assert response.data["validation_errors"] == []

        # now add more 25kg and it shouldn't have enough stock
        response = client.post("/api/shuup/basket/{}/add/".format(basket_uuid), format="json", data={
            "shop": shop.pk,
            "product": sand_bag_25kg_product.id
        })
        assert response.status_code == status.HTTP_400_BAD_REQUEST
        assert "Insufficient stock" in response.data["error"]

        # create order anyway
        response = client.post("/api/shuup/basket/{}/create_order/".format(basket_uuid), format="json")
        assert response.status_code == status.HTTP_201_CREATED
        order = Order.objects.get(id=response.data["id"])
        line_counter = Counter()

        for line in order.lines.products():
            line_counter[line.product.id] += line.quantity

        assert bankers_round(line_counter[base_sand_product.id]) == bankers_round(
            Decimal(10) + Decimal(18.45) + Decimal(25)
        )
        assert line_counter[sand_bag_10kg_product.id] == 1
        assert line_counter[sand_bag_1845kg_product.id] == 1
        assert line_counter[sand_bag_25kg_product.id] == 1
Пример #18
0
def _get_taxful_price(line):
    return bankers_round(
        line.taxful_base_unit_price * line.quantity -
        line.taxful_discount_amount, 2)
Пример #19
0
def bround(value):
    return bankers_round(value, 2)
Пример #20
0
def test_basket_with_package_product(admin_user):
    shop = factories.get_default_shop()
    factories.get_default_shipping_method()
    factories.get_default_payment_method()
    OrderStatusManager().ensure_default_statuses()

    client = get_client(admin_user)
    response = client.post("/api/shuup/basket/new/",
                           format="json",
                           data={"shop": shop.pk})
    assert response.status_code == status.HTTP_201_CREATED
    basket_uuid = response.data["uuid"]

    supplier = factories.get_supplier(SimpleSupplierModule.identifier,
                                      shop=shop,
                                      stock_managed=True)

    # base product - 1kg of sand
    base_sand_product = factories.create_product("Sand",
                                                 shop=shop,
                                                 supplier=supplier,
                                                 default_price="15.2",
                                                 net_weight=Decimal(1))

    # 10kg bag of sand - package made by 10kg of sand
    sand_bag_10kg_product = factories.create_product("Sand-bag-10-kg",
                                                     shop=shop,
                                                     supplier=supplier,
                                                     default_price="149.9",
                                                     net_weight=Decimal(10000))
    sand_bag_10kg_product.make_package({base_sand_product: 10})
    sand_bag_10kg_product.save()

    # 18.45kg bag of sand - package made by 18.45kg of sand
    sand_bag_1845kg_product = factories.create_product(
        "Sand-bag-1845-kg",
        shop=shop,
        supplier=supplier,
        default_price="179.9",
        net_weight=Decimal(18450))
    sand_bag_1845kg_product.make_package({base_sand_product: 18.45})
    sand_bag_1845kg_product.save()

    # 25kg bag of sand - package made by 25kg of sand
    sand_bag_25kg_product = factories.create_product("Sand-bag-25-kg",
                                                     shop=shop,
                                                     supplier=supplier,
                                                     default_price="2450.25",
                                                     net_weight=Decimal(25000))
    sand_bag_25kg_product.make_package({base_sand_product: 25})
    sand_bag_25kg_product.save()

    initial_stock = 55

    # put 55 sands (55kg) in stock
    supplier.adjust_stock(base_sand_product.id, initial_stock)
    stock_status = supplier.get_stock_status(base_sand_product.id)
    assert stock_status.physical_count == initial_stock
    assert stock_status.logical_count == initial_stock

    # zero stock for packages
    assert supplier.get_stock_status(
        sand_bag_10kg_product.id).logical_count == 0
    assert supplier.get_stock_status(
        sand_bag_1845kg_product.id).logical_count == 0
    assert supplier.get_stock_status(
        sand_bag_25kg_product.id).logical_count == 0

    # add all the 3 packages to the basket, this will require (10 + 18.45 + 25 = 53.45 Sands)
    for product in [
            sand_bag_10kg_product, sand_bag_1845kg_product,
            sand_bag_25kg_product
    ]:
        response = client.post(
            "/api/shuup/basket/{}/add/".format(basket_uuid),
            format="json",
            data={
                "shop": shop.pk,
                "product": product.id
            },
        )
        assert response.status_code == status.HTTP_200_OK

    # get the basket
    response = client.get("/api/shuup/basket/{}/".format(basket_uuid))
    assert response.status_code == status.HTTP_200_OK
    assert response.data["validation_errors"] == []

    # now add more 25kg and it shouldn't have enough stock
    response = client.post(
        "/api/shuup/basket/{}/add/".format(basket_uuid),
        format="json",
        data={
            "shop": shop.pk,
            "product": sand_bag_25kg_product.id
        },
    )
    assert response.status_code == status.HTTP_400_BAD_REQUEST
    assert "Insufficient quantity" in response.data["error"]

    # create order anyway
    response = client.post(
        "/api/shuup/basket/{}/create_order/".format(basket_uuid),
        format="json")
    assert response.status_code == status.HTTP_201_CREATED
    order = Order.objects.get(id=response.data["id"])
    line_counter = Counter()

    for line in order.lines.products():
        line_counter[line.product.id] += line.quantity

    assert bankers_round(line_counter[base_sand_product.id]) == bankers_round(
        Decimal(10) + Decimal(18.45) + Decimal(25))
    assert line_counter[sand_bag_10kg_product.id] == 1
    assert line_counter[sand_bag_1845kg_product.id] == 1
    assert line_counter[sand_bag_25kg_product.id] == 1
Пример #21
0
def test_broken_order(admin_user):
    """
    """
    quantities = [44, 23, 65]
    expected = sum(quantities) * 50
    expected_based_on = expected / 1.5

    # Shuup is calculating taxes per line so there will be some "errors"
    expected_based_on = ensure_decimal_places(Decimal("%s" % (expected_based_on + 0.01)))

    shop = get_default_shop()

    supplier = get_default_supplier()
    product1 = create_product("simple-test-product1", shop, supplier, 50)
    product2 = create_product("simple-test-product2", shop, supplier, 50)
    product3 = create_product("simple-test-product3", shop, supplier, 50)

    tax = get_default_tax()

    source = BasketishOrderSource(get_default_shop())
    billing_address = get_address(country="US")
    shipping_address = get_address(name="Test street", country="US")
    source.status = get_initial_order_status()
    source.billing_address = billing_address
    source.shipping_address = shipping_address
    source.customer = create_random_person()
    source.payment_method = get_default_payment_method()
    source.shipping_method = get_default_shipping_method()

    source.add_line(
        type=OrderLineType.PRODUCT,
        product=product1,
        supplier=get_default_supplier(),
        quantity=quantities[0],
        base_unit_price=source.create_price(50),
    )

    source.add_line(
        type=OrderLineType.PRODUCT,
        product=product2,
        supplier=get_default_supplier(),
        quantity=quantities[1],
        base_unit_price=source.create_price(50),
    )

    source.add_line(
        type=OrderLineType.PRODUCT,
        product=product3,
        supplier=get_default_supplier(),
        quantity=quantities[2],
        base_unit_price=source.create_price(50),
    )

    currency = "EUR"
    summary = source.get_tax_summary()


    assert len(summary) == 1
    summary = summary[0]

    assert summary.taxful == Money(expected, "EUR")
    assert summary.based_on == Money(expected_based_on, "EUR")

    # originally non-rounded value
    assert bankers_round(source.get_total_tax_amount()) == summary.tax_amount

    assert source.taxless_total_price.value == expected_based_on
    assert summary.taxful.value == source.taxful_total_price.value

    assert summary.tax_amount == Money(bankers_round(source.taxful_total_price.value - source.taxless_total_price.value), currency)
    assert summary.taxful == summary.raw_based_on + summary.tax_amount

    assert summary.tax_rate == tax.rate
    assert summary.taxful.value == (summary.based_on + summary.tax_amount).value - Decimal("%s" % 0.01)

    # create order from basket
    creator = OrderCreator()
    order = creator.create_order(source)
    assert order.taxless_total_price.value == expected_based_on

    # originally non-rounded value
    assert bankers_round(order.get_total_tax_amount()) == summary.tax_amount
Пример #22
0
def test_broken_order(admin_user):
    """"""
    quantities = [44, 23, 65]
    expected = sum(quantities) * 50
    expected_based_on = expected / 1.5

    # Shuup is calculating taxes per line so there will be some "errors"
    expected_based_on = ensure_decimal_places(
        Decimal("%s" % (expected_based_on + 0.01)))

    shop = get_default_shop()

    supplier = get_default_supplier()
    product1 = create_product("simple-test-product1", shop, supplier, 50)
    product2 = create_product("simple-test-product2", shop, supplier, 50)
    product3 = create_product("simple-test-product3", shop, supplier, 50)

    tax = get_default_tax()

    source = BasketishOrderSource(get_default_shop())
    billing_address = get_address(country="US")
    shipping_address = get_address(name="Test street", country="US")
    source.status = get_initial_order_status()
    source.billing_address = billing_address
    source.shipping_address = shipping_address
    source.customer = create_random_person()
    source.payment_method = get_default_payment_method()
    source.shipping_method = get_default_shipping_method()

    source.add_line(
        type=OrderLineType.PRODUCT,
        product=product1,
        supplier=get_default_supplier(),
        quantity=quantities[0],
        base_unit_price=source.create_price(50),
    )

    source.add_line(
        type=OrderLineType.PRODUCT,
        product=product2,
        supplier=get_default_supplier(),
        quantity=quantities[1],
        base_unit_price=source.create_price(50),
    )

    source.add_line(
        type=OrderLineType.PRODUCT,
        product=product3,
        supplier=get_default_supplier(),
        quantity=quantities[2],
        base_unit_price=source.create_price(50),
    )

    currency = "EUR"
    summary = source.get_tax_summary()

    assert len(summary) == 1
    summary = summary[0]

    assert summary.taxful == Money(expected, "EUR")
    assert summary.based_on == Money(expected_based_on, "EUR")

    # originally non-rounded value
    assert bankers_round(source.get_total_tax_amount()) == summary.tax_amount

    assert source.taxless_total_price.value == expected_based_on
    assert summary.taxful.value == source.taxful_total_price.value

    assert summary.tax_amount == Money(
        bankers_round(source.taxful_total_price.value -
                      source.taxless_total_price.value), currency)
    assert summary.taxful == summary.raw_based_on + summary.tax_amount

    assert summary.tax_rate == tax.rate
    assert summary.taxful.value == (
        summary.based_on + summary.tax_amount).value - Decimal("%s" % 0.01)

    # create order from basket
    creator = OrderCreator()
    order = creator.create_order(source)
    assert order.taxless_total_price.value == expected_based_on

    # originally non-rounded value
    assert bankers_round(order.get_total_tax_amount()) == summary.tax_amount
Пример #23
0
def _round_price(value):
    return bankers_round(value, 2)  # TODO: To be fixed in SHUUP-1912
Пример #24
0
def _get_taxful_price(line):
    return bankers_round(line.taxful_base_unit_price*line.quantity - line.taxful_discount_amount, 2)
Пример #25
0
 def round(self, value):
     return bankers_round(parse_decimal_string(value), self.decimals)
Пример #26
0
 def round(self, value):
     return bankers_round(parse_decimal_string(value), self.decimals)
Пример #27
0
 def rounded_amount(self):
     return bankers_round(self.amount, 2)