Merge lp:~openerp-dev/openobject-addons/7.0-account-assets_fixes-acl into lp:openobject-addons/7.0

Proposed by Anaël Closson (openerp)
Status: Needs review
Proposed branch: lp:~openerp-dev/openobject-addons/7.0-account-assets_fixes-acl
Merge into: lp:openobject-addons/7.0
Diff against target: 267 lines (+142/-23)
4 files modified
account_asset/account_asset.py (+33/-22)
account_asset/test/account_asset_wizard.yml (+1/-1)
account_asset/tests/__init__.py (+26/-0)
account_asset/tests/test_depreciation.py (+82/-0)
To merge this branch: bzr merge lp:~openerp-dev/openobject-addons/7.0-account-assets_fixes-acl
Reviewer Review Type Date Requested Status
OpenERP Core Team Pending
Review via email: mp+211361@code.launchpad.net
To post a comment you must log in.
9907. By Anaël Closson (openerp)

[FIX] account assets: prorata temporis tooltip should match the fix from revision 9906.

9908. By Martin Trigaux (OpenERP)

[IMP] use finds method account.fiscalyear

9909. By Martin Trigaux (OpenERP)

[FIX] copy should not keep history and move lines of previous asset

9910. By Martin Trigaux (OpenERP)

[FIX] compute correctly the depreciation lines to recreate in 'Ending Date' method

9911. By Martin Trigaux (OpenERP)

[ADD] some tests, fixed the test account_asset_wizard as the number of depreciation was fixed

Unmerged revisions

9911. By Martin Trigaux (OpenERP)

[ADD] some tests, fixed the test account_asset_wizard as the number of depreciation was fixed

9910. By Martin Trigaux (OpenERP)

[FIX] compute correctly the depreciation lines to recreate in 'Ending Date' method

9909. By Martin Trigaux (OpenERP)

[FIX] copy should not keep history and move lines of previous asset

9908. By Martin Trigaux (OpenERP)

[IMP] use finds method account.fiscalyear

9907. By Anaël Closson (openerp)

[FIX] account assets: prorata temporis tooltip should match the fix from revision 9906.

9906. By Anaël Closson (openerp)

[FIX] Assets depreciation: several fixes:
 - first depreciation always starts on 01/01/asset_purchase_year
 - prorata temporis is always computed against start of year

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'account_asset/account_asset.py'
--- account_asset/account_asset.py 2014-01-17 10:40:37 +0000
+++ account_asset/account_asset.py 2014-03-26 15:52:48 +0000
@@ -51,7 +51,7 @@
51 " * Number of Depreciations: Fix the number of depreciation lines and the time between 2 depreciations.\n" \51 " * Number of Depreciations: Fix the number of depreciation lines and the time between 2 depreciations.\n" \
52 " * Ending Date: Choose the time between 2 depreciations and the date the depreciations won't go beyond."),52 " * Ending Date: Choose the time between 2 depreciations and the date the depreciations won't go beyond."),
53 'method_end': fields.date('Ending date'),53 'method_end': fields.date('Ending date'),
54 'prorata':fields.boolean('Prorata Temporis', help='Indicates that the first depreciation entry for this asset have to be done from the purchase date instead of the first January'),54 'prorata':fields.boolean('Prorata Temporis', help='Indicates that the first depreciation entry for this asset have to be done from the purchase date instead of the first day of depreciation period.'),
55 'open_asset': fields.boolean('Skip Draft State', help="Check this if you want to automatically confirm the assets of this category when created by invoices."),55 'open_asset': fields.boolean('Skip Draft State', help="Check this if you want to automatically confirm the assets of this category when created by invoices."),
56 }56 }
5757
@@ -105,19 +105,16 @@
105105
106 def _compute_board_amount(self, cr, uid, asset, i, residual_amount, amount_to_depr, undone_dotation_number, posted_depreciation_line_ids, total_days, depreciation_date, context=None):106 def _compute_board_amount(self, cr, uid, asset, i, residual_amount, amount_to_depr, undone_dotation_number, posted_depreciation_line_ids, total_days, depreciation_date, context=None):
107 #by default amount = 0107 #by default amount = 0
108 assert undone_dotation_number > len(posted_depreciation_line_ids)
108 amount = 0109 amount = 0
109 if i == undone_dotation_number:110 if i == undone_dotation_number:
110 amount = residual_amount111 amount = residual_amount
111 else:112 else:
112 if asset.method == 'linear':113 if asset.method == 'linear':
113 amount = amount_to_depr / (undone_dotation_number - len(posted_depreciation_line_ids))114 amount = amount_to_depr / (undone_dotation_number - len(posted_depreciation_line_ids))
114 if asset.prorata:115 if asset.prorata and i == 1:
115 amount = amount_to_depr / asset.method_number
116 days = total_days - float(depreciation_date.strftime('%j'))
117 if i == 1:116 if i == 1:
118 amount = (amount_to_depr / asset.method_number) / total_days * days117 amount = amount * (30 - float(depreciation_date.strftime('%j')) % 30) / 30
119 elif i == undone_dotation_number:
120 amount = (amount_to_depr / asset.method_number) / total_days * (total_days - days)
121 elif asset.method == 'degressive':118 elif asset.method == 'degressive':
122 amount = residual_amount * asset.method_progress_factor119 amount = residual_amount * asset.method_progress_factor
123 if asset.prorata:120 if asset.prorata:
@@ -128,21 +125,29 @@
128 amount = (residual_amount * asset.method_progress_factor) / total_days * (total_days - days)125 amount = (residual_amount * asset.method_progress_factor) / total_days * (total_days - days)
129 return amount126 return amount
130127
128 # TODO in trunk: rename total_days into number_posted_lines
131 def _compute_board_undone_dotation_nb(self, cr, uid, asset, depreciation_date, total_days, context=None):129 def _compute_board_undone_dotation_nb(self, cr, uid, asset, depreciation_date, total_days, context=None):
132 undone_dotation_number = asset.method_number130 """Compute the number of remaining depreciation line to compute (skipping posted one)
131 asset: browse record (account.asset) of the current asset
132 depreciation_date: date of the next depreciation
133 total_days: the number
134 """
133 if asset.method_time == 'end':135 if asset.method_time == 'end':
134 end_date = datetime.strptime(asset.method_end, '%Y-%m-%d')136 end_date = datetime.strptime(asset.method_end, '%Y-%m-%d')
135 undone_dotation_number = 0137 undone_dotation_number = 0
136 while depreciation_date <= end_date:138 while depreciation_date <= end_date:
137 depreciation_date = (datetime(depreciation_date.year, depreciation_date.month, depreciation_date.day) + relativedelta(months=+asset.method_period))139 depreciation_date = (datetime(depreciation_date.year, depreciation_date.month, depreciation_date.day) + relativedelta(months=+asset.method_period))
138 undone_dotation_number += 1140 undone_dotation_number += 1
139 if asset.prorata:141 undone_dotation_number += self.pool.get('account.asset.depreciation.line').search(cr, uid, [('asset_id', '=', asset.id), ('move_id', '!=', False)], count=True)
140 undone_dotation_number += 1142 else:
143 undone_dotation_number = asset.method_number
141 return undone_dotation_number144 return undone_dotation_number
142145
143 def compute_depreciation_board(self, cr, uid, ids, context=None):146 def compute_depreciation_board(self, cr, uid, ids, context=None):
147 """Generate depreciation lines, skip posted entries and recreate unposted"""
144 depreciation_lin_obj = self.pool.get('account.asset.depreciation.line')148 depreciation_lin_obj = self.pool.get('account.asset.depreciation.line')
145 currency_obj = self.pool.get('res.currency')149 currency_obj = self.pool.get('res.currency')
150 fy_obj = self.pool.get('account.fiscalyear')
146 for asset in self.browse(cr, uid, ids, context=context):151 for asset in self.browse(cr, uid, ids, context=context):
147 if asset.value_residual == 0.0:152 if asset.value_residual == 0.0:
148 continue153 continue
@@ -155,23 +160,29 @@
155 if asset.prorata:160 if asset.prorata:
156 depreciation_date = datetime.strptime(self._get_last_depreciation_date(cr, uid, [asset.id], context)[asset.id], '%Y-%m-%d')161 depreciation_date = datetime.strptime(self._get_last_depreciation_date(cr, uid, [asset.id], context)[asset.id], '%Y-%m-%d')
157 else:162 else:
158 # depreciation_date = 1st January of purchase year163 # depreciation_date = first day of current period
159 purchase_date = datetime.strptime(asset.purchase_date, '%Y-%m-%d')164 purchase_date = datetime.strptime(asset.purchase_date, '%Y-%m-%d')
160 #if we already have some previous validated entries, starting date isn't 1st January but last entry + method period165
166 #if we already have some previous validated entries, starting date isn't 1st day of period but last entry + method period
161 if (len(posted_depreciation_line_ids)>0):167 if (len(posted_depreciation_line_ids)>0):
162 last_depreciation_date = datetime.strptime(depreciation_lin_obj.browse(cr,uid,posted_depreciation_line_ids[0],context=context).depreciation_date, '%Y-%m-%d')168 last_depreciation_date = datetime.strptime(depreciation_lin_obj.browse(cr,uid,posted_depreciation_line_ids[0],context=context).depreciation_date, '%Y-%m-%d')
163 depreciation_date = (last_depreciation_date+relativedelta(months=+asset.method_period))169 depreciation_date = (last_depreciation_date+relativedelta(months=+asset.method_period))
164 else:170 else:
165 depreciation_date = datetime(purchase_date.year, 1, 1)171 # else we should start at the first day of the period, relative to the start of fiscal year
172 fiscal_year_ids = fy_obj.finds(cr, uid, purchase_date, context=context)
173 fiscal_year = fiscal_year_ids and fy_obj.browse(cr, uid, fiscal_year_ids[0], context=context)
174 delta = relativedelta(purchase_date, (fiscal_year and datetime.strptime(fiscal_year.date_start, '%Y-%m-%d') or datetime(purchase_date.year, 1, 1)))
175 period_start = purchase_date + relativedelta(months=-((delta.years * 12 + delta.months) % asset.method_period))
176 depreciation_date = datetime(period_start.year, period_start.month, 1)
177
166 day = depreciation_date.day178 day = depreciation_date.day
167 month = depreciation_date.month179 month = depreciation_date.month
168 year = depreciation_date.year180 year = depreciation_date.year
169 total_days = (year % 4) and 365 or 366181 total_days = asset.method_period * 30 # we use month of 30 days for accounting
170182
171 undone_dotation_number = self._compute_board_undone_dotation_nb(cr, uid, asset, depreciation_date, total_days, context=context)183 undone_dotation_number = self._compute_board_undone_dotation_nb(cr, uid, asset, depreciation_date, len(posted_depreciation_line_ids), context=context)
172 for x in range(len(posted_depreciation_line_ids), undone_dotation_number):184 for sequence in range(len(posted_depreciation_line_ids) + 1, undone_dotation_number + 1):
173 i = x + 1185 amount = self._compute_board_amount(cr, uid, asset, sequence, residual_amount, amount_to_depr, undone_dotation_number, posted_depreciation_line_ids, total_days, depreciation_date, context=context)
174 amount = self._compute_board_amount(cr, uid, asset, i, residual_amount, amount_to_depr, undone_dotation_number, posted_depreciation_line_ids, total_days, depreciation_date, context=context)
175 company_currency = asset.company_id.currency_id.id186 company_currency = asset.company_id.currency_id.id
176 current_currency = asset.currency_id.id187 current_currency = asset.currency_id.id
177 # compute amount into company currency188 # compute amount into company currency
@@ -180,8 +191,8 @@
180 vals = {191 vals = {
181 'amount': amount,192 'amount': amount,
182 'asset_id': asset.id,193 'asset_id': asset.id,
183 'sequence': i,194 'sequence': sequence,
184 'name': str(asset.id) +'/' + str(i),195 'name': str(asset.id) +'/' + str(sequence),
185 'remaining_value': residual_amount,196 'remaining_value': residual_amount,
186 'depreciated_value': (asset.purchase_value - asset.salvage_value) - (residual_amount + amount),197 'depreciated_value': (asset.purchase_value - asset.salvage_value) - (residual_amount + amount),
187 'depreciation_date': depreciation_date.strftime('%Y-%m-%d'),198 'depreciation_date': depreciation_date.strftime('%Y-%m-%d'),
@@ -270,7 +281,7 @@
270 help="Choose the method to use to compute the dates and number of depreciation lines.\n"\281 help="Choose the method to use to compute the dates and number of depreciation lines.\n"\
271 " * Number of Depreciations: Fix the number of depreciation lines and the time between 2 depreciations.\n" \282 " * Number of Depreciations: Fix the number of depreciation lines and the time between 2 depreciations.\n" \
272 " * Ending Date: Choose the time between 2 depreciations and the date the depreciations won't go beyond."),283 " * Ending Date: Choose the time between 2 depreciations and the date the depreciations won't go beyond."),
273 'prorata':fields.boolean('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'),284 'prorata':fields.boolean('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 day of depreciation period.'),
274 'history_ids': fields.one2many('account.asset.history', 'asset_id', 'History', readonly=True),285 'history_ids': fields.one2many('account.asset.history', 'asset_id', 'History', readonly=True),
275 'depreciation_line_ids': fields.one2many('account.asset.depreciation.line', 'asset_id', 'Depreciation Lines', readonly=True, states={'draft':[('readonly',False)],'open':[('readonly',False)]}),286 'depreciation_line_ids': fields.one2many('account.asset.depreciation.line', 'asset_id', 'Depreciation Lines', readonly=True, states={'draft':[('readonly',False)],'open':[('readonly',False)]}),
276 'salvage_value': fields.float('Salvage Value', digits_compute=dp.get_precision('Account'), help="It is the amount you plan to have that you cannot depreciate.", readonly=True, states={'draft':[('readonly',False)]}),287 'salvage_value': fields.float('Salvage Value', digits_compute=dp.get_precision('Account'), help="It is the amount you plan to have that you cannot depreciate.", readonly=True, states={'draft':[('readonly',False)]}),
@@ -330,7 +341,7 @@
330 default = {}341 default = {}
331 if context is None:342 if context is None:
332 context = {}343 context = {}
333 default.update({'depreciation_line_ids': [], 'state': 'draft'})344 default.update({'depreciation_line_ids': [], 'account_move_line_ids': [], 'history_ids': [], 'state': 'draft'})
334 return super(account_asset_asset, self).copy(cr, uid, id, default, context=context)345 return super(account_asset_asset, self).copy(cr, uid, id, default, context=context)
335346
336 def _compute_entries(self, cr, uid, ids, period_id, context=None):347 def _compute_entries(self, cr, uid, ids, period_id, context=None):
337348
=== modified file 'account_asset/test/account_asset_wizard.yml'
--- account_asset/test/account_asset_wizard.yml 2011-12-20 10:08:42 +0000
+++ account_asset/test/account_asset_wizard.yml 2014-03-26 15:52:48 +0000
@@ -13,7 +13,7 @@
13 I check the proper depreciation lines created.13 I check the proper depreciation lines created.
14-14-
15 !assert {model: account.asset.asset, id: account_asset.account_asset_asset_office0}:15 !assert {model: account.asset.asset, id: account_asset.account_asset_asset_office0}:
16 - method_number == len(depreciation_line_ids) -116 - method_number == len(depreciation_line_ids)
17-17-
18 I create a period to compute a asset on period.18 I create a period to compute a asset on period.
19-19-
2020
=== added directory 'account_asset/tests'
=== added file 'account_asset/tests/__init__.py'
--- account_asset/tests/__init__.py 1970-01-01 00:00:00 +0000
+++ account_asset/tests/__init__.py 2014-03-26 15:52:48 +0000
@@ -0,0 +1,26 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# OpenERP, Open Source Business Applications
5# Copyright (c) 2014-TODAY OpenERP S.A. <http://openerp.com>
6#
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU Affero General Public License as
9# published by the Free Software Foundation, either version 3 of the
10# License, or (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU Affero General Public License for more details.
16#
17# You should have received a copy of the GNU Affero General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19#
20##############################################################################
21
22from . import test_depreciation
23
24checks = [
25 test_depreciation,
26]
027
=== added file 'account_asset/tests/test_depreciation.py'
--- account_asset/tests/test_depreciation.py 1970-01-01 00:00:00 +0000
+++ account_asset/tests/test_depreciation.py 2014-03-26 15:52:48 +0000
@@ -0,0 +1,82 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# OpenERP, Open Source Business Applications
5# Copyright (c) 2012-TODAY OpenERP S.A. <http://openerp.com>
6#
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU Affero General Public License as
9# published by the Free Software Foundation, either version 3 of the
10# License, or (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU Affero General Public License for more details.
16#
17# You should have received a copy of the GNU Affero General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19#
20##############################################################################
21
22from openerp.tests import common
23
24import time
25
26class TestDepreciation(common.TransactionCase):
27
28 def setUp(self):
29 super(TestDepreciation, self).setUp()
30
31 # Usefull models
32 self.ir_model_data = self.registry('ir.model.data')
33 self.asset = self.registry('account.asset.asset')
34 self.asset_line = self.registry('account.asset.depreciation.line')
35 self.useless_category_id = self.ir_model_data.get_object_reference(self.cr, self.uid, 'account_asset', 'account_asset_category_fixedassets0')[1]
36
37 def test_yearly(self):
38 cr, uid, context = self.cr, self.uid, {}
39 asset_id = self.asset.create(cr, uid, {
40 'name': 'A 5 years car',
41 'category_id': self.useless_category_id,
42 'purchase_value': 10000,
43 'method': 'linear',
44 'method_number': 5,
45 'method_period': 12,
46 'purchase_date': time.strftime('%Y-01-01')
47 }, context=context)
48 asset = self.asset.browse(cr, uid, asset_id, context=context)
49
50 self.assertEquals(len(asset.depreciation_line_ids), 5, 'Incorrect number of depreciations for created asset')
51 # make sure lines are sorted by sequence
52 lines = sorted([line for line in asset.depreciation_line_ids], key=lambda line: line.sequence)
53 remanining_value = asset.purchase_value
54 depreciation_amount = asset.purchase_value/asset.method_number
55 for line in lines:
56 self.assertEquals(line.amount, depreciation_amount, "Linear depreciation does not have equal depreciation")
57 self.assertEquals(line.remaining_value, remanining_value-depreciation_amount, "Remaining value should be decreased of the depreciation amount")
58 remanining_value -= depreciation_amount
59
60 def test_monthly(self):
61 cr, uid, context = self.cr, self.uid, {}
62
63 asset_id = self.asset.create(cr, uid, {
64 'name': 'A 4 months coffee machine',
65 'category_id': self.useless_category_id,
66 'purchase_value': 24,
67 'method': 'linear',
68 'method_number': 4,
69 'method_period': 1,
70 'purchase_date': time.strftime('%Y-05-15')
71 }, context=context)
72 asset = self.asset.browse(cr, uid, asset_id, context=context)
73
74 self.assertEquals(len(asset.depreciation_line_ids), 4, "Incorrect number of depreciations for created asset")
75 lines = sorted([line for line in asset.depreciation_line_ids], key=lambda line: line.sequence)
76 self.assertEquals(lines[0].depreciation_date, time.strftime('%Y-05-01'), "First depreciation should be the first day of the current period")
77
78 self.asset_line.create_move(cr, uid, [lines[0].id], context=context)
79 self.asset_line.create_move(cr, uid, [lines[1].id], context=context)
80
81 self.asset.compute_depreciation_board(cr, uid, [asset_id], context=context)
82 self.assertEquals(len(asset.depreciation_line_ids), 4, "The number of depreciation lines has changed when some are posted")