From 805f3a610f5f986f3b92d2d91dc3f6fb02540346 Mon Sep 17 00:00:00 2001 From: Laurent Smet Date: Wed, 14 Feb 2018 10:23:23 +0100 Subject: [PATCH] [IMP] account_asset: improved depreciation dates management related to task id 29411 add selection field 'date_first_depreciation' on 'account.asset.asset' to manage the depreciation dates: -manual: set manually with the manual_date_first_depreciation field (defaulted on purchase date) -last_day_period: last day of purchase month/year add a selection field on 'account.asset.category' to set the default value as well. --- addons/account_asset/models/account_asset.py | 121 ++++++++++-------- .../views/account_asset_views.xml | 116 ++++++++++------- 2 files changed, 137 insertions(+), 100 deletions(-) diff --git a/addons/account_asset/models/account_asset.py b/addons/account_asset/models/account_asset.py index 3bb25d93e73..f8e0ce17c87 100644 --- a/addons/account_asset/models/account_asset.py +++ b/addons/account_asset/models/account_asset.py @@ -36,9 +36,16 @@ class AccountAssetCategory(models.Model): " * Ending Date: Choose the time between 2 depreciations and the date the depreciations won't go beyond.") method_end = fields.Date('Ending date') prorata = fields.Boolean(string='Prorata Temporis', help='Indicates that the first depreciation entry for this asset have to be done from the purchase date instead of the first of January') - open_asset = fields.Boolean(string='Auto-confirm Assets', help="Check this if you want to automatically confirm the assets of this category when created by invoices.") + open_asset = fields.Boolean(string='Auto-Confirm Assets', help="Check this if you want to automatically confirm the assets of this category when created by invoices.") group_entries = fields.Boolean(string='Group Journal Entries', help="Check this if you want to group the generated entries by categories.") type = fields.Selection([('sale', 'Sale: Revenue Recognition'), ('purchase', 'Purchase: Asset')], required=True, index=True, default='purchase') + date_first_depreciation = fields.Selection([ + ('last_day_period', 'Based on Last Day of Purchase Period'), + ('manual', 'Manual (Defaulted on Purchase Date)')], + string='Depreciation Dates', default='manual', required=True, + help='The way to compute the date of the first depreciation.\n' + ' * Based on last day of purchase period: The depreciation dates will be based on the last day of the purchase month or the purchase year (depending on the periodicity of the depreciations).\n' + ' * Based on purchase date: The depreciation dates will be based on the purchase date.') @api.onchange('account_asset_id') def onchange_account_asset(self): @@ -97,12 +104,25 @@ class AccountAssetAsset(models.Model): " * Number of Entries: Fix the number of entries and the time between 2 depreciations.\n" " * Ending Date: Choose the time between 2 depreciations and the date the depreciations won't go beyond.") prorata = fields.Boolean(string='Prorata Temporis', readonly=True, states={'draft': [('readonly', False)]}, - help='Indicates that the first depreciation entry for this asset have to be done from the purchase date instead of the first January / Start date of fiscal year') + help='Indicates that the first depreciation entry for this asset have to be done from the asset date (purchase date) instead of the first January / Start date of fiscal year') depreciation_line_ids = fields.One2many('account.asset.depreciation.line', 'asset_id', string='Depreciation Lines', readonly=True, states={'draft': [('readonly', False)], 'open': [('readonly', False)]}) salvage_value = fields.Float(string='Salvage Value', digits=0, readonly=True, states={'draft': [('readonly', False)]}, help="It is the amount you plan to have that you cannot depreciate.") invoice_id = fields.Many2one('account.invoice', string='Invoice', states={'draft': [('readonly', False)]}, copy=False) type = fields.Selection(related="category_id.type", string='Type', required=True) + date_first_depreciation = fields.Selection([ + ('last_day_period', 'Based on Last Day of Purchase Period'), + ('manual', 'Manual')], + string='Depreciation Dates', default='manual', + readonly=True, states={'draft': [('readonly', False)]}, required=True, + help='The way to compute the date of the first depreciation.\n' + ' * Based on last day of purchase period: The depreciation dates will be based on the last day of the purchase month or the purchase year (depending on the periodicity of the depreciations).\n' + ' * Based on purchase date: The depreciation dates will be based on the purchase date.\n') + first_depreciation_manual_date = fields.Date( + string='First Depreciation Date', + readonly=True, states={'draft': [('readonly', False)]}, + help='Note that this date does not alter the computation of the first journal entry in case of prorata temporis assets. It simply changes its accounting date' + ) @api.multi def unlink(self): @@ -114,22 +134,6 @@ class AccountAssetAsset(models.Model): raise UserError(_('You cannot delete a document that contains posted entries.')) return super(AccountAssetAsset, self).unlink() - @api.multi - def _get_last_depreciation_date(self): - """ - @param id: ids of a account.asset.asset objects - @return: Returns a dictionary of the effective dates of the last depreciation entry made for given asset ids. If there isn't any, return the purchase date of this asset - """ - self.env.cr.execute(""" - SELECT a.id as id, COALESCE(MAX(m.date),a.date) AS date - FROM account_asset_asset a - LEFT JOIN account_asset_depreciation_line rel ON (rel.asset_id = a.id) - LEFT JOIN account_move m ON (rel.move_id = m.id) - WHERE a.id IN %s - GROUP BY a.id, m.date """, (tuple(self.ids),)) - result = dict(self.env.cr.fetchall()) - return result - @api.model def _cron_generate_entries(self): self.compute_generated_entries(datetime.today()) @@ -160,25 +164,25 @@ class AccountAssetAsset(models.Model): if self.prorata: amount = amount_to_depr / self.method_number if sequence == 1: + date = datetime.strptime(self.date, DF) if self.method_period % 12 != 0: - date = datetime.strptime(self.date, '%Y-%m-%d') month_days = calendar.monthrange(date.year, date.month)[1] days = month_days - date.day + 1 amount = (amount_to_depr / self.method_number) / month_days * days else: - days = (self.company_id.compute_fiscalyear_dates(depreciation_date)['date_to'] - depreciation_date).days + 1 + days = (self.company_id.compute_fiscalyear_dates(date)['date_to'] - date).days + 1 amount = (amount_to_depr / self.method_number) / total_days * days elif self.method == 'degressive': amount = residual_amount * self.method_progress_factor if self.prorata: if sequence == 1: + date = datetime.strptime(self.date, DF) if self.method_period % 12 != 0: - date = datetime.strptime(self.date, '%Y-%m-%d') month_days = calendar.monthrange(date.year, date.month)[1] days = month_days - date.day + 1 amount = (residual_amount * self.method_progress_factor) / month_days * days else: - days = (self.company_id.compute_fiscalyear_dates(depreciation_date)['date_to'] - depreciation_date).days + 1 + days = (self.company_id.compute_fiscalyear_dates(date)['date_to'] - date).days + 1 amount = (residual_amount * self.method_progress_factor) / total_days * days return amount @@ -206,31 +210,32 @@ class AccountAssetAsset(models.Model): if self.value_residual != 0.0: amount_to_depr = residual_amount = self.value_residual - if self.prorata: - # if we already have some previous validated entries, starting date is last entry + method perio - if posted_depreciation_line_ids and posted_depreciation_line_ids[-1].depreciation_date: - last_depreciation_date = datetime.strptime(posted_depreciation_line_ids[-1].depreciation_date, DF).date() - depreciation_date = last_depreciation_date + relativedelta(months=+self.method_period) - else: - depreciation_date = datetime.strptime(self._get_last_depreciation_date()[self.id], DF).date() - else: - # depreciation_date = 1st of January of purchase year if annual valuation, 1st of - # purchase month in other cases - if self.method_period >= 12: - asset_date = datetime.strptime(self.date[:4] + '-01-01', DF).date() - else: - asset_date = datetime.strptime(self.date[:7] + '-01', DF).date() - # if we already have some previous validated entries, starting date isn't 1st January but last entry + method period - if posted_depreciation_line_ids and posted_depreciation_line_ids[-1].depreciation_date: - last_depreciation_date = datetime.strptime(posted_depreciation_line_ids[-1].depreciation_date, DF).date() - depreciation_date = last_depreciation_date + relativedelta(months=+self.method_period) - else: - depreciation_date = asset_date - day = depreciation_date.day - month = depreciation_date.month - year = depreciation_date.year - total_days = (year % 4) and 365 or 366 + # if we already have some previous validated entries, starting date is last entry + method period + if posted_depreciation_line_ids and posted_depreciation_line_ids[-1].depreciation_date: + last_depreciation_date = datetime.strptime(posted_depreciation_line_ids[-1].depreciation_date, DF).date() + depreciation_date = last_depreciation_date + relativedelta(months=+self.method_period) + else: + # depreciation_date computed from the purchase date + depreciation_date = self.date + depreciation_date = datetime.strptime(depreciation_date, DF) + if self.date_first_depreciation == 'last_day_period': + # depreciation_date = the last day of the month + depreciation_date = depreciation_date + relativedelta(day=31) + # ... or fiscalyear depending the number of period + if self.method_period == 12: + depreciation_date = depreciation_date + relativedelta(month=self.company_id.fiscalyear_last_month) + depreciation_date = depreciation_date + relativedelta(day=self.company_id.fiscalyear_last_day) + if datetime.strftime(depreciation_date, DF) < self.date: + depreciation_date = depreciation_date + relativedelta(years=1) + elif self.first_depreciation_manual_date and self.first_depreciation_manual_date != self.date: + # depreciation_date set manually from the 'first_depreciation_manual_date' field + depreciation_date = self.first_depreciation_manual_date + depreciation_date = datetime.strptime(depreciation_date, DF) + + depreciation_date = depreciation_date.date() + total_days = (depreciation_date.year % 4) and 365 or 366 + month_day = depreciation_date.day undone_dotation_number = self._compute_board_undone_dotation_nb(depreciation_date, total_days) for x in range(len(posted_depreciation_line_ids), undone_dotation_number): @@ -250,11 +255,17 @@ class AccountAssetAsset(models.Model): 'depreciation_date': depreciation_date.strftime(DF), } commands.append((0, False, vals)) - # Considering Depr. Period as months - depreciation_date = date(year, month, day) + relativedelta(months=+self.method_period) - day = depreciation_date.day - month = depreciation_date.month - year = depreciation_date.year + + depreciation_date = depreciation_date + relativedelta(months=+self.method_period) + + if month_day > 28 and self.date_first_depreciation == 'manual': + max_day_in_month = calendar.monthrange(depreciation_date.year, depreciation_date.month)[1] + depreciation_date = depreciation_date.replace(day=min(max_day_in_month, month_day)) + + # datetime doesn't take into account that the number of days is not the same for each month + if not self.prorata and self.method_period % 12 != 0 and self.date_first_depreciation == 'last_day_period': + max_day_in_month = calendar.monthrange(depreciation_date.year, depreciation_date.month)[1] + depreciation_date = depreciation_date.replace(day=max_day_in_month) self.write({'depreciation_line_ids': commands}) @@ -359,6 +370,13 @@ class AccountAssetAsset(models.Model): def onchange_company_id(self): self.currency_id = self.company_id.currency_id.id + @api.multi + @api.onchange('date_first_depreciation') + def onchange_date_first_depreciation(self): + for record in self: + if record.date_first_depreciation == 'manual': + record.first_depreciation_manual_date = record.date + @api.multi @api.depends('depreciation_line_ids.move_id') def _entry_count(self): @@ -392,6 +410,7 @@ class AccountAssetAsset(models.Model): 'method_progress_factor': category.method_progress_factor, 'method_end': category.method_end, 'prorata': category.prorata, + 'date_first_depreciation': category.date_first_depreciation, } } diff --git a/addons/account_asset/views/account_asset_views.xml b/addons/account_asset/views/account_asset_views.xml index 41a44d7a53c..4d4c9cea441 100644 --- a/addons/account_asset/views/account_asset_views.xml +++ b/addons/account_asset/views/account_asset_views.xml @@ -10,57 +10,72 @@ account.asset.category
- -
-
+ - - - - - -
-