Add start/end date to tax
issue3600 review2771002
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
* Add start/end date to tax
|
||||
* Use account of write-off journal as default
|
||||
* Add write-off journal type
|
||||
* Add description on write-off move
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
import datetime
|
||||
from decimal import Decimal
|
||||
from sql.aggregate import Sum
|
||||
|
||||
@@ -347,6 +348,8 @@ class TaxTemplate(ModelSQL, ModelView):
|
||||
description = fields.Char('Description', required=True, translate=True)
|
||||
group = fields.Many2One('account.tax.group', 'Group')
|
||||
sequence = fields.Integer('Sequence')
|
||||
start_date = fields.Date('Starting Date')
|
||||
end_date = fields.Date('Ending Date')
|
||||
amount = fields.Numeric('Amount', digits=(16, 8),
|
||||
states={
|
||||
'required': Eval('type') == 'fixed',
|
||||
@@ -449,7 +452,8 @@ class TaxTemplate(ModelSQL, ModelView):
|
||||
res = {}
|
||||
for field in ('name', 'description', 'sequence', 'amount',
|
||||
'rate', 'type', 'invoice_base_sign', 'invoice_tax_sign',
|
||||
'credit_note_base_sign', 'credit_note_tax_sign'):
|
||||
'credit_note_base_sign', 'credit_note_tax_sign',
|
||||
'start_date', 'end_date'):
|
||||
if not tax or getattr(tax, field) != getattr(self, field):
|
||||
res[field] = getattr(self, field)
|
||||
for field in ('group',):
|
||||
@@ -571,6 +575,8 @@ class Tax(ModelSQL, ModelView):
|
||||
}, depends=['parent'])
|
||||
active = fields.Boolean('Active')
|
||||
sequence = fields.Integer('Sequence', help='Use to order the taxes')
|
||||
start_date = fields.Date('Starting Date')
|
||||
end_date = fields.Date('Ending Date')
|
||||
currency_digits = fields.Function(fields.Integer('Currency Digits'),
|
||||
'on_change_with_currency_digits')
|
||||
amount = fields.Numeric('Amount', digits=(16, Eval('currency_digits', 2)),
|
||||
@@ -749,13 +755,17 @@ class Tax(ModelSQL, ModelView):
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def _unit_compute(cls, taxes, price_unit):
|
||||
def _unit_compute(cls, taxes, price_unit, date):
|
||||
res = []
|
||||
for tax in taxes:
|
||||
start_date = tax.start_date or datetime.date.min
|
||||
end_date = tax.end_date or datetime.date.max
|
||||
if not (start_date <= date <= end_date):
|
||||
continue
|
||||
if tax.type != 'none':
|
||||
res.append(tax._process_tax(price_unit))
|
||||
if len(tax.childs):
|
||||
res.extend(cls._unit_compute(tax.childs, price_unit))
|
||||
res.extend(cls._unit_compute(tax.childs, price_unit, date))
|
||||
return res
|
||||
|
||||
@classmethod
|
||||
@@ -766,16 +776,20 @@ class Tax(ModelSQL, ModelView):
|
||||
return sorted(taxes, key=lambda t: (t.sequence, t.id))
|
||||
|
||||
@classmethod
|
||||
def compute(cls, taxes, price_unit, quantity):
|
||||
def compute(cls, taxes, price_unit, quantity, date=None):
|
||||
'''
|
||||
Compute taxes for price_unit and quantity.
|
||||
Compute taxes for price_unit and quantity at the date.
|
||||
Return list of dict for each taxes and their childs with:
|
||||
base
|
||||
amount
|
||||
tax
|
||||
'''
|
||||
pool = Pool()
|
||||
Date = pool.get('ir.date')
|
||||
if date is None:
|
||||
date = Date.today()
|
||||
taxes = cls.sort_taxes(taxes)
|
||||
res = cls._unit_compute(taxes, price_unit)
|
||||
res = cls._unit_compute(taxes, price_unit, date)
|
||||
quantity = Decimal(str(quantity or 0.0))
|
||||
for row in res:
|
||||
row['base'] *= quantity
|
||||
|
||||
@@ -4,6 +4,7 @@ import unittest
|
||||
import doctest
|
||||
import datetime
|
||||
from decimal import Decimal
|
||||
from dateutil.relativedelta import relativedelta
|
||||
import trytond.tests.test_tryton
|
||||
from trytond.tests.test_tryton import test_view, test_depends, doctest_dropdb
|
||||
from trytond.tests.test_tryton import POOL, DB_NAME, USER, CONTEXT
|
||||
@@ -31,6 +32,7 @@ class AccountTestCase(unittest.TestCase):
|
||||
self.period = POOL.get('account.period')
|
||||
self.balance_non_deferral = POOL.get(
|
||||
'account.fiscalyear.balance_non_deferral', type='wizard')
|
||||
self.tax = POOL.get('account.tax')
|
||||
|
||||
def test0005views(self):
|
||||
'Test views'
|
||||
@@ -316,6 +318,111 @@ class AccountTestCase(unittest.TestCase):
|
||||
|
||||
transaction.cursor.rollback()
|
||||
|
||||
def test0040tax_compute(self):
|
||||
'Test tax compute'
|
||||
with Transaction().start(DB_NAME, USER, context=CONTEXT):
|
||||
today = datetime.date.today()
|
||||
|
||||
tax_account, = self.account.search([
|
||||
('name', '=', 'Main Tax'),
|
||||
])
|
||||
tax = self.tax()
|
||||
tax.name = tax.description = 'Test'
|
||||
tax.type = 'none'
|
||||
tax.invoice_account = tax_account
|
||||
tax.credit_note_account = tax_account
|
||||
|
||||
child1 = self.tax()
|
||||
child1.name = child1.description = 'Child 1'
|
||||
child1.type = 'percentage'
|
||||
child1.rate = Decimal('0.2')
|
||||
child1.invoice_account = tax_account
|
||||
child1.credit_note_account = tax_account
|
||||
child1.save()
|
||||
|
||||
child2 = self.tax()
|
||||
child2.name = child2.description = 'Child 1'
|
||||
child2.type = 'fixed'
|
||||
child2.amount = Decimal('10')
|
||||
child2.invoice_account = tax_account
|
||||
child2.credit_note_account = tax_account
|
||||
child2.save()
|
||||
|
||||
tax.childs = [child1, child2]
|
||||
tax.save()
|
||||
|
||||
self.assertEqual(self.tax.compute([tax], Decimal('100'), 2),
|
||||
[{
|
||||
'base': Decimal('200'),
|
||||
'amount': Decimal('40.0'),
|
||||
'tax': child1,
|
||||
}, {
|
||||
'base': Decimal('200'),
|
||||
'amount': Decimal('20'),
|
||||
'tax': child2,
|
||||
}])
|
||||
|
||||
child1.end_date = today + relativedelta(days=5)
|
||||
child1.save()
|
||||
self.assertEqual(self.tax.compute([tax], Decimal('100'), 2, today),
|
||||
[{
|
||||
'base': Decimal('200'),
|
||||
'amount': Decimal('40.0'),
|
||||
'tax': child1,
|
||||
}, {
|
||||
'base': Decimal('200'),
|
||||
'amount': Decimal('20'),
|
||||
'tax': child2,
|
||||
}])
|
||||
|
||||
child1.start_date = today + relativedelta(days=1)
|
||||
child1.save()
|
||||
self.assertEqual(self.tax.compute([tax], Decimal('100'), 2, today),
|
||||
[{
|
||||
'base': Decimal('200'),
|
||||
'amount': Decimal('20'),
|
||||
'tax': child2,
|
||||
}])
|
||||
self.assertEqual(self.tax.compute([tax], Decimal('100'), 2,
|
||||
today + relativedelta(days=1)), [{
|
||||
'base': Decimal('200'),
|
||||
'amount': Decimal('40.0'),
|
||||
'tax': child1,
|
||||
}, {
|
||||
'base': Decimal('200'),
|
||||
'amount': Decimal('20'),
|
||||
'tax': child2,
|
||||
}])
|
||||
self.assertEqual(self.tax.compute([tax], Decimal('100'), 2,
|
||||
today + relativedelta(days=5)), [{
|
||||
'base': Decimal('200'),
|
||||
'amount': Decimal('40.0'),
|
||||
'tax': child1,
|
||||
}, {
|
||||
'base': Decimal('200'),
|
||||
'amount': Decimal('20'),
|
||||
'tax': child2,
|
||||
}])
|
||||
self.assertEqual(self.tax.compute([tax], Decimal('100'), 2,
|
||||
today + relativedelta(days=6)), [{
|
||||
'base': Decimal('200'),
|
||||
'amount': Decimal('20'),
|
||||
'tax': child2,
|
||||
}])
|
||||
|
||||
child1.end_date = None
|
||||
child1.save()
|
||||
self.assertEqual(self.tax.compute([tax], Decimal('100'), 2,
|
||||
today + relativedelta(days=6)), [{
|
||||
'base': Decimal('200'),
|
||||
'amount': Decimal('40.0'),
|
||||
'tax': child1,
|
||||
}, {
|
||||
'base': Decimal('200'),
|
||||
'amount': Decimal('20'),
|
||||
'tax': child2,
|
||||
}])
|
||||
|
||||
|
||||
def suite():
|
||||
suite = trytond.tests.test_tryton.suite()
|
||||
|
||||
@@ -14,6 +14,10 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="group"/>
|
||||
<label name="sequence"/>
|
||||
<field name="sequence"/>
|
||||
<label name="start_date"/>
|
||||
<field name="start_date"/>
|
||||
<label name="end_date"/>
|
||||
<field name="end_date"/>
|
||||
<label name="type"/>
|
||||
<field name="type"/>
|
||||
<group col="1" id="label_amount_rate">
|
||||
|
||||
@@ -14,6 +14,10 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="group"/>
|
||||
<label name="sequence"/>
|
||||
<field name="sequence"/>
|
||||
<label name="start_date"/>
|
||||
<field name="start_date"/>
|
||||
<label name="end_date"/>
|
||||
<field name="end_date"/>
|
||||
<label name="type"/>
|
||||
<field name="type"/>
|
||||
<group col="1" id="label_amount_rate">
|
||||
|
||||
Reference in New Issue
Block a user