[MERGE] with trunk
[odoo/odoo.git] / addons / account_asset / account_asset.py
1 # -*- encoding: utf-8 -*-
2 ##############################################################################
3 #
4 #    OpenERP, Open Source Management Solution
5 #    Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
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
22 import time
23 from datetime import datetime
24 from dateutil.relativedelta import relativedelta
25
26 from osv import osv, fields
27 import decimal_precision as dp
28
29 class account_asset_category(osv.osv):
30     _name = 'account.asset.category'
31     _description = 'Asset category'
32
33     _columns = {
34         'name': fields.char('Name', size=64, required=True, select=1),
35         'note': fields.text('Note'),
36         'account_analytic_id': fields.many2one('account.analytic.account', 'Analytic account'),
37         'account_asset_id': fields.many2one('account.account', 'Asset Account', required=True),
38         'account_depreciation_id': fields.many2one('account.account', 'Depreciation Account', required=True),
39         'account_expense_depreciation_id': fields.many2one('account.account', 'Depr. Expense Account', required=True),
40         'journal_id': fields.many2one('account.journal', 'Journal', required=True),
41         'company_id': fields.many2one('res.company', 'Company', required=True),
42         'method': fields.selection([('linear','Linear'),('degressive','Degressive')], 'Computation Method', required=True, help="Choose the method to use to compute the amount of depreciation lines.\n"\
43             "  * Linear: Calculated on basis of: Gross Value / Number of Depreciations\n" \
44             "  * Degressive: Calculated on basis of: Residual Value * Degressive Factor"),
45         'method_number': fields.integer('Number of Depreciations', help="The number of depreciations needed to depreciate your asset"),
46         'method_period': fields.integer('Period Length', help="State here the time between 2 depreciations, in months", required=True),
47         'method_progress_factor': fields.float('Degressive Factor'),
48         'method_time': fields.selection([('number','Number of Depreciations'),('end','Ending Date')], 'Time Method', required=True,
49                                   help="Choose the method to use to compute the dates and number of depreciation lines.\n"\
50                                        "  * Number of Depreciations: Fix the number of depreciation lines and the time between 2 depreciations.\n" \
51                                        "  * Ending Date: Choose the time between 2 depreciations and the date the depreciations won't go beyond."),
52         'method_end': fields.date('Ending date'),
53         '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         '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     }
56
57     _defaults = {
58         'company_id': lambda self, cr, uid, context: self.pool.get('res.company')._company_default_get(cr, uid, 'account.asset.category', context=context),
59         'method': 'linear',
60         'method_number': 5,
61         'method_time': 'number',
62         'method_period': 12,
63         'method_progress_factor': 0.3,
64     }
65
66     def onchange_account_asset(self, cr, uid, ids, account_asset_id, context=None):
67         res = {'value':{}}
68         if account_asset_id:
69            res['value'] = {'account_depreciation_id': account_asset_id}
70         return res
71
72 account_asset_category()
73
74 class account_asset_asset(osv.osv):
75     _name = 'account.asset.asset'
76     _description = 'Asset'
77
78     def _get_period(self, cr, uid, context=None):
79         periods = self.pool.get('account.period').find(cr, uid)
80         if periods:
81             return periods[0]
82         else:
83             return False
84
85     def _get_last_depreciation_date(self, cr, uid, ids, context=None):
86         """
87         @param id: ids of a account.asset.asset objects
88         @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
89         """
90         cr.execute("""
91             SELECT a.id as id, COALESCE(MAX(l.date),a.purchase_date) AS date
92             FROM account_asset_asset a
93             LEFT JOIN account_move_line l ON (l.asset_id = a.id)
94             WHERE a.id IN %s
95             GROUP BY a.id, a.purchase_date """, (tuple(ids),))
96         return dict(cr.fetchall())
97
98     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):
99         #by default amount = 0
100         amount = 0
101         if i == undone_dotation_number:
102             amount = residual_amount
103         else:
104             if asset.method == 'linear':
105                 amount = amount_to_depr / (undone_dotation_number - len(posted_depreciation_line_ids))
106                 if asset.prorata:
107                     amount = amount_to_depr / asset.method_number
108                     days = total_days - float(depreciation_date.strftime('%j'))
109                     if i == 1:
110                         amount = (amount_to_depr / asset.method_number) / total_days * days
111                     elif i == undone_dotation_number:
112                         amount = (amount_to_depr / asset.method_number) / total_days * (total_days - days)
113             elif asset.method == 'degressive':
114                 amount = residual_amount * asset.method_progress_factor
115                 if asset.prorata:
116                     days = total_days - float(depreciation_date.strftime('%j'))
117                     if i == 1:
118                         amount = (residual_amount * asset.method_progress_factor) / total_days * days
119                     elif i == undone_dotation_number:
120                         amount = (residual_amount * asset.method_progress_factor) / total_days * (total_days - days)
121         return amount
122
123     def _compute_board_undone_dotation_nb(self, cr, uid, asset, depreciation_date, total_days, context=None):
124         undone_dotation_number = asset.method_number
125         if asset.method_time == 'end':
126             end_date = datetime.strptime(asset.method_end, '%Y-%m-%d')
127             undone_dotation_number = 0
128             while depreciation_date <= end_date:
129                 depreciation_date = (datetime(depreciation_date.year, depreciation_date.month, depreciation_date.day) + relativedelta(months=+asset.method_period))
130                 undone_dotation_number += 1
131         if asset.prorata:
132             undone_dotation_number += 1
133         return undone_dotation_number
134
135     def compute_depreciation_board(self, cr, uid, ids, context=None):
136         depreciation_lin_obj = self.pool.get('account.asset.depreciation.line')
137         currency_obj = self.pool.get('res.currency')
138         for asset in self.browse(cr, uid, ids, context=context):
139             if asset.value_residual == 0.0:
140                 continue
141             posted_depreciation_line_ids = depreciation_lin_obj.search(cr, uid, [('asset_id', '=', asset.id), ('move_check', '=', True)],order='depreciation_date desc')
142             old_depreciation_line_ids = depreciation_lin_obj.search(cr, uid, [('asset_id', '=', asset.id), ('move_id', '=', False)])
143             if old_depreciation_line_ids:
144                 depreciation_lin_obj.unlink(cr, uid, old_depreciation_line_ids, context=context)
145
146             amount_to_depr = residual_amount = asset.value_residual
147             if asset.prorata:
148                 depreciation_date = datetime.strptime(self._get_last_depreciation_date(cr, uid, [asset.id], context)[asset.id], '%Y-%m-%d')
149             else:
150                 # depreciation_date = 1st January of purchase year
151                 purchase_date = datetime.strptime(asset.purchase_date, '%Y-%m-%d')
152                 #if we already have some previous validated entries, starting date isn't 1st January but last entry + method period
153                 if (len(posted_depreciation_line_ids)>0):
154                     last_depreciation_date = datetime.strptime(depreciation_lin_obj.browse(cr,uid,posted_depreciation_line_ids[0],context=context).depreciation_date, '%Y-%m-%d')
155                     depreciation_date = (last_depreciation_date+relativedelta(months=+asset.method_period))
156                 else:
157                     depreciation_date = datetime(purchase_date.year, 1, 1)
158             day = depreciation_date.day
159             month = depreciation_date.month
160             year = depreciation_date.year
161             total_days = (year % 4) and 365 or 366
162
163             undone_dotation_number = self._compute_board_undone_dotation_nb(cr, uid, asset, depreciation_date, total_days, context=context)
164             for x in range(len(posted_depreciation_line_ids), undone_dotation_number):
165                 i = x + 1
166                 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)
167                 company_currency = asset.company_id.currency_id.id
168                 current_currency = asset.currency_id.id
169                 # compute amount into company currency
170                 amount = currency_obj.compute(cr, uid, current_currency, company_currency, amount, context=context)
171                 residual_amount -= amount
172                 vals = {
173                      'amount': amount,
174                      'asset_id': asset.id,
175                      'sequence': i,
176                      'name': str(asset.id) +'/' + str(i),
177                      'remaining_value': residual_amount,
178                      'depreciated_value': (asset.purchase_value - asset.salvage_value) - (residual_amount + amount),
179                      'depreciation_date': depreciation_date.strftime('%Y-%m-%d'),
180                 }
181                 depreciation_lin_obj.create(cr, uid, vals, context=context)
182                 # Considering Depr. Period as months
183                 depreciation_date = (datetime(year, month, day) + relativedelta(months=+asset.method_period))
184                 day = depreciation_date.day
185                 month = depreciation_date.month
186                 year = depreciation_date.year
187         return True
188
189     def validate(self, cr, uid, ids, context=None):
190         if context is None:
191             context = {}
192         return self.write(cr, uid, ids, {
193             'state':'open'
194         }, context)
195
196     def set_to_close(self, cr, uid, ids, context=None):
197         return self.write(cr, uid, ids, {'state': 'close'}, context=context)
198
199     def set_to_draft(self, cr, uid, ids, context=None):
200         return self.write(cr, uid, ids, {'state': 'draft'}, context=context)
201
202     def _amount_residual(self, cr, uid, ids, name, args, context=None):
203         cr.execute("""SELECT
204                 l.asset_id as id, SUM(abs(l.debit-l.credit)) AS amount
205             FROM
206                 account_move_line l
207             WHERE
208                 l.asset_id IN %s GROUP BY l.asset_id """, (tuple(ids),))
209         res=dict(cr.fetchall())
210         for asset in self.browse(cr, uid, ids, context):
211             res[asset.id] = asset.purchase_value - res.get(asset.id, 0.0) - asset.salvage_value
212         for id in ids:
213             res.setdefault(id, 0.0)
214         return res
215
216     def onchange_company_id(self, cr, uid, ids, company_id=False, context=None):
217         val = {}
218         if company_id:
219             company = self.pool.get('res.company').browse(cr, uid, company_id, context=context)
220             if company.currency_id.company_id and company.currency_id.company_id.id != company_id:
221                 val['currency_id'] = False
222             else:
223                 val['currency_id'] = company.currency_id.id
224         return {'value': val}
225     
226     def onchange_purchase_salvage_value(self, cr, uid, ids, purchase_value, salvage_value, context=None):
227         val = {}
228         for asset in self.browse(cr, uid, ids, context=context):
229             if purchase_value:
230                 val['value_residual'] = purchase_value - salvage_value
231             if salvage_value:
232                 val['value_residual'] = purchase_value - salvage_value
233         return {'value': val}    
234
235     _columns = {
236         'account_move_line_ids': fields.one2many('account.move.line', 'asset_id', 'Entries', readonly=True, states={'draft':[('readonly',False)]}),
237         'name': fields.char('Asset Name', size=64, required=True, readonly=True, states={'draft':[('readonly',False)]}),
238         'code': fields.char('Reference', size=32, readonly=True, states={'draft':[('readonly',False)]}),
239         'purchase_value': fields.float('Gross Value', required=True, readonly=True, states={'draft':[('readonly',False)]}),
240         'currency_id': fields.many2one('res.currency','Currency',required=True, readonly=True, states={'draft':[('readonly',False)]}),
241         'company_id': fields.many2one('res.company', 'Company', required=True, readonly=True, states={'draft':[('readonly',False)]}),
242         'note': fields.text('Note'),
243         'category_id': fields.many2one('account.asset.category', 'Asset Category', required=True, change_default=True, readonly=True, states={'draft':[('readonly',False)]}),
244         'parent_id': fields.many2one('account.asset.asset', 'Parent Asset', readonly=True, states={'draft':[('readonly',False)]}),
245         'child_ids': fields.one2many('account.asset.asset', 'parent_id', 'Children Assets'),
246         'purchase_date': fields.date('Purchase Date', required=True, readonly=True, states={'draft':[('readonly',False)]}),
247         'state': fields.selection([('draft','Draft'),('open','Running'),('close','Close')], 'Status', required=True,
248                                   help="When an asset is created, the status is 'Draft'.\n" \
249                                        "If the asset is confirmed, the status goes in 'Running' and the depreciation lines can be posted in the accounting.\n" \
250                                        "You can manually close an asset when the depreciation is over. If the last line of depreciation is posted, the asset automatically goes in that status."),
251         'active': fields.boolean('Active'),
252         'partner_id': fields.many2one('res.partner', 'Partner', readonly=True, states={'draft':[('readonly',False)]}),
253         'method': fields.selection([('linear','Linear'),('degressive','Degressive')], 'Computation Method', required=True, readonly=True, states={'draft':[('readonly',False)]}, help="Choose the method to use to compute the amount of depreciation lines.\n"\
254             "  * Linear: Calculated on basis of: Gross Value / Number of Depreciations\n" \
255             "  * Degressive: Calculated on basis of: Residual Value * Degressive Factor"),
256         'method_number': fields.integer('Number of Depreciations', readonly=True, states={'draft':[('readonly',False)]}, help="The number of depreciations needed to depreciate your asset"),
257         'method_period': fields.integer('Number of Months in a Period', required=True, readonly=True, states={'draft':[('readonly',False)]}, help="The amount of time between two depreciations, in months"),
258         'method_end': fields.date('Ending Date', readonly=True, states={'draft':[('readonly',False)]}),
259         'method_progress_factor': fields.float('Degressive Factor', readonly=True, states={'draft':[('readonly',False)]}),
260         'value_residual': fields.function(_amount_residual, method=True, digits_compute=dp.get_precision('Account'), string='Residual Value'),
261         'method_time': fields.selection([('number','Number of Depreciations'),('end','Ending Date')], 'Time Method', required=True, readonly=True, states={'draft':[('readonly',False)]},
262                                   help="Choose the method to use to compute the dates and number of depreciation lines.\n"\
263                                        "  * Number of Depreciations: Fix the number of depreciation lines and the time between 2 depreciations.\n" \
264                                        "  * Ending Date: Choose the time between 2 depreciations and the date the depreciations won't go beyond."),
265         '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'),
266         'history_ids': fields.one2many('account.asset.history', 'asset_id', 'History', readonly=True),
267         'depreciation_line_ids': fields.one2many('account.asset.depreciation.line', 'asset_id', 'Depreciation Lines', readonly=True, states={'draft':[('readonly',False)],'open':[('readonly',False)]}),
268         '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)]}),
269     }
270     _defaults = {
271         'code': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(cr, uid, 'account.asset.code'),
272         'purchase_date': lambda obj, cr, uid, context: time.strftime('%Y-%m-%d'),
273         'active': True,
274         'state': 'draft',
275         'method': 'linear',
276         'method_number': 5,
277         'method_time': 'number',
278         'method_period': 12,
279         'method_progress_factor': 0.3,
280         'currency_id': lambda self,cr,uid,c: self.pool.get('res.users').browse(cr, uid, uid, c).company_id.currency_id.id,
281         'company_id': lambda self, cr, uid, context: self.pool.get('res.company')._company_default_get(cr, uid, 'account.asset.asset',context=context),
282     }
283
284     def _check_recursion(self, cr, uid, ids, context=None, parent=None):
285         return super(account_asset_asset, self)._check_recursion(cr, uid, ids, context=context, parent=parent)
286
287     def _check_prorata(self, cr, uid, ids, context=None):
288         for asset in self.browse(cr, uid, ids, context=context):
289             if asset.prorata and asset.method_time != 'number':
290                 return False
291         return True
292
293     _constraints = [
294         (_check_recursion, 'Error ! You cannot create recursive assets.', ['parent_id']),
295         (_check_prorata, 'Prorata temporis can be applied only for time method "number of depreciations".', ['prorata']),
296     ]
297
298     def onchange_category_id(self, cr, uid, ids, category_id, context=None):
299         res = {'value':{}}
300         asset_categ_obj = self.pool.get('account.asset.category')
301         if category_id:
302             category_obj = asset_categ_obj.browse(cr, uid, category_id, context=context)
303             res['value'] = {
304                             'method': category_obj.method,
305                             'method_number': category_obj.method_number,
306                             'method_time': category_obj.method_time,
307                             'method_period': category_obj.method_period,
308                             'method_progress_factor': category_obj.method_progress_factor,
309                             'method_end': category_obj.method_end,
310                             'prorata': category_obj.prorata,
311             }
312         return res
313
314     def onchange_method_time(self, cr, uid, ids, method_time='number', context=None):
315         res = {'value': {}}
316         if method_time != 'number':
317             res['value'] = {'prorata': False}
318         return res
319
320     def copy(self, cr, uid, id, default=None, context=None):
321         if default is None:
322             default = {}
323         if context is None:
324             context = {}
325         default.update({'depreciation_line_ids': [], 'state': 'draft'})
326         return super(account_asset_asset, self).copy(cr, uid, id, default, context=context)
327
328     def _compute_entries(self, cr, uid, ids, period_id, context=None):
329         result = []
330         period_obj = self.pool.get('account.period')
331         depreciation_obj = self.pool.get('account.asset.depreciation.line')
332         period = period_obj.browse(cr, uid, period_id, context=context)
333         depreciation_ids = depreciation_obj.search(cr, uid, [('asset_id', 'in', ids), ('depreciation_date', '<=', period.date_stop), ('depreciation_date', '>=', period.date_start), ('move_check', '=', False)], context=context)
334         return depreciation_obj.create_move(cr, uid, depreciation_ids, context=context)
335
336     def create(self, cr, uid, vals, context=None):
337         asset_id = super(account_asset_asset, self).create(cr, uid, vals, context=context)
338         self.compute_depreciation_board(cr, uid, [asset_id], context=context)
339         return asset_id
340     
341     def open_entries(self, cr, uid, ids, context=None):
342         if context is None:
343             context = {}
344         context.update({'search_default_asset_id': ids, 'default_asset_id': ids})
345         return {
346             'view_type': 'form',
347             'view_mode': 'tree,form',
348             'res_model': 'account.move.line',
349             'view_id': False,
350             'type': 'ir.actions.act_window',
351             'context': context,
352         }
353
354 account_asset_asset()
355
356 class account_asset_depreciation_line(osv.osv):
357     _name = 'account.asset.depreciation.line'
358     _description = 'Asset depreciation line'
359
360     def _get_move_check(self, cr, uid, ids, name, args, context=None):
361         res = {}
362         for line in self.browse(cr, uid, ids, context=context):
363             res[line.id] = bool(line.move_id)
364         return res
365
366     _columns = {
367         'name': fields.char('Depreciation Name', size=64, required=True, select=1),
368         'sequence': fields.integer('Sequence', required=True),
369         'asset_id': fields.many2one('account.asset.asset', 'Asset', required=True),
370         'parent_state': fields.related('asset_id', 'state', type='char', string='State of Asset'),
371         'amount': fields.float('Current Depreciation', digits_compute=dp.get_precision('Account'), required=True),
372         'remaining_value': fields.float('Next Period Depreciation', digits_compute=dp.get_precision('Account'),required=True),
373         'depreciated_value': fields.float('Amount Already Depreciated', required=True),
374         'depreciation_date': fields.date('Depreciation Date', select=1),
375         'move_id': fields.many2one('account.move', 'Depreciation Entry'),
376         'move_check': fields.function(_get_move_check, method=True, type='boolean', string='Posted', store=True)
377     }
378
379     def create_move(self, cr, uid, ids, context=None):
380         can_close = False
381         if context is None:
382             context = {}
383         asset_obj = self.pool.get('account.asset.asset')
384         period_obj = self.pool.get('account.period')
385         move_obj = self.pool.get('account.move')
386         move_line_obj = self.pool.get('account.move.line')
387         currency_obj = self.pool.get('res.currency')
388         created_move_ids = []
389         asset_ids = []
390         for line in self.browse(cr, uid, ids, context=context):
391             depreciation_date = time.strftime('%Y-%m-%d')
392             period_ids = period_obj.find(cr, uid, depreciation_date, context=context)
393             company_currency = line.asset_id.company_id.currency_id.id
394             current_currency = line.asset_id.currency_id.id
395             context.update({'date': depreciation_date})
396             amount = currency_obj.compute(cr, uid, current_currency, company_currency, line.amount, context=context)
397             sign = (line.asset_id.category_id.journal_id.type == 'purchase' and 1) or -1
398             asset_name = line.asset_id.name
399             reference = line.name
400             move_vals = {
401                 'name': asset_name,
402                 'date': depreciation_date,
403                 'ref': reference,
404                 'period_id': period_ids and period_ids[0] or False,
405                 'journal_id': line.asset_id.category_id.journal_id.id,
406                 }
407             move_id = move_obj.create(cr, uid, move_vals, context=context)
408             journal_id = line.asset_id.category_id.journal_id.id
409             partner_id = line.asset_id.partner_id.id
410             move_line_obj.create(cr, uid, {
411                 'name': asset_name,
412                 'ref': reference,
413                 'move_id': move_id,
414                 'account_id': line.asset_id.category_id.account_depreciation_id.id,
415                 'debit': 0.0,
416                 'credit': amount,
417                 'period_id': period_ids and period_ids[0] or False,
418                 'journal_id': journal_id,
419                 'partner_id': partner_id,
420                 'currency_id': company_currency != current_currency and  current_currency or False,
421                 'amount_currency': company_currency != current_currency and - sign * line.amount or 0.0,
422                 'date': depreciation_date,
423             })
424             move_line_obj.create(cr, uid, {
425                 'name': asset_name,
426                 'ref': reference,
427                 'move_id': move_id,
428                 'account_id': line.asset_id.category_id.account_expense_depreciation_id.id,
429                 'credit': 0.0,
430                 'debit': amount,
431                 'period_id': period_ids and period_ids[0] or False,
432                 'journal_id': journal_id,
433                 'partner_id': partner_id,
434                 'currency_id': company_currency != current_currency and  current_currency or False,
435                 'amount_currency': company_currency != current_currency and sign * line.amount or 0.0,
436                 'analytic_account_id': line.asset_id.category_id.account_analytic_id.id,
437                 'date': depreciation_date,
438                 'asset_id': line.asset_id.id
439             })
440             self.write(cr, uid, line.id, {'move_id': move_id}, context=context)
441             created_move_ids.append(move_id)
442             asset_ids.append(line.asset_id.id)
443         # we re-evaluate the assets to determine whether we can close them
444         for asset in asset_obj.browse(cr, uid, list(set(asset_ids)), context=context):
445             if currency_obj.is_zero(cr, uid, asset.currency_id, asset.value_residual):
446                 asset.write({'state': 'close'})
447         return created_move_ids
448
449 account_asset_depreciation_line()
450
451 class account_move_line(osv.osv):
452     _inherit = 'account.move.line'
453     _columns = {
454         'asset_id': fields.many2one('account.asset.asset', 'Asset'),
455         'entry_ids': fields.one2many('account.move.line', 'asset_id', 'Entries', readonly=True, states={'draft':[('readonly',False)]}),
456
457     }
458 account_move_line()
459
460 class account_asset_history(osv.osv):
461     _name = 'account.asset.history'
462     _description = 'Asset history'
463     _columns = {
464         'name': fields.char('History name', size=64, select=1),
465         'user_id': fields.many2one('res.users', 'User', required=True),
466         'date': fields.date('Date', required=True),
467         'asset_id': fields.many2one('account.asset.asset', 'Asset', required=True),
468         'method_time': fields.selection([('number','Number of Depreciations'),('end','Ending Date')], 'Time Method', required=True,
469                                   help="The method to use to compute the dates and number of depreciation lines.\n"\
470                                        "Number of Depreciations: Fix the number of depreciation lines and the time between 2 depreciations.\n" \
471                                        "Ending Date: Choose the time between 2 depreciations and the date the depreciations won't go beyond."),
472         'method_number': fields.integer('Number of Depreciations', help="The number of depreciations needed to depreciate your asset"),
473         'method_period': fields.integer('Period Length', help="Time in month between two depreciations"),
474         'method_end': fields.date('Ending date'),
475         'note': fields.text('Note'),
476     }
477     _order = 'date desc'
478     _defaults = {
479         'date': lambda *args: time.strftime('%Y-%m-%d'),
480         'user_id': lambda self, cr, uid, ctx: uid
481     }
482
483 account_asset_history()
484
485 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: