diff --git a/account_asset_management/README.rst b/account_asset_management/README.rst
index 51da1743e..615fb150c 100644
--- a/account_asset_management/README.rst
+++ b/account_asset_management/README.rst
@@ -58,6 +58,11 @@ The module in NOT compatible with the standard account_asset module.
Changelog
=========
+12.0.1.1.0 (2019-07-08)
+~~~~~~~~~~~~~~~~~~~~~~~
+
+* [IMP] Add option to calculate depreciation table by days
+
12.0.1.0.0 (2019-01-13)
~~~~~~~~~~~~~~~~~~~~~~~
@@ -94,6 +99,8 @@ Contributors
- Akim Juillerat
- Henrik Norlin (Apps2GROW)
- Maxence Groine
+- Kitti Upariphutthiphong
+- Saran Lim.
Maintainers
~~~~~~~~~~~
diff --git a/account_asset_management/__manifest__.py b/account_asset_management/__manifest__.py
index 32d504301..57385e6cd 100644
--- a/account_asset_management/__manifest__.py
+++ b/account_asset_management/__manifest__.py
@@ -4,7 +4,7 @@
{
'name': 'Assets Management',
- 'version': '12.0.2.0.0',
+ 'version': '12.0.2.1.0',
'license': 'AGPL-3',
'depends': [
'account',
diff --git a/account_asset_management/models/account_asset.py b/account_asset_management/models/account_asset.py
index c2ef18192..ed280dfcd 100644
--- a/account_asset_management/models/account_asset.py
+++ b/account_asset_management/models/account_asset.py
@@ -162,6 +162,23 @@ class AccountAsset(models.Model):
# " * Ending Date: Choose the time between 2 depreciations "
# "and the date the depreciations won't go beyond."
)
+ days_calc = fields.Boolean(
+ string='Calculate by days',
+ default=False,
+ help="Use number of days to calculate depreciation amount",
+ )
+ use_leap_years = fields.Boolean(
+ string='Use leap years',
+ default=False,
+ help="If not set, the system will distribute evenly the amount to "
+ "amortize across the years, based on the number of years. "
+ "So the amount per year will be the "
+ "depreciation base / number of years.\n "
+ "If set, the system will consider if the current year "
+ "is a leap year. The amount to depreciate per year will be "
+ "calculated as depreciation base / (depreciation end date - "
+ "start date + 1) * days in the current year.",
+ )
prorata = fields.Boolean(
string='Prorata Temporis', readonly=True,
states={'draft': [('readonly', False)]},
@@ -276,6 +293,8 @@ class AccountAsset(models.Model):
'method_number': profile.method_number,
'method_time': profile.method_time,
'method_period': profile.method_period,
+ 'days_calc': profile.days_calc,
+ 'use_leap_years': profile.use_leap_years,
'method_progress_factor': profile.method_progress_factor,
'prorata': profile.prorata,
'account_analytic_id': profile.account_analytic_id,
@@ -287,6 +306,16 @@ class AccountAsset(models.Model):
if self.method_time != 'year':
self.prorata = True
+ @api.onchange('method_number')
+ def _onchange_method_number(self):
+ if self.method_number and self.method_end:
+ self.method_end = False
+
+ @api.onchange('method_end')
+ def _onchange_method_end(self):
+ if self.method_end and self.method_number:
+ self.method_number = 0
+
@api.model
def create(self, vals):
if vals.get('method_time') != 'year' and not vals.get('prorata'):
@@ -554,13 +583,14 @@ class AccountAsset(models.Model):
if amount:
vals = {
'previous_id': depr_line.id,
- 'amount': amount,
+ 'amount': round(amount, digits),
'asset_id': asset.id,
'name': name,
'line_date': line['date'],
+ 'line_days': line['days'],
'init_entry': entry['init'],
}
- depreciated_value += amount
+ depreciated_value += round(amount, digits)
depr_line = line_obj.create(vals)
else:
seq -= 1
@@ -645,7 +675,7 @@ class AccountAsset(models.Model):
return depreciation_start_date
def _get_depreciation_stop_date(self, depreciation_start_date):
- if self.method_time == 'year':
+ if self.method_time == 'year' and not self.method_end:
depreciation_stop_date = depreciation_start_date + \
relativedelta(years=self.method_number, days=-1)
elif self.method_time == 'number':
@@ -663,7 +693,7 @@ class AccountAsset(models.Model):
elif self.method_period == 'year':
depreciation_stop_date = depreciation_start_date + \
relativedelta(years=self.method_number, days=-1)
- elif self.method_time == 'end':
+ elif self.method_time == 'year' and self.method_end:
depreciation_stop_date = self.method_end
return depreciation_stop_date
@@ -680,7 +710,21 @@ class AccountAsset(models.Model):
amount = entry['fy_amount'] - amount * full_periods
return amount
- def _compute_year_amount(self, residual_amount):
+ def _get_amount_linear(
+ self, depreciation_start_date, depreciation_stop_date, entry):
+ """
+ Override this method if you want to compute differently the
+ yearly amount.
+ """
+ if not self.use_leap_years and self.method_number:
+ return self.depreciation_base / self.method_number
+ year = entry['date_stop'].year
+ cy_days = calendar.isleap(year) and 366 or 365
+ days = (depreciation_stop_date - depreciation_start_date).days + 1
+ return (self.depreciation_base / days) * cy_days
+
+ def _compute_year_amount(self, residual_amount, depreciation_start_date,
+ depreciation_stop_date, entry):
"""
Localization: override this method to change the degressive-linear
calculation logic according to local legislation.
@@ -689,8 +733,8 @@ class AccountAsset(models.Model):
raise UserError(
_("The '_compute_year_amount' method is only intended for "
"Time Method 'Number of Years."))
-
- year_amount_linear = self.depreciation_base / self.method_number
+ year_amount_linear = self._get_amount_linear(
+ depreciation_start_date, depreciation_stop_date, entry)
if self.method == 'linear':
return year_amount_linear
if self.method == 'linear-limit':
@@ -750,18 +794,30 @@ class AccountAsset(models.Model):
# last entry
if not (self.method_time == 'number' and
len(line_dates) == self.method_number):
- line_dates.append(line_date)
+ if self.days_calc:
+ line_dates.append(stop_date)
+ else:
+ line_dates.append(line_date)
return line_dates
- def _compute_depreciation_amount_per_fiscal_year(self, table, line_dates):
+ def _compute_depreciation_amount_per_fiscal_year(
+ self, table, line_dates, depreciation_start_date,
+ depreciation_stop_date):
digits = self.env['decimal.precision'].precision_get('Account')
fy_residual_amount = self.depreciation_base
i_max = len(table) - 1
asset_sign = self.depreciation_base >= 0 and 1 or -1
+ day_amount = 0.0
+ if self.days_calc:
+ days = (depreciation_stop_date - depreciation_start_date).days + 1
+ day_amount = self.depreciation_base / days
+
for i, entry in enumerate(table):
if self.method_time == 'year':
- year_amount = self._compute_year_amount(fy_residual_amount)
+ year_amount = self._compute_year_amount(
+ fy_residual_amount, depreciation_start_date,
+ depreciation_stop_date, entry)
if self.method_period == 'year':
period_amount = year_amount
elif self.method_period == 'quarter':
@@ -792,6 +848,7 @@ class AccountAsset(models.Model):
entry.update({
'period_amount': period_amount,
'fy_amount': fy_amount,
+ 'day_amount': day_amount,
})
if self.method_time == 'year':
fy_residual_amount -= fy_amount
@@ -816,26 +873,36 @@ class AccountAsset(models.Model):
fy_amount_check = 0.0
fy_amount = entry['fy_amount']
li_max = len(line_dates) - 1
+ prev_date = max(entry['date_start'], depreciation_start_date)
for li, line_date in enumerate(line_dates):
-
+ line_days = (line_date - prev_date).days + 1
if round(remaining_value, digits) == 0.0:
break
if (line_date > min(entry['date_stop'],
depreciation_stop_date) and not
(i == i_max and li == li_max)):
+ prev_date = line_date
break
+ else:
+ prev_date = line_date + relativedelta(days=1)
if self.method == 'degr-linear' \
and asset_sign * (fy_amount - fy_amount_check) < 0:
break
if i == 0 and li == 0:
- amount = self._get_first_period_amount(
- table, entry, depreciation_start_date, line_dates)
- amount = round(amount, digits)
+ if entry.get('day_amount') > 0.0:
+ amount = line_days * entry.get('day_amount')
+ else:
+ amount = self._get_first_period_amount(
+ table, entry, depreciation_start_date, line_dates)
+ amount = round(amount, digits)
else:
- amount = entry.get('period_amount')
+ if entry.get('day_amount') > 0.0:
+ amount = line_days * entry.get('day_amount')
+ else:
+ amount = entry.get('period_amount')
# last year, last entry
# Handle rounding deviations.
@@ -847,6 +914,7 @@ class AccountAsset(models.Model):
fy_amount_check += amount
line = {
'date': line_date,
+ 'days': line_days,
'amount': amount,
'depreciated_value': depreciated_value,
'remaining_value': remaining_value,
@@ -862,7 +930,7 @@ class AccountAsset(models.Model):
# was compensated in the first FY depreciation line.
# The code has now been simplified with compensation
# always in last FT depreciation line.
- if self.method_time == 'year':
+ if self.method_time == 'year' and not entry.get('day_amount'):
if round(fy_amount_check - fy_amount, digits) != 0:
diff = fy_amount_check - fy_amount
amount = amount - diff
@@ -896,7 +964,8 @@ class AccountAsset(models.Model):
def _compute_depreciation_table(self):
table = []
- if self.method_time in ['year', 'number'] and not self.method_number:
+ if self.method_time in ['year', 'number'] \
+ and not self.method_number and not self.method_end:
return table
company = self.company_id
asset_date_start = self.date_start
@@ -922,7 +991,7 @@ class AccountAsset(models.Model):
line_dates = self._compute_line_dates(
table, depreciation_start_date, depreciation_stop_date)
table = self._compute_depreciation_amount_per_fiscal_year(
- table, line_dates,
+ table, line_dates, depreciation_start_date, depreciation_stop_date
)
# Step 2:
# Spread depreciation amount per fiscal year
diff --git a/account_asset_management/models/account_asset_line.py b/account_asset_management/models/account_asset_line.py
index 5fda7e66a..326f9c7a2 100644
--- a/account_asset_management/models/account_asset_line.py
+++ b/account_asset_management/models/account_asset_line.py
@@ -43,6 +43,10 @@ class AccountAssetLine(models.Model):
string='Amount Already Depreciated',
store=True)
line_date = fields.Date(string='Date', required=True)
+ line_days = fields.Integer(
+ string='Days',
+ readonly=True,
+ )
move_id = fields.Many2one(
comodel_name='account.move',
string='Depreciation Entry', readonly=True)
diff --git a/account_asset_management/models/account_asset_profile.py b/account_asset_management/models/account_asset_profile.py
index f2f03fa17..cd3b1f659 100644
--- a/account_asset_management/models/account_asset_profile.py
+++ b/account_asset_management/models/account_asset_profile.py
@@ -90,6 +90,22 @@ class AccountAssetProfile(models.Model):
"number of depreciation lines.\n"
" * Number of Years: Specify the number of years "
"for the depreciation.\n")
+ days_calc = fields.Boolean(
+ string='Calculate by days',
+ default=False,
+ help="Use number of days to calculate depreciation amount")
+ use_leap_years = fields.Boolean(
+ string='Use leap years',
+ default=False,
+ help="If not set, the system will distribute evenly the amount to "
+ "amortize across the years, based on the number of years. "
+ "So the amount per year will be the "
+ "depreciation base / number of years.\n "
+ "If set, the system will consider if the current year "
+ "is a leap year. The amount to depreciate per year will be "
+ "calculated as depreciation base / (depreciation end date - "
+ "start date + 1) * days in the current year.",
+ )
prorata = fields.Boolean(
string='Prorata Temporis',
help="Indicates that the first depreciation entry for this asset "
@@ -137,7 +153,7 @@ class AccountAssetProfile(models.Model):
'Number' and 'End' Time Methods.
"""
return [
- ('year', _('Number of Years')),
+ ('year', _('Number of Years or end date')),
]
@api.multi
diff --git a/account_asset_management/readme/CONTRIBUTORS.rst b/account_asset_management/readme/CONTRIBUTORS.rst
index bf16c0bbd..6afc965f8 100644
--- a/account_asset_management/readme/CONTRIBUTORS.rst
+++ b/account_asset_management/readme/CONTRIBUTORS.rst
@@ -7,3 +7,5 @@
- Akim Juillerat
- Henrik Norlin (Apps2GROW)
- Maxence Groine
+- Kitti Upariphutthiphong
+- Saran Lim.
diff --git a/account_asset_management/readme/HISTORY.rst b/account_asset_management/readme/HISTORY.rst
index c192efa62..d68c9d780 100644
--- a/account_asset_management/readme/HISTORY.rst
+++ b/account_asset_management/readme/HISTORY.rst
@@ -1,3 +1,8 @@
+12.0.2.1.0 (2019-10-21)
+~~~~~~~~~~~~~~~~~~~~~~~
+
+* [IMP] Add option to calculate depreciation table by days
+
12.0.1.0.0 (2019-01-13)
~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/account_asset_management/static/description/index.html b/account_asset_management/static/description/index.html
index 02e2eba13..20dd2d65e 100644
--- a/account_asset_management/static/description/index.html
+++ b/account_asset_management/static/description/index.html
@@ -380,34 +380,41 @@ the standard account_asset module from Odoo.
Table of contents
-
+
It is recommended to configure your Purchase Journal with “Group Invoice Lines” to avoid the
creation of separate assets per Supplier Invoice Line.
-
+
The module in NOT compatible with the standard account_asset module.
-
+
-
+
+
+- [IMP] Add option to calculate depreciation table by days
+
+
+
+
- [BREAKING] account.asset: parent_path has replaced parent_left & parent_right (TODO: migration script)
- [BREAKING] account.asset.recompute.trigger: depends on date_range.py (TODO: re-implement in account_fiscal_year.py)
@@ -415,7 +422,7 @@ creation of separate assets per Supplier Invoice Line.
-
+
Bugs are tracked on GitHub Issues.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed
@@ -423,15 +430,15 @@ If you spotted it first, help us smashing it by providing a detailed and welcome
Do not contact contributors directly about support or help with technical issues.
-
+
-
+
This module is maintained by the OCA.
OCA, or the Odoo Community Association, is a nonprofit organization whose
diff --git a/account_asset_management/tests/test_account_asset_management.py b/account_asset_management/tests/test_account_asset_management.py
index 2cc5622b0..a53d58b26 100644
--- a/account_asset_management/tests/test_account_asset_management.py
+++ b/account_asset_management/tests/test_account_asset_management.py
@@ -515,3 +515,96 @@ class TestAssetManagement(SavepointCase):
dlines = dlines.sorted(key=lambda l: l.line_date)
self.assertAlmostEqual(dlines[0].depreciated_value, 0.0)
self.assertAlmostEqual(dlines[-1].remaining_value, 0.0)
+
+ def test_12_prorata_days_calc(self):
+ """Prorata temporis depreciation with days calc option."""
+ asset = self.asset_model.create({
+ 'name': 'test asset',
+ 'profile_id': self.ref('account_asset_management.'
+ 'account_asset_profile_car_5Y'),
+ 'purchase_value': 3333,
+ 'salvage_value': 0,
+ 'date_start': time.strftime('%Y-07-07'),
+ 'method_time': 'year',
+ 'method_number': 5,
+ 'method_period': 'month',
+ 'prorata': True,
+ 'days_calc': True,
+ 'use_leap_years': False,
+ })
+ asset.compute_depreciation_board()
+ asset.refresh()
+ if calendar.isleap(date.today().year) or \
+ calendar.isleap(date.today().year + 1):
+ day_rate = 3333 / 1827 # 3333 / 1827 depreciation days
+ else:
+ day_rate = 3333 / 1826 # 3333 / 1826 depreciation days
+ for i in range(1, 10):
+ self.assertAlmostEqual(
+ asset.depreciation_line_ids[i].amount,
+ asset.depreciation_line_ids[i].line_days * day_rate, places=2)
+
+ # Last depreciation remaining
+ if calendar.isleap(date.today().year) or \
+ calendar.isleap(date.today().year + 1):
+ self.assertAlmostEqual(
+ asset.depreciation_line_ids[-1].amount, 11.05, places=2)
+ else:
+ self.assertAlmostEqual(
+ asset.depreciation_line_ids[-1].amount, 11.05, places=2)
+
+ def test_13_use_leap_year(self):
+ # When you use the depreciation with years method and using lap years,
+ # the depreciation amount is calculated as 10000 / 1826 days * 365 days
+ # = yearly depreciation amount of 1998.90.
+ # Then 1998.90 / 12 = 166.58
+ asset = self.asset_model.create({
+ 'name': 'test asset',
+ 'profile_id': self.ref('account_asset_management.'
+ 'account_asset_profile_car_5Y'),
+ 'purchase_value': 10000,
+ 'salvage_value': 0,
+ 'date_start': time.strftime('2019-01-01'),
+ 'method_time': 'year',
+ 'method_number': 5,
+ 'method_period': 'month',
+ 'prorata': False,
+ 'days_calc': False,
+ 'use_leap_years': True,
+ })
+ asset.compute_depreciation_board()
+ asset.refresh()
+ for i in range(2, 11):
+ self.assertAlmostEqual(
+ asset.depreciation_line_ids[i].amount, 166.58, places=2)
+ self.assertAlmostEqual(
+ asset.depreciation_line_ids[13].depreciated_value, 1998.90,
+ places=2)
+
+ def test_14_not_use_leap_year(self):
+ # When you run a depreciation with method = 'year' and no not use
+ # lap years you divide 1000 / 5 years = 2000, then divided by 12 months
+ # to get 166.67 per month, equal for all periods.
+ asset = self.asset_model.create({
+ 'name': 'test asset',
+ 'profile_id': self.ref('account_asset_management.'
+ 'account_asset_profile_car_5Y'),
+ 'purchase_value': 10000,
+ 'salvage_value': 0,
+ 'date_start': time.strftime('2019-01-01'),
+ 'method_time': 'year',
+ 'method_number': 5,
+ 'method_period': 'month',
+ 'prorata': False,
+ 'days_calc': False,
+ 'use_leap_years': False,
+ })
+ asset.compute_depreciation_board()
+ asset.refresh()
+ for i in range(1, 11):
+ self.assertAlmostEqual(
+ asset.depreciation_line_ids[1].amount, 166.67, places=2)
+ # In the last month of the fiscal year we compensate for the small
+ # deviations if that is necessary.
+ self.assertAlmostEqual(
+ asset.depreciation_line_ids[12].amount, 166.63, places=2)
diff --git a/account_asset_management/views/account_asset.xml b/account_asset_management/views/account_asset.xml
index 8c28fe939..182470eb2 100644
--- a/account_asset_management/views/account_asset.xml
+++ b/account_asset_management/views/account_asset.xml
@@ -65,7 +65,10 @@
attrs="{'invisible': [('method_time', 'not in', ['number', 'year'])], 'required': [('method_time', 'in', ['number', 'year'])]}"/>
+ attrs="{'required': [('method_time', '=', 'end')], 'invisible': [('method_time', 'in', ['number'])]}"/>
+
+
@@ -86,6 +89,7 @@
+
diff --git a/account_asset_management/views/account_asset_profile.xml b/account_asset_management/views/account_asset_profile.xml
index b6053505b..2f684a17d 100644
--- a/account_asset_management/views/account_asset_profile.xml
+++ b/account_asset_management/views/account_asset_profile.xml
@@ -29,6 +29,7 @@
+