def test_compute_price_from_gross(self):
        price = compute_price(gross=0.99, tax=0.021, keep_gross=True)
        self.assertEqual(price.net.amount, D('0.97'))
        self.assertEqual(price.gross.amount, D('0.99'))
        self.assertEqual(price.tax.amount, D('0.02'))

        price = compute_price(gross=100, tax=0.2, keep_gross=True)
        self.assertEqual(price.net.amount, D('83.33'))
        self.assertEqual(price.gross.amount, D('100'))
        self.assertEqual(price.tax.amount, D('16.67'))

        price = compute_price(gross=10000, tax=0.196, keep_gross=True)
        self.assertEqual(price.net.amount, D('8361.20'))
        self.assertEqual(price.gross.amount, D('10000'))
        self.assertEqual(price.tax.amount, D('1638.80'))
    def test_compute_price_from_net_no_tax_fixed_discount(self):
        price = compute_price(net=100, keep_gross=False)
        self.assertEqual(price.net.amount, D('100'))
        self.assertEqual(price.gross.amount, D('100'))
        self.assertEqual(price.tax.amount, D(0))
        self.assertEqual(price.currency, 'EUR')

        discount = compute_discount(price=price,
                                    discount_amount=9.99,
                                    from_gross=False)
        self.assertEqual(discount.net.amount, D('90.01'))
        self.assertEqual(discount.gross.amount, D('90.01'))
        self.assertEqual(discount.tax.amount, D(0))
        self.assertEqual(discount.currency, 'EUR')
    def test_compute_discount_exception(self):
        self.assertEqual(compute_discount(discount_amount=1), None)

        price = compute_price(net=100, keep_gross=False)

        with self.assertRaises(Exception) as ctx:
            compute_discount(price=price, discount_percent=-10)
        self.assertEqual(str(ctx.exception),
                         "Discount percent must be a value between 0 and 1")

        with self.assertRaises(Exception) as ctx:
            compute_discount(price=price, discount_percent=200)
        self.assertEqual(str(ctx.exception),
                         "Discount percent must be a value between 0 and 1")
    def test_compute_price_from_gross_percentage_discount(self):
        price = compute_price(gross=120, tax=0.2, keep_gross=True)
        self.assertEqual(price.net.amount, D('100'))
        self.assertEqual(price.gross.amount, D('120'))
        self.assertEqual(price.tax.amount, D('20'))
        self.assertEqual(price.currency, 'EUR')

        discount = compute_discount(price=price,
                                    tax=0.2,
                                    discount_percent=0.1,
                                    from_gross=True)
        self.assertEqual(discount.net.amount, D('90'))
        self.assertEqual(discount.gross.amount, D('108'))
        self.assertEqual(discount.tax.amount, D('18'))
        self.assertEqual(discount.currency, 'EUR')
