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')
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')
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')
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
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))