Example #5
0
 def create(cls, keep_gross=True, **kwargs):
     data = kwargs.copy()
     if cls.get_schema_definition:
         sch = cls.get_schema_definition(registry=cls.registry)
         data = sch.load(kwargs)
     net = data.get('unit_price_untaxed') or D(0)
     gross = data.get('unit_price') or D(0)
     tax = data.get('unit_tax') or D(0)
     price = compute_price(net=net,
                           gross=gross,
                           tax=tax,
                           keep_gross=keep_gross)
     data['unit_price_untaxed'] = price.net.amount
     data['unit_price'] = price.gross.amount
     data['unit_tax'] = compute_tax(tax)
     return cls.insert(**data)
    def test_compute_price_from_gross_fixed_discount(self):
        price = compute_price(gross=120, tax=0.2, keep_gross=True)
        self.assertEqual(price.net.amount, D('100'))
        self.assertEqual(price.gross.amount, D('120'))
        self.assertEqual(price.tax.amount, D('20'))
        self.assertEqual(price.currency, 'EUR')

        discount = compute_discount(price=price,
                                    tax=0.2,
                                    discount_amount=10,
                                    from_gross=True)

        self.assertEqual(discount.net.amount, D('91.67'))
        self.assertEqual(discount.gross.amount, D('110'))
        self.assertEqual(discount.tax.amount, D('18.33'))
        self.assertEqual(discount.currency, 'EUR')
    def test_compute_price_from_net_fixed_discount(self):
        price = compute_price(net=100, tax=0.2, keep_gross=False)
        self.assertEqual(price.net.amount, D('100'))
        self.assertEqual(price.gross.amount, D('120'))
        self.assertEqual(price.tax.amount, D('20'))
        self.assertEqual(price.currency, 'EUR')

        discount = compute_discount(price=price,
                                    tax=0.2,
                                    discount_amount=10,
                                    from_gross=False)

        self.assertEqual(discount.net.amount, D('90'))
        self.assertEqual(discount.gross.amount, D('108'))
        self.assertEqual(discount.tax.amount, D('18'))
        self.assertEqual(discount.currency, 'EUR')
    def test_compute_price_from_net_no_tax_fixed_and_percentage_discount(self):
        price = compute_price(net=100, keep_gross=False)
        self.assertEqual(price.net.amount, D('100'))
        self.assertEqual(price.gross.amount, D('100'))
        self.assertEqual(price.tax.amount, D(0))
        self.assertEqual(price.currency, 'EUR')

        discount = compute_discount(price=price,
                                    discount_amount=9.99,
                                    discount_percent=0.1,
                                    from_gross=False)
        # for now only discount_amount is applied if both discount_amount and
        # discount_percent are set
        self.assertEqual(discount.net.amount, D('90.01'))
        self.assertEqual(discount.gross.amount, D('90.01'))
        self.assertEqual(discount.tax.amount, D(0))
        self.assertEqual(discount.currency, 'EUR')
    def test_compute_price_from_gross_fixed_and_percentage_discount(self):
        price = compute_price(gross=120, tax=0.2, keep_gross=True)
        self.assertEqual(price.net.amount, D('100'))
        self.assertEqual(price.gross.amount, D('120'))
        self.assertEqual(price.tax.amount, D('20'))
        self.assertEqual(price.currency, 'EUR')

        discount = compute_discount(price=price,
                                    tax=0.2,
                                    discount_amount=10,
                                    discount_percent=0.1,
                                    from_gross=True)
        # for now only discount_amount is applied if both discount_amount and
        # discount_percent are set
        self.assertEqual(discount.net.amount, D('91.67'))
        self.assertEqual(discount.gross.amount, D('110'))
        self.assertEqual(discount.tax.amount, D('18.33'))
        self.assertEqual(discount.currency, 'EUR')
Example #10
0
    def test_compute_price_from_net_fixed_and_percentage_discount(self):
        price = compute_price(net=83.33, tax=0.2, keep_gross=False)
        self.assertEqual(price.net.amount, D('83.33'))
        self.assertEqual(price.gross.amount, D('100'))
        self.assertEqual(price.tax.amount, D('16.67'))
        self.assertEqual(price.currency, 'EUR')

        discount = compute_discount(price=price,
                                    tax=0.2,
                                    discount_amount=9.99,
                                    discount_percent=0.1,
                                    from_gross=False)
        # for now only discount_amount is applied if both discount_amount and
        # discount_percent are set
        self.assertEqual(discount.net.amount, D('73.34'))
        self.assertEqual(discount.gross.amount, D('88.01'))
        self.assertEqual(discount.tax.amount, D('14.67'))
        self.assertEqual(discount.currency, 'EUR')
Example #11
0
    def compute(self):
        """Compute order line total amount

        * check unit_price consistency
        * compute tax if any
        * compute line total amount

        TODO: maybe add configuration options for computation behaviours, for
        example computation based on unit_price or unit_price_untaxed
        """

        if not self.order.price_list:
            self.check_unit_price()
            if self.unit_price != D(0) and self.unit_price_untaxed == D(0):
                # compute unit_price_untaxed based on unit_price
                price = compute_price(net=self.unit_price,
                                      gross=self.unit_price,
                                      tax=compute_tax(self.unit_tax),
                                      keep_gross=True)
            elif self.unit_price_untaxed != D(0) and self.unit_price == D(0):
                # compute unit_price based on unit_price_untaxed
                price = compute_price(net=self.unit_price_untaxed,
                                      gross=self.unit_price_untaxed,
                                      tax=compute_tax(self.unit_tax),
                                      keep_gross=False)
            elif self.unit_price_untaxed != D(0) and self.unit_price != D(0):
                # compute unit_price_untaxed based on unit_price
                price = compute_price(net=self.unit_price,
                                      gross=self.unit_price,
                                      tax=compute_tax(self.unit_tax),
                                      keep_gross=True)
            else:
                raise LineException(
                    """Can not find a strategy to compute price""")

            self.unit_price_untaxed = price.net.amount
            self.unit_price = price.gross.amount
            self.unit_tax = compute_tax(self.unit_tax)
        else:
            # compute unit price based on price list
            price_list_item = self.registry.Sale.PriceList.Item.query(
            ).filter_by(price_list=self.order.price_list).filter_by(
                item=self.item).one_or_none()
            if price_list_item:
                self.unit_price = price_list_item.unit_price
                self.unit_price_untaxed = price_list_item.unit_price_untaxed
                self.unit_tax = price_list_item.unit_tax
            else:
                raise LineException("""Can not find a price for %r on %r""" %
                                    (self.item, self.order.price_list))

        # compute total amount
        self.amount_total = D(self.unit_price * self.quantity)
        self.amount_untaxed = D(self.unit_price_untaxed * self.quantity)
        self.amount_tax = self.amount_total - self.amount_untaxed

        # compute total amount after discount
        if self.amount_discount_untaxed != D('0'):
            price = compute_price(net=self.amount_untaxed,
                                  tax=self.unit_tax,
                                  keep_gross=False)
            discount = compute_discount(
                price=price,
                tax=self.unit_tax,
                discount_amount=self.amount_discount_untaxed,
                from_gross=False)

            self.amount_total = discount.gross.amount
            self.amount_untaxed = discount.net.amount
            self.amount_tax = discount.tax.amount
            return

        if self.amount_discount_percentage_untaxed != D('0'):
            price = compute_price(net=self.amount_untaxed,
                                  tax=self.unit_tax,
                                  keep_gross=False)
            discount = compute_discount(
                price=price,
                tax=self.unit_tax,
                discount_percent=self.amount_discount_percentage_untaxed,
                from_gross=False)

            self.amount_total = discount.gross.amount
            self.amount_untaxed = discount.net.amount
            self.amount_tax = discount.tax.amount
            return

        if self.amount_discount != D('0'):
            price = compute_price(gross=self.amount_total,
                                  tax=self.unit_tax,
                                  keep_gross=True)
            discount = compute_discount(price=price,
                                        tax=self.unit_tax,
                                        discount_amount=self.amount_discount,
                                        from_gross=True)
            self.amount_total = discount.gross.amount
            self.amount_untaxed = discount.net.amount
            self.amount_tax = discount.tax.amount
            return

        if self.amount_discount_percentage != D('0'):
            price = compute_price(gross=self.amount_total,
                                  tax=self.unit_tax,
                                  keep_gross=True)
            discount = compute_discount(
                price=price,
                tax=self.unit_tax,
                discount_percent=self.amount_discount_percentage,
                from_gross=True)

            self.amount_total = discount.gross.amount
            self.amount_untaxed = discount.net.amount
            self.amount_tax = discount.tax.amount
            return
Example #12
0
 def test_compute_price_from_gross_no_tax(self):
     price = compute_price(gross=100, keep_gross=True)
     self.assertEqual(price.net.amount, D('100'))
     self.assertEqual(price.gross.amount, D('100'))
     self.assertEqual(price.tax.amount, D(0))