[IMP] account_asset: new api conversion, added asset type

This commit is contained in:
Chirag Dodiya
2015-05-08 17:30:54 +02:00
committed by Olivier Dony
parent d0c64049b9
commit 6120babb45
25 changed files with 1148 additions and 1038 deletions
+1 -20
View File
@@ -1,23 +1,4 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
# -*- coding: utf-8 -*-
import account_asset
import account_asset_invoice
+11 -32
View File
@@ -1,31 +1,12 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
# -*- coding: utf-8 -*-
{
'name': 'Assets Management',
'version': '1.0',
'depends': ['account'],
'author': 'OpenERP S.A.',
'depends': ['account_accountant'],
'author': 'Odoo S.A.',
'description': """
Financial and accounting asset management.
Assets management.
==========================================
This Module manages the assets owned by a company or an individual. It will keep
@@ -36,22 +17,20 @@ of the depreciation lines.
'website': 'https://www.odoo.com/page/accounting',
'category': 'Accounting & Finance',
'sequence': 32,
'demo': [ 'account_asset_demo.xml'],
'test': [
'test/account_asset_demo.yml',
'test/account_asset.yml',
'test/account_asset_wizard.yml',
],
'demo': ['account_asset_demo.xml'],
'data': [
'security/account_asset_security.xml',
'security/ir.model.access.csv',
'wizard/account_asset_change_duration_view.xml',
'wizard/wizard_asset_compute_view.xml',
'account_asset_view.xml',
'account_asset_invoice_view.xml',
'views/account_asset_view.xml',
'views/account_asset_invoice_view.xml',
'report/account_asset_report_view.xml',
'views/account_asset.xml',
],
'qweb': [
"static/src/xml/account_asset_template.xml",
],
'auto_install': False,
'installable': True,
'application': False,
}
+350 -363
View File
@@ -1,350 +1,318 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
# -*- coding: utf-8 -*-
import time
from datetime import datetime
from datetime import date, datetime
from dateutil.relativedelta import relativedelta
from openerp.osv import fields, osv
import openerp.addons.decimal_precision as dp
from openerp.tools.translate import _
from openerp.exceptions import UserError
from openerp import api, fields, models, _
from openerp.exceptions import UserError, ValidationError
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT as DF
class account_asset_category(osv.osv):
class AccountAssetCategory(models.Model):
_name = 'account.asset.category'
_description = 'Asset category'
_columns = {
'name': fields.char('Name', required=True, select=1),
'note': fields.text('Note'),
'account_analytic_id': fields.many2one('account.analytic.account', 'Analytic account'),
'account_asset_id': fields.many2one('account.account', 'Asset Account', required=True, domain=[('type','=','other')]),
'account_depreciation_id': fields.many2one('account.account', 'Depreciation Account', required=True, domain=[('type','=','other')]),
'account_expense_depreciation_id': fields.many2one('account.account', 'Depr. Expense Account', required=True, domain=[('type','=','other')]),
'journal_id': fields.many2one('account.journal', 'Journal', required=True),
'company_id': fields.many2one('res.company', 'Company', required=True),
'method': fields.selection([('linear','Linear: Computed on basis of Gross Value / Number of Depreciations'),('degressive','Degressive: Computed on basis of Residual Value * Degressive Factor')], 'Computation Method', required=True, help="Choose the method to use to compute the amount of depreciation lines.\n"\
" * Linear: Calculated on basis of: Gross Value / Number of Depreciations\n" \
" * Degressive: Calculated on basis of: Residual Value * Degressive Factor"),
'method_number': fields.integer('Number of Depreciations', help="The number of depreciations needed to depreciate your asset"),
'method_period': fields.integer('Period Length', help="State here the time between 2 depreciations, in months", required=True),
'method_progress_factor': fields.float('Degressive Factor'),
'method_time': fields.selection([('number','Number of Depreciations'),('end','Ending Date')], 'Time Method', required=True,
help="Choose the method to use to compute the dates and number of depreciation lines.\n"\
" * Number of Depreciations: Fix the number of depreciation lines and the time between 2 depreciations.\n" \
" * 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('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'),
'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."),
}
active = fields.Boolean(default=True)
name = fields.Char(required=True, index=True)
note = fields.Text()
account_analytic_id = fields.Many2one('account.analytic.account', string='Analytic Account')
account_asset_id = fields.Many2one('account.account', string='Asset Account', required=True, domain=[('type', '=', 'other')])
account_income_recognition_id = fields.Many2one('account.account', string='Recognition Income Account', domain=[('type', '=', 'other')], oldname='account_expense_depreciation_id')
account_depreciation_id = fields.Many2one('account.account', string='Depreciation Account', required=True, domain=[('type', '=', 'other')])
journal_id = fields.Many2one('account.journal', string='Journal', required=True)
company_id = fields.Many2one('res.company', string='Company', required=True, default=lambda self: self.env['res.company']._company_default_get('account.asset.category'))
method = fields.Selection([('linear', 'Linear'), ('degressive', 'Degressive')], string='Computation Method', required=True, default='linear',
help="Choose the method to use to compute the amount of depreciation lines.\n"
" * Linear: Calculated on basis of: Gross Value / Number of Depreciations\n"
" * Degressive: Calculated on basis of: Residual Value * Degressive Factor")
method_number = fields.Integer(string='Number of Depreciations', default=5, help="The number of depreciations needed to depreciate your asset")
method_period = fields.Integer(string='Period Length', default=1, help="State here the time between 2 depreciations, in months", required=True)
method_progress_factor = fields.Float('Degressive Factor', default=0.3)
method_time = fields.Selection([('number', 'Number of Depreciations'), ('end', 'Ending Date')], string='Time Method', required=True, default='number',
help="Choose the method to use to compute the dates and number of depreciation lines.\n"
" * Number of Depreciations: Fix the number of depreciation lines and the time between 2 depreciations.\n"
" * 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='Skip Draft State', help="Check this if you want to automatically confirm the assets of this category when created by invoices.")
type = fields.Selection([('sale', 'Sale: Revenue Recognition'), ('purchase', 'Purchase: Asset')], required=True, index=True, default='purchase')
_defaults = {
'company_id': lambda self, cr, uid, context: self.pool.get('res.company')._company_default_get(cr, uid, 'account.asset.category', context=context),
'method': 'linear',
'method_number': 5,
'method_time': 'number',
'method_period': 12,
'method_progress_factor': 0.3,
}
@api.onchange('account_asset_id')
def onchange_account_asset(self):
self.account_depreciation_id = self.account_asset_id
def onchange_account_asset(self, cr, uid, ids, account_asset_id, context=None):
res = {'value':{}}
if account_asset_id:
res['value'] = {'account_depreciation_id': account_asset_id}
return res
class account_asset_asset(osv.osv):
_name = 'account.asset.asset'
_description = 'Asset'
def unlink(self, cr, uid, ids, context=None):
for asset in self.browse(cr, uid, ids, context=context):
if asset.account_move_line_ids:
raise UserError(_('You cannot delete an asset that contains posted depreciation lines.'))
return super(account_asset_asset, self).unlink(cr, uid, ids, context=context)
def _get_period(self, cr, uid, context=None):
periods = self.pool.get('account.period').find(cr, uid, context=context)
if periods:
return periods[0]
@api.onchange('type')
def onchange_type(self):
if self.type == 'sale':
self.prorata = True
self.method_period = 1
else:
return False
self.method_period = 12
def _get_last_depreciation_date(self, cr, uid, ids, context=None):
class AccountAssetAsset(models.Model):
_name = 'account.asset.asset'
_description = 'Asset/Revenue Recognition'
_inherit = ['mail.thread', 'ir.needaction_mixin']
account_move_line_ids = fields.One2many('account.move.line', 'asset_id', string='Entries', readonly=True, states={'draft': [('readonly', False)]})
entry_count = fields.Integer(compute='_entry_count', string='# Asset Entries')
name = fields.Char(string='Asset/Deferred Revenue Name', required=True, readonly=True, states={'draft': [('readonly', False)]})
code = fields.Char(string='Reference', size=32, readonly=True, states={'draft': [('readonly', False)]}, default=lambda self: self.env['ir.sequence'].next_by_code('account.asset.code'))
value = fields.Float(string='Gross Value', required=True, readonly=True, digits=dp.get_precision('Account'), states={'draft': [('readonly', False)]}, oldname='purchase_value')
currency_id = fields.Many2one('res.currency', string='Currency', required=True, readonly=True, states={'draft': [('readonly', False)]},
default=lambda self: self.env.user.company_id.currency_id.id)
company_id = fields.Many2one('res.company', string='Company', required=True, readonly=True, states={'draft': [('readonly', False)]},
default=lambda self: self.env['res.company']._company_default_get('account.asset.asset'))
note = fields.Text()
category_id = fields.Many2one('account.asset.category', string='Category', required=True, change_default=True, readonly=True, states={'draft': [('readonly', False)]})
date = fields.Date(string='Date', required=True, readonly=True, states={'draft': [('readonly', False)]}, default=fields.Date.context_today, oldname="purchase_date")
state = fields.Selection([('draft', 'Draft'), ('open', 'Running'), ('close', 'Close')], 'Status', required=True, copy=False, default='draft',
help="When an asset is created, the status is 'Draft'.\n"
"If the asset is confirmed, the status goes in 'Running' and the depreciation lines can be posted in the accounting.\n"
"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.")
active = fields.Boolean(default=True)
partner_id = fields.Many2one('res.partner', string='Partner', readonly=True, states={'draft': [('readonly', False)]})
method = fields.Selection([('linear', 'Linear'), ('degressive', 'Degressive')], string='Computation Method', required=True, readonly=True, states={'draft': [('readonly', False)]}, default='linear',
help="Choose the method to use to compute the amount of depreciation lines.\n * Linear: Calculated on basis of: Gross Value / Number of Depreciations\n"
" * Degressive: Calculated on basis of: Residual Value * Degressive Factor")
method_number = fields.Integer(string='Number of Depreciations', readonly=True, states={'draft': [('readonly', False)]}, default=5, help="The number of depreciations needed to depreciate your asset")
method_period = fields.Integer(string='Number of Months in a Period', required=True, readonly=True, default=12, states={'draft': [('readonly', False)]},
help="The amount of time between two depreciations, in months")
method_end = fields.Date(string='Ending Date', readonly=True, states={'draft': [('readonly', False)]})
method_progress_factor = fields.Float(string='Degressive Factor', readonly=True, default=0.3, states={'draft': [('readonly', False)]})
value_residual = fields.Float(compute='_amount_residual', method=True, digits=dp.get_precision('Account'), string='Residual Value')
method_time = fields.Selection([('number', 'Number of Depreciations'), ('end', 'Ending Date')], string='Time Method', required=True, readonly=True, default='number', states={'draft': [('readonly', False)]},
help="Choose the method to use to compute the dates and number of depreciation lines.\n"
" * Number of Depreciations: Fix the number of depreciation lines 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')
history_ids = fields.One2many('account.asset.history', 'asset_id', string='History', readonly=True)
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=dp.get_precision('Account'), 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, default='purchase')
@api.multi
def unlink(self):
for asset in self:
if asset.state in ['open', 'close']:
raise UserError(_('You cannot delete a document is in %s state.') % (asset.state,))
if asset.account_move_line_ids:
raise UserError(_('You cannot delete a document that contains posted lines.'))
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
"""
cr.execute("""
SELECT a.id as id, COALESCE(MAX(l.date),a.purchase_date) AS date
self.env.cr.execute("""
SELECT a.id as id, COALESCE(MAX(l.date),a.date) AS date
FROM account_asset_asset a
LEFT JOIN account_move_line l ON (l.asset_id = a.id)
WHERE a.id IN %s
GROUP BY a.id, a.purchase_date """, (tuple(ids),))
return dict(cr.fetchall())
GROUP BY a.id, a.date """, (tuple(self.ids),))
result = dict(self.env.cr.fetchall())
return result
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):
#by default amount = 0
def _compute_board_amount(self, sequence, residual_amount, amount_to_depr, undone_dotation_number, posted_depreciation_line_ids, total_days, depreciation_date):
amount = 0
if i == undone_dotation_number:
if sequence == undone_dotation_number:
amount = residual_amount
else:
if asset.method == 'linear':
if self.method == 'linear':
amount = amount_to_depr / (undone_dotation_number - len(posted_depreciation_line_ids))
if asset.prorata:
amount = amount_to_depr / asset.method_number
if self.prorata and self.category_id.type == 'purchase':
amount = amount_to_depr / self.method_number
days = total_days - float(depreciation_date.strftime('%j'))
if i == 1:
amount = (amount_to_depr / asset.method_number) / total_days * days
elif i == undone_dotation_number:
amount = (amount_to_depr / asset.method_number) / total_days * (total_days - days)
elif asset.method == 'degressive':
amount = residual_amount * asset.method_progress_factor
if asset.prorata:
if sequence == 1:
amount = (amount_to_depr / self.method_number) / total_days * days
elif sequence == undone_dotation_number:
amount = (amount_to_depr / self.method_number) / total_days * (total_days - days)
elif self.method == 'degressive':
amount = residual_amount * self.method_progress_factor
if self.prorata:
days = total_days - float(depreciation_date.strftime('%j'))
if i == 1:
amount = (residual_amount * asset.method_progress_factor) / total_days * days
elif i == undone_dotation_number:
amount = (residual_amount * asset.method_progress_factor) / total_days * (total_days - days)
if sequence == 1:
amount = (residual_amount * self.method_progress_factor) / total_days * days
elif sequence == undone_dotation_number:
amount = (residual_amount * self.method_progress_factor) / total_days * (total_days - days)
return amount
def _compute_board_undone_dotation_nb(self, cr, uid, asset, depreciation_date, total_days, context=None):
undone_dotation_number = asset.method_number
if asset.method_time == 'end':
end_date = datetime.strptime(asset.method_end, '%Y-%m-%d')
def _compute_board_undone_dotation_nb(self, depreciation_date, total_days):
undone_dotation_number = self.method_number
if self.method_time == 'end':
end_date = datetime.strptime(self.method_end, DF).date()
undone_dotation_number = 0
while depreciation_date <= end_date:
depreciation_date = (datetime(depreciation_date.year, depreciation_date.month, depreciation_date.day) + relativedelta(months=+asset.method_period))
depreciation_date = date(depreciation_date.year, depreciation_date.month, depreciation_date.day) + relativedelta(months=+self.method_period)
undone_dotation_number += 1
if asset.prorata:
if self.prorata and self.category_id.type == 'purchase':
undone_dotation_number += 1
return undone_dotation_number
def compute_depreciation_board(self, cr, uid, ids, context=None):
depreciation_lin_obj = self.pool.get('account.asset.depreciation.line')
currency_obj = self.pool.get('res.currency')
for asset in self.browse(cr, uid, ids, context=context):
if asset.value_residual == 0.0:
continue
posted_depreciation_line_ids = depreciation_lin_obj.search(cr, uid, [('asset_id', '=', asset.id), ('move_check', '=', True)],order='depreciation_date desc')
old_depreciation_line_ids = depreciation_lin_obj.search(cr, uid, [('asset_id', '=', asset.id), ('move_id', '=', False)])
if old_depreciation_line_ids:
depreciation_lin_obj.unlink(cr, uid, old_depreciation_line_ids, context=context)
@api.multi
def compute_depreciation_board(self):
self.ensure_one()
amount_to_depr = residual_amount = asset.value_residual
if asset.prorata:
depreciation_date = datetime.strptime(self._get_last_depreciation_date(cr, uid, [asset.id], context)[asset.id], '%Y-%m-%d')
posted_depreciation_line_ids = self.depreciation_line_ids.filtered(lambda x: x.move_check)
unposted_depreciation_line_ids = self.depreciation_line_ids.filtered(lambda x: not x.move_check)
# Remove old unposted depreciation lines. We cannot use unlink() with One2many field
commands = [(2, line_id.id, False) for line_id in unposted_depreciation_line_ids]
if self.value != 0.0:
amount_to_depr = residual_amount = self.value_residual
if self.prorata:
depreciation_date = datetime.strptime(self._get_last_depreciation_date()[self.id], DF).date()
else:
# depreciation_date = 1st January of purchase year
purchase_date = datetime.strptime(asset.purchase_date, '%Y-%m-%d')
#if we already have some previous validated entries, starting date isn't 1st January but last entry + method period
if (len(posted_depreciation_line_ids)>0):
last_depreciation_date = datetime.strptime(depreciation_lin_obj.browse(cr,uid,posted_depreciation_line_ids[0],context=context).depreciation_date, '%Y-%m-%d')
depreciation_date = (last_depreciation_date+relativedelta(months=+asset.method_period))
# depreciation_date = 1st of January of purchase year
asset_date = datetime.strptime(self.date, 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[0].depreciation_date:
last_depreciation_date = datetime.strptime(posted_depreciation_line_ids[0].depreciation_date, DF).date()
depreciation_date = last_depreciation_date + relativedelta(months=+self.method_period)
else:
depreciation_date = datetime(purchase_date.year, 1, 1)
depreciation_date = asset_date
day = depreciation_date.day
month = depreciation_date.month
year = depreciation_date.year
total_days = (year % 4) and 365 or 366
undone_dotation_number = self._compute_board_undone_dotation_nb(cr, uid, asset, depreciation_date, total_days, context=context)
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):
i = x + 1
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)
sequence = x + 1
amount = self._compute_board_amount(sequence, residual_amount, amount_to_depr, undone_dotation_number, posted_depreciation_line_ids, total_days, depreciation_date)
amount = self.currency_id.round(amount)
residual_amount -= amount
vals = {
'amount': amount,
'asset_id': asset.id,
'sequence': i,
'name': str(asset.id) +'/' + str(i),
'remaining_value': residual_amount,
'depreciated_value': (asset.purchase_value - asset.salvage_value) - (residual_amount + amount),
'depreciation_date': depreciation_date.strftime('%Y-%m-%d'),
'amount': amount,
'asset_id': self.id,
'sequence': sequence,
'name': (self.code or str(self.id)) + '/' + str(sequence),
'remaining_value': residual_amount,
'depreciated_value': (self.value - self.salvage_value) - (residual_amount + amount),
'depreciation_date': depreciation_date.strftime(DF),
}
depreciation_lin_obj.create(cr, uid, vals, context=context)
commands.append((0, False, vals))
# Considering Depr. Period as months
depreciation_date = (datetime(year, month, day) + relativedelta(months=+asset.method_period))
depreciation_date = date(year, month, day) + relativedelta(months=+self.method_period)
day = depreciation_date.day
month = depreciation_date.month
year = depreciation_date.year
self.write({'depreciation_line_ids': commands})
return True
def validate(self, cr, uid, ids, context=None):
if context is None:
context = {}
return self.write(cr, uid, ids, {
'state':'open'
}, context)
@api.multi
def validate(self):
self.write({'state': 'open'})
def set_to_close(self, cr, uid, ids, context=None):
return self.write(cr, uid, ids, {'state': 'close'}, context=context)
@api.multi
def set_to_close(self):
unposted_dep_line = self.env['account.asset.depreciation.line'].search_count(
[('asset_id', 'in', self.ids), ('move_check', '=', False)])
if unposted_dep_line:
raise UserError(_('You cannot close a document which has unposted lines.'))
self.message_post(body=_("Document closed."))
self.write({'state': 'close'})
def set_to_draft(self, cr, uid, ids, context=None):
return self.write(cr, uid, ids, {'state': 'draft'}, context=context)
@api.multi
def set_to_draft(self):
self.write({'state': 'draft'})
def _amount_residual(self, cr, uid, ids, name, args, context=None):
cr.execute("""SELECT
l.asset_id as id, SUM(abs(l.debit-l.credit)) AS amount
FROM
account_move_line l
WHERE
l.asset_id IN %s GROUP BY l.asset_id """, (tuple(ids),))
res=dict(cr.fetchall())
for asset in self.browse(cr, uid, ids, context):
company_currency = asset.company_id.currency_id.id
current_currency = asset.currency_id.id
amount = self.pool['res.currency'].compute(cr, uid, company_currency, current_currency, res.get(asset.id, 0.0), context=context)
res[asset.id] = asset.purchase_value - amount - asset.salvage_value
for id in ids:
res.setdefault(id, 0.0)
return res
@api.one
@api.depends('value', 'salvage_value', 'depreciation_line_ids')
def _amount_residual(self):
total_amount = 0.0
for line in self.depreciation_line_ids:
if line.move_check:
total_amount += line.amount
self.value_residual = self.value - total_amount - self.salvage_value
def onchange_company_id(self, cr, uid, ids, company_id=False, context=None):
val = {}
if company_id:
company = self.pool.get('res.company').browse(cr, uid, company_id, context=context)
if company.currency_id.company_id and company.currency_id.company_id.id != company_id:
val['currency_id'] = False
else:
val['currency_id'] = company.currency_id.id
return {'value': val}
def onchange_purchase_salvage_value(self, cr, uid, ids, purchase_value, salvage_value, context=None):
val = {}
for asset in self.browse(cr, uid, ids, context=context):
if purchase_value:
val['value_residual'] = purchase_value - salvage_value
if salvage_value:
val['value_residual'] = purchase_value - salvage_value
return {'value': val}
def _entry_count(self, cr, uid, ids, field_name, arg, context=None):
MoveLine = self.pool('account.move.line')
return {
asset_id: MoveLine.search_count(cr, uid, [('asset_id', '=', asset_id)], context=context)
for asset_id in ids
}
_columns = {
'account_move_line_ids': fields.one2many('account.move.line', 'asset_id', 'Entries', readonly=True, states={'draft':[('readonly',False)]}),
'entry_count': fields.function(_entry_count, string='# Asset Entries', type='integer'),
'name': fields.char('Asset Name', required=True, readonly=True, states={'draft':[('readonly',False)]}),
'code': fields.char('Reference', size=32, readonly=True, states={'draft':[('readonly',False)]}),
'purchase_value': fields.float('Gross Value', required=True, readonly=True, states={'draft':[('readonly',False)]}),
'currency_id': fields.many2one('res.currency','Currency',required=True, readonly=True, states={'draft':[('readonly',False)]}),
'company_id': fields.many2one('res.company', 'Company', required=True, readonly=True, states={'draft':[('readonly',False)]}),
'note': fields.text('Note'),
'category_id': fields.many2one('account.asset.category', 'Asset Category', required=True, change_default=True, readonly=True, states={'draft':[('readonly',False)]}),
'parent_id': fields.many2one('account.asset.asset', 'Parent Asset', readonly=True, states={'draft':[('readonly',False)]}),
'child_ids': fields.one2many('account.asset.asset', 'parent_id', 'Children Assets', copy=True),
'purchase_date': fields.date('Purchase Date', required=True, readonly=True, states={'draft':[('readonly',False)]}),
'state': fields.selection([('draft','Draft'),('open','Running'),('close','Close')], 'Status', required=True, copy=False,
help="When an asset is created, the status is 'Draft'.\n" \
"If the asset is confirmed, the status goes in 'Running' and the depreciation lines can be posted in the accounting.\n" \
"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."),
'active': fields.boolean('Active'),
'partner_id': fields.many2one('res.partner', 'Partner', readonly=True, states={'draft':[('readonly',False)]}),
'method': fields.selection([('linear','Linear: Computed on basis of Gross Value / Number of Depreciations'),('degressive','Degressive: Computed on basis of Residual Value * Degressive Factor')], 'Computation Method', required=True, readonly=True, states={'draft':[('readonly',False)]}, help="Choose the method to use to compute the amount of depreciation lines.\n"\
" * Linear: Calculated on basis of: Gross Value / Number of Depreciations\n" \
" * Degressive: Calculated on basis of: Residual Value * Degressive Factor"),
'method_number': fields.integer('Number of Depreciations', readonly=True, states={'draft':[('readonly',False)]}, help="The number of depreciations needed to depreciate your asset"),
'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"),
'method_end': fields.date('Ending Date', readonly=True, states={'draft':[('readonly',False)]}),
'method_progress_factor': fields.float('Degressive Factor', readonly=True, states={'draft':[('readonly',False)]}),
'value_residual': fields.function(_amount_residual, method=True, digits_compute=dp.get_precision('Account'), string='Residual Value'),
'method_time': fields.selection([('number','Number of Depreciations'),('end','Ending Date')], 'Time Method', required=True, readonly=True, states={'draft':[('readonly',False)]},
help="Choose the method to use to compute the dates and number of depreciation lines.\n"\
" * Number of Depreciations: Fix the number of depreciation lines 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('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'),
'history_ids': fields.one2many('account.asset.history', 'asset_id', 'History', readonly=True),
'depreciation_line_ids': fields.one2many('account.asset.depreciation.line', 'asset_id', 'Depreciation Lines', readonly=True, states={'draft':[('readonly',False)],'open':[('readonly',False)]}),
'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)]}),
}
_defaults = {
'code': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').next_by_code(cr, uid, 'account.asset.code'),
'purchase_date': lambda obj, cr, uid, context: time.strftime('%Y-%m-%d'),
'active': True,
'state': 'draft',
'method': 'linear',
'method_number': 5,
'method_time': 'number',
'method_period': 12,
'method_progress_factor': 0.3,
'currency_id': lambda self,cr,uid,c: self.pool.get('res.users').browse(cr, uid, uid, c).company_id.currency_id.id,
'company_id': lambda self, cr, uid, context: self.pool.get('res.company')._company_default_get(cr, uid, 'account.asset.asset',context=context),
}
@api.onchange('company_id')
def onchange_company_id(self):
if self.company_id.currency_id.company_id and self.company_id.currency_id.company_id.id != self.company_id.id:
self.currency_id = False
else:
self.currency_id = self.company_id.currency_id.id
def _check_recursion(self, cr, uid, ids, context=None, parent=None):
return super(account_asset_asset, self)._check_recursion(cr, uid, ids, context=context, parent=parent)
@api.multi
@api.depends('account_move_line_ids')
def _entry_count(self):
for asset in self:
asset.entry_count = self.env['account.move.line'].search_count([('asset_id', '=', asset.id)])
def _check_prorata(self, cr, uid, ids, context=None):
for asset in self.browse(cr, uid, ids, context=context):
if asset.prorata and asset.method_time != 'number':
return False
return True
@api.one
@api.constrains('prorata', 'method_time')
def _check_prorata(self):
if self.prorata and self.method_time != 'number':
raise ValidationError(_('Prorata temporis can be applied only for time method "number of depreciations".'))
_constraints = [
(_check_recursion, 'Error ! You cannot create recursive assets.', ['parent_id']),
(_check_prorata, 'Prorata temporis can be applied only for time method "number of depreciations".', ['prorata']),
]
@api.onchange('category_id')
def onchange_category_id(self):
vals = self.onchange_category_id_values(self.category_id.id)
# We cannot use 'write' on an object that doesn't exist yet
if vals:
for k, v in vals['value'].iteritems():
setattr(self, k, v)
def onchange_category_id(self, cr, uid, ids, category_id, context=None):
res = {'value':{}}
asset_categ_obj = self.pool.get('account.asset.category')
def onchange_category_id_values(self, category_id):
if category_id:
category_obj = asset_categ_obj.browse(cr, uid, category_id, context=context)
res['value'] = {
'method': category_obj.method,
'method_number': category_obj.method_number,
'method_time': category_obj.method_time,
'method_period': category_obj.method_period,
'method_progress_factor': category_obj.method_progress_factor,
'method_end': category_obj.method_end,
'prorata': category_obj.prorata,
category = self.env['account.asset.category'].browse(category_id)
return {
'value': {
'method': category.method,
'method_number': category.method_number,
'method_time': category.method_time,
'method_period': category.method_period,
'method_progress_factor': category.method_progress_factor,
'method_end': category.method_end,
'prorata': category.prorata,
}
}
@api.onchange('method_time')
def onchange_method_time(self):
if self.method_time != 'number':
self.prorata = False
@api.multi
def copy_data(self, default=None):
if default is None:
default = {}
default['name'] = self.name + _(' (copy)')
return super(AccountAssetAsset, self).copy_data(default)[0]
@api.multi
def _compute_entries(self, period_id):
period = self.env['account.period'].browse(period_id)
depreciation_ids = self.env['account.asset.depreciation.line'].search([
('asset_id', 'in', self.ids), ('depreciation_date', '<=', period.date_stop),
('depreciation_date', '>=', period.date_start), ('move_check', '=', False)])
return depreciation_ids.create_move()
@api.model
def create(self, vals):
asset = super(AccountAssetAsset, self.with_context(mail_create_nolog=True)).create(vals)
asset.compute_depreciation_board()
return asset
@api.multi
def write(self, vals):
res = super(AccountAssetAsset, self).write(vals)
if 'depreciation_line_ids' not in vals:
self.compute_depreciation_board()
return res
def onchange_method_time(self, cr, uid, ids, method_time='number', context=None):
res = {'value': {}}
if method_time != 'number':
res['value'] = {'prorata': False}
return res
def _compute_entries(self, cr, uid, ids, period_id, context=None):
result = []
period_obj = self.pool.get('account.period')
depreciation_obj = self.pool.get('account.asset.depreciation.line')
period = period_obj.browse(cr, uid, period_id, context=context)
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)
context = dict(context or {}, depreciation_date=period.date_stop)
return depreciation_obj.create_move(cr, uid, depreciation_ids, context=context)
def create(self, cr, uid, vals, context=None):
asset_id = super(account_asset_asset, self).create(cr, uid, vals, context=context)
self.compute_depreciation_board(cr, uid, [asset_id], context=context)
return asset_id
def open_entries(self, cr, uid, ids, context=None):
context = dict(context or {}, search_default_asset_id=ids, default_asset_id=ids)
@api.multi
def open_entries(self):
return {
'name': _('Journal Items'),
'view_type': 'form',
@@ -352,128 +320,147 @@ class account_asset_asset(osv.osv):
'res_model': 'account.move.line',
'view_id': False,
'type': 'ir.actions.act_window',
'context': context,
'context': dict(self.env.context or {}, search_default_asset_id=self.id, default_asset_id=self.id),
}
class account_asset_depreciation_line(osv.osv):
class AccountAssetDepreciationLine(models.Model):
_name = 'account.asset.depreciation.line'
_description = 'Asset depreciation line'
def _get_move_check(self, cr, uid, ids, name, args, context=None):
res = {}
for line in self.browse(cr, uid, ids, context=context):
res[line.id] = bool(line.move_id)
return res
name = fields.Char(string='Depreciation Name', required=True, index=True)
sequence = fields.Integer(required=True)
asset_id = fields.Many2one('account.asset.asset', string='Asset', required=True, ondelete='cascade')
parent_state = fields.Selection(related='asset_id.state', string='State of Asset')
amount = fields.Float(string='Current Depreciation', digits=dp.get_precision('Account'), required=True)
remaining_value = fields.Float(string='Next Period Depreciation', digits=dp.get_precision('Account'), required=True)
depreciated_value = fields.Float(string='Amount Already Depreciated', required=True)
depreciation_date = fields.Date('Depreciation Date', index=True)
move_id = fields.Many2one('account.move', string='Depreciation Entry')
move_check = fields.Boolean(compute='_get_move_check', string='Posted', track_visibility='always', store=True)
_columns = {
'name': fields.char('Depreciation Name', required=True, select=1),
'sequence': fields.integer('Sequence', required=True),
'asset_id': fields.many2one('account.asset.asset', 'Asset', required=True, ondelete='cascade'),
'parent_state': fields.related('asset_id', 'state', type='char', string='State of Asset'),
'amount': fields.float('Current Depreciation', digits_compute=dp.get_precision('Account'), required=True),
'remaining_value': fields.float('Next Period Depreciation', digits_compute=dp.get_precision('Account'),required=True),
'depreciated_value': fields.float('Amount Already Depreciated', required=True),
'depreciation_date': fields.date('Depreciation Date', select=1),
'move_id': fields.many2one('account.move', 'Depreciation Entry'),
'move_check': fields.function(_get_move_check, method=True, type='boolean', string='Posted', store=True)
}
@api.one
@api.depends('move_id')
def _get_move_check(self):
self.move_check = bool(self.move_id)
def create_move(self, cr, uid, ids, context=None):
context = dict(context or {})
can_close = False
asset_obj = self.pool.get('account.asset.asset')
period_obj = self.pool.get('account.period')
move_obj = self.pool.get('account.move')
move_line_obj = self.pool.get('account.move.line')
currency_obj = self.pool.get('res.currency')
@api.multi
def create_move(self):
created_move_ids = []
asset_ids = []
for line in self.browse(cr, uid, ids, context=context):
depreciation_date = context.get('depreciation_date') or line.depreciation_date or time.strftime('%Y-%m-%d')
period_ids = period_obj.find(cr, uid, depreciation_date, context=context)
company_currency = line.asset_id.company_id.currency_id.id
current_currency = line.asset_id.currency_id.id
context.update({'date': depreciation_date})
amount = currency_obj.compute(cr, uid, current_currency, company_currency, line.amount, context=context)
sign = (line.asset_id.category_id.journal_id.type == 'purchase' and 1) or -1
for line in self:
depreciation_date = self.env.context.get('depreciation_date') or line.depreciation_date or fields.Date.context_today(self)
periods = self.env['account.period'].find(depreciation_date)
company_currency = line.asset_id.company_id.currency_id
current_currency = line.asset_id.currency_id
amount = company_currency.compute(line.amount, current_currency)
sign = (line.asset_id.category_id.journal_id.type == 'purchase' or line.asset_id.category_id.journal_id.type == 'sale' and 1) or -1
asset_name = line.asset_id.name
reference = line.name
move_vals = {
'name': asset_name,
'date': depreciation_date,
'ref': reference,
'period_id': period_ids and period_ids[0] or False,
'period_id': periods and periods[0].id or False,
'journal_id': line.asset_id.category_id.journal_id.id,
}
move_id = move_obj.create(cr, uid, move_vals, context=context)
}
move = self.env['account.move'].create(move_vals)
journal_id = line.asset_id.category_id.journal_id.id
partner_id = line.asset_id.partner_id.id
move_line_obj.create(cr, uid, {
'name': asset_name,
categ_type = line.asset_id.category_id.type
debit_account = line.asset_id.category_id.account_asset_id.id
credit_account = line.asset_id.category_id.account_depreciation_id.id
self.env['account.move.line'].create({
'name': asset_name or reference,
'ref': reference,
'move_id': move_id,
'account_id': line.asset_id.category_id.account_depreciation_id.id,
'move_id': move.id,
'account_id': credit_account,
'debit': 0.0,
'credit': amount,
'period_id': period_ids and period_ids[0] or False,
'period_id': periods.id or False,
'journal_id': journal_id,
'partner_id': partner_id,
'currency_id': company_currency != current_currency and current_currency or False,
'currency_id': company_currency != current_currency and current_currency or False,
'amount_currency': company_currency != current_currency and - sign * line.amount or 0.0,
'analytic_account_id': line.asset_id.category_id.account_analytic_id.id if categ_type == 'sale' else False,
'date': depreciation_date,
'asset_id': line.asset_id.id if categ_type == 'sale' else False,
})
move_line_obj.create(cr, uid, {
'name': asset_name,
self.env['account.move.line'].create({
'name': asset_name or reference,
'ref': reference,
'move_id': move_id,
'account_id': line.asset_id.category_id.account_expense_depreciation_id.id,
'move_id': move.id,
'account_id': debit_account,
'credit': 0.0,
'debit': amount,
'period_id': period_ids and period_ids[0] or False,
'period_id': periods.id or False,
'journal_id': journal_id,
'partner_id': partner_id,
'currency_id': company_currency != current_currency and current_currency or False,
'currency_id': company_currency != current_currency and current_currency or False,
'amount_currency': company_currency != current_currency and sign * line.amount or 0.0,
'analytic_account_id': line.asset_id.category_id.account_analytic_id.id,
'analytic_account_id': line.asset_id.category_id.account_analytic_id.id if categ_type == 'purchase' else False,
'date': depreciation_date,
'asset_id': line.asset_id.id
'asset_id': line.asset_id.id if categ_type == 'purchase' else False
})
self.write(cr, uid, line.id, {'move_id': move_id}, context=context)
created_move_ids.append(move_id)
asset_ids.append(line.asset_id.id)
line.write({'move_id': move.id, 'move_check': True})
created_move_ids.append(move.id)
asset_ids.append(line.asset_id)
partner_name = line.asset_id.partner_id.name
currency_name = line.asset_id.currency_id.name
def _format_message(message_description, tracked_values):
message = ''
if message_description:
message = '<span>%s</span>' % message_description
for name, values in tracked_values.iteritems():
message += '<div> &nbsp; &nbsp; &bull; <b>%s</b>: ' % name
message += '%s</div>' % values
return message
msg_values = {_('Currency'): currency_name, _('Amount'): line.amount}
if partner_name:
msg_values[_('Partner')] = partner_name
msg = _format_message(_('Depreciation line posted.'), msg_values)
line.asset_id.message_post(body=msg)
# we re-evaluate the assets to determine whether we can close them
for asset in asset_obj.browse(cr, uid, list(set(asset_ids)), context=context):
if currency_obj.is_zero(cr, uid, asset.currency_id, asset.value_residual):
for asset in asset_ids:
if asset.currency_id.is_zero(asset.value_residual):
asset.message_post(body=_("Document closed."))
asset.write({'state': 'close'})
asset.compute_depreciation_board()
return created_move_ids
@api.multi
def unlink(self):
for record in self:
if record.move_check:
if record.asset_id.category_id.type == 'purchase':
msg = _("You cannot delete posted depreciation lines.")
else:
msg = _("You cannot delete posted installment lines.")
raise UserError(msg)
return super(AccountAssetDepreciationLine, self).unlink()
class account_move_line(osv.osv):
class AccountMoveLine(models.Model):
_inherit = 'account.move.line'
_columns = {
'asset_id': fields.many2one('account.asset.asset', 'Asset', ondelete="restrict"),
}
asset_id = fields.Many2one('account.asset.asset', string='Asset', ondelete="restrict")
class account_asset_history(osv.osv):
class AccountAssetHistory(models.Model):
_name = 'account.asset.history'
_description = 'Asset history'
_columns = {
'name': fields.char('History name', select=1),
'user_id': fields.many2one('res.users', 'User', required=True),
'date': fields.date('Date', required=True),
'asset_id': fields.many2one('account.asset.asset', 'Asset', required=True),
'method_time': fields.selection([('number','Number of Depreciations'),('end','Ending Date')], 'Time Method', required=True,
help="The method to use to compute the dates and number of depreciation lines.\n"\
"Number of Depreciations: Fix the number of depreciation lines and the time between 2 depreciations.\n" \
"Ending Date: Choose the time between 2 depreciations and the date the depreciations won't go beyond."),
'method_number': fields.integer('Number of Depreciations', help="The number of depreciations needed to depreciate your asset"),
'method_period': fields.integer('Period Length', help="Time in month between two depreciations"),
'method_end': fields.date('Ending date'),
'note': fields.text('Note'),
}
_order = 'date desc'
_defaults = {
'date': lambda *args: time.strftime('%Y-%m-%d'),
'user_id': lambda self, cr, uid, ctx: uid
}
name = fields.Char(string='History name', index=True)
user_id = fields.Many2one('res.users', string='User', required=True, default=lambda self: self.env.user)
date = fields.Date(required=True, default=fields.Date.context_today)
asset_id = fields.Many2one('account.asset.asset', string='Asset', required=True)
method_time = fields.Selection([('number', 'Number of Depreciations'), ('end', 'Ending Date')], string='Time Method', required=True,
help="The method to use to compute the dates and number of depreciation lines.\n"
"Number of Depreciations: Fix the number of depreciation lines and the time between 2 depreciations.\n"
"Ending Date: Choose the time between 2 depreciations and the date the depreciations won't go beyond.")
method_number = fields.Integer(string='Number of Depreciations', help="The number of depreciations needed to depreciate your asset")
method_period = fields.Integer(string='Period Length', help="Time in months between two depreciations")
method_end = fields.Date(string='Ending date')
note = fields.Text()
+92 -19
View File
@@ -1,36 +1,49 @@
<?xml version="1.0" ?>
<openerp>
<odoo>
<data noupdate="1">
<!--
Asset Category Demo
-->
<record id="account_asset_category_fixedassets0" model="account.asset.category">
<field name="account_expense_depreciation_id" ref="account.a_expense"/>
<field name="account_depreciation_id" ref="account.a_expense"/>
<field name="account_asset_id" ref="account.xfa"/>
<field name="account_depreciation_id" ref="account.xfa"/>
<field name="journal_id" ref="account.expenses_journal"/>
<field name="name">Hardware - 3 Years</field>
<field name="method_number">3</field>
<field name="method_period">12</field>
</record>
<record id="account_asset_category_sale" model="account.asset.category">
<field name="account_expense_depreciation_id" ref="account.a_expense"/>
<field name="account_depreciation_id" ref="account.a_expense"/>
<field name="account_asset_id" ref="account.xfa"/>
<field name="account_depreciation_id" ref="account.xfa"/>
<field name="journal_id" ref="account.expenses_journal"/>
<field name="name">Cars - 5 Years</field>
<field name="method_number">5</field>
<field name="method_period">12</field>
</record>
<record id="account_asset_category_sale" model="account.asset.category">
<field name="account_expense_depreciation_id" ref="account.a_sale"/>
<record id="account_asset_category_sale0" model="account.asset.category">
<field name="account_depreciation_id" ref="account.a_sale"/>
<field name="account_asset_id" ref="account.xfa"/>
<field name="account_depreciation_id" ref="account.xfa"/>
<field name="journal_id" ref="account.expenses_journal"/>
<field name="name">Revenue Recognition Maintenance Contract - 3 Years</field>
<field name="journal_id" ref="account.sales_journal"/>
<field name="name">Maintenance Contract - 3 Years</field>
<field name="method_number">3</field>
<field name="method_period">12</field>
<field name="prorata" eval="True"/>
<field name="type">sale</field>
</record>
<record id="account_asset_category_sale1" model="account.asset.category">
<field name="account_asset_id" ref="account.xfa"/>
<field name="account_depreciation_id" ref="account.a_sale"/>
<field name="journal_id" ref="account.sales_journal"/>
<field name="name">Maintenance Contract - 1 Year</field>
<field name="method_number">12</field>
<field name="method_period">1</field>
<field name="prorata" eval="True"/>
<field name="type">sale</field>
</record>
<!--
@@ -43,8 +56,8 @@
<field eval="12" name="method_period"/>
<field eval="5" name="method_number"/>
<field name="name">CEO's Car</field>
<field eval="12000.0" name="purchase_value"/>
<field name="category_id" ref="account_asset_category_fixedassets0"/>
<field eval="12000.0" name="value"/>
<field name="category_id" ref="account_asset_category_sale"/>
</record>
<record id="account_asset_asset_cab0" model="account.asset.asset">
@@ -52,9 +65,8 @@
<field eval="0.0" name="salvage_value"/>
<field name="method_time">end</field>
<field name="name">V6 Engine and 10 inches tires</field>
<field eval="2800.0" name="purchase_value"/>
<field eval="2800.0" name="value"/>
<field name="category_id" ref="account_asset_category_fixedassets0"/>
<field name="parent_id" ref="account_asset_asset_vehicles0"/>
</record>
<record id="account_asset_asset_office0" model="account.asset.asset">
@@ -62,12 +74,73 @@
<field eval="100000.0" name="salvage_value"/>
<field name="state">open</field>
<field eval="12" name="method_period"/>
<field eval="20" name="method_number"/>
<field name="purchase_date" eval="time.strftime('%Y-01-01')"/>
<field eval="3" name="method_number"/>
<field name="date" eval="time.strftime('%Y-01-01')"/>
<field name="name">Office</field>
<field eval="500000.0" name="purchase_value"/>
<field eval="500000.0" name="value"/>
<field name="category_id" ref="account_asset_category_fixedassets0"/>
</record>
<record id="account_asset_asset_pc" model="account.asset.asset">
<field eval="1" name="prorata"/>
<field name="state">draft</field>
<field eval="12" name="method_period"/>
<field eval="3" name="method_number"/>
<field name="date" eval="time.strftime('%Y-01-01')"/>
<field name="name">Car Maintenance</field>
<field eval="30000.0" name="value"/>
<field name="category_id" ref="account_asset_category_sale0"/>
</record>
<record id="account_asset_asset_a/c" model="account.asset.asset">
<field eval="1" name="prorata"/>
<field name="state">open</field>
<field eval="1" name="method_period"/>
<field eval="12" name="method_number"/>
<field name="date" eval="time.strftime('%Y-01-01')"/>
<field name="name">Air Conditioner Maintenance Contract</field>
<field eval="1000.0" name="value"/>
<field name="category_id" ref="account_asset_category_sale1"/>
</record>
<!--
Assets Tests
-->
<record id="data_fiscalyear_plus1" model="account.fiscalyear">
<field ref="base.main_company" name="company_id"/>
<field eval="'%s-01-01' %(datetime.now().year+1)" name="date_start"/>
<field eval="'%s-12-31' %(datetime.now().year+1)" name="date_stop"/>
<field name="name" eval="'Fiscal Year X %s' %(datetime.now().year+1)"/>
<field name="code" eval="'FY%s' %(datetime.now().year+1)"/>
</record>
<record id="data_fiscalyear_plus2" model="account.fiscalyear">
<field ref="base.main_company" name="company_id"/>
<field eval="'%s-01-01' %(datetime.now().year+2)" name="date_start"/>
<field eval="'%s-12-31' %(datetime.now().year+2)" name="date_stop"/>
<field name="name" eval="'Fiscal Year X %s' %(datetime.now().year+2)"/>
<field name="code" eval="'FY%s' %(datetime.now().year+2)"/>
</record>
<record id="data_fiscalyear_plus3" model="account.fiscalyear">
<field ref="base.main_company" name="company_id"/>
<field eval="'%s-01-01' %(datetime.now().year+3)" name="date_start"/>
<field eval="'%s-12-31' %(datetime.now().year+3)" name="date_stop"/>
<field name="name" eval="'Fiscal Year X %s' %(datetime.now().year+3)"/>
<field name="code" eval="'FY%s' %(datetime.now().year+3)"/>
</record>
<record id="data_fiscalyear_plus4" model="account.fiscalyear">
<field ref="base.main_company" name="company_id"/>
<field eval="'%s-01-01' %(datetime.now().year+4)" name="date_start"/>
<field eval="'%s-12-31' %(datetime.now().year+4)" name="date_stop"/>
<field name="name" eval="'Fiscal Year X %s' %(datetime.now().year+4)"/>
<field name="code" eval="'FY%s' %(datetime.now().year+4)"/>
</record>
<record id="data_fiscalyear_plus5" model="account.fiscalyear">
<field ref="base.main_company" name="company_id"/>
<field eval="'%s-01-01' %(datetime.now().year+5)" name="date_start"/>
<field eval="'%s-12-31' %(datetime.now().year+5)" name="date_stop"/>
<field name="name" eval="'Fiscal Year X %s' %(datetime.now().year+5)"/>
<field name="code" eval="'FY%s' %(datetime.now().year+5)"/>
</record>
</data>
</openerp>
</odoo>
+40 -55
View File
@@ -1,66 +1,51 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
# -*- coding: utf-8 -*-
from openerp.osv import fields, osv
from datetime import datetime
from dateutil.relativedelta import relativedelta
from openerp import api, fields, models
import openerp.addons.decimal_precision as dp
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT as DF
class account_invoice(osv.osv):
class AccountInvoice(models.Model):
_inherit = 'account.invoice'
def action_number(self, cr, uid, ids, *args):
result = super(account_invoice, self).action_number(cr, uid, ids, *args)
for inv in self.browse(cr, uid, ids):
self.pool.get('account.invoice.line').asset_create(cr, uid, inv.invoice_line)
@api.multi
def action_number(self):
result = super(AccountInvoice, self).action_number()
for inv in self:
inv.invoice_line.asset_create()
return result
def line_get_convert(self, cr, uid, x, part, date, context=None):
res = super(account_invoice, self).line_get_convert(cr, uid, x, part, date, context=context)
res['asset_id'] = x.get('asset_id', False)
@api.model
def line_get_convert(self, line, part, date):
res = super(AccountInvoice, self).line_get_convert(line, part, date)
res['asset_id'] = line.get('asset_id', False)
return res
class account_invoice_line(osv.osv):
class AccountInvoiceLine(models.Model):
_inherit = 'account.invoice.line'
_columns = {
'asset_category_id': fields.many2one('account.asset.category', 'Asset Category'),
}
def asset_create(self, cr, uid, lines, context=None):
context = context or {}
asset_obj = self.pool.get('account.asset.asset')
for line in lines:
if line.asset_category_id:
vals = {
'name': line.name,
'code': line.invoice_id.number or False,
'category_id': line.asset_category_id.id,
'purchase_value': line.price_subtotal,
'period_id': line.invoice_id.period_id.id,
'partner_id': line.invoice_id.partner_id.id,
'company_id': line.invoice_id.company_id.id,
'currency_id': line.invoice_id.currency_id.id,
'purchase_date' : line.invoice_id.date_invoice,
}
changed_vals = asset_obj.onchange_category_id(cr, uid, [], vals['category_id'], context=context)
vals.update(changed_vals['value'])
asset_id = asset_obj.create(cr, uid, vals, context=context)
if line.asset_category_id.open_asset:
asset_obj.validate(cr, uid, [asset_id], context=context)
asset_category_id = fields.Many2one('account.asset.category', string='Asset Category')
@api.one
def asset_create(self):
if self.asset_category_id and self.asset_category_id.method_number > 1:
vals = {
'name': self.name,
'code': self.invoice_id.number or False,
'category_id': self.asset_category_id.id,
'value': self.price_subtotal,
'partner_id': self.invoice_id.partner_id.id,
'company_id': self.invoice_id.company_id.id,
'currency_id': self.invoice_id.currency_id.id,
'date': self.asset_start_date or self.invoice_id.date_invoice,
'invoice_id': self.invoice_id.id,
}
changed_vals = self.env['account.asset.asset'].onchange_category_id_values(vals['category_id'])
vals.update(changed_vals['value'])
asset = self.env['account.asset.asset'].create(vals)
if self.asset_category_id.open_asset:
asset.validate()
return True
@@ -1,29 +0,0 @@
<?xml version="1.0"?>
<openerp>
<data>
<!-- Fiscal Year -->
<record model="ir.ui.view" id="view_account_invoice_asset_form">
<field name="name">account.invoice.line.form</field>
<field name="model">account.invoice.line</field>
<field name="inherit_id" ref="account.view_invoice_line_form"/>
<field name="arch" type="xml">
<field name="account_id" position="after">
<field name="asset_category_id"/>
</field>
</field>
</record>
<record model="ir.ui.view" id="view_invoice_asset_category">
<field name="name">account.invoice.supplier.form</field>
<field name="model">account.invoice</field>
<field name="inherit_id" ref="account.invoice_supplier_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='invoice_line']/tree/field[@name='quantity']" position="before">
<field name="asset_category_id"/>
</xpath>
</field>
</record>
</data>
</openerp>
-19
View File
@@ -1,22 +1,3 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import account_asset_report
@@ -1,64 +1,46 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
# -*- coding: utf-8 -*-
from openerp import fields, models, tools
from openerp import tools
from openerp.osv import fields, osv
class asset_asset_report(osv.osv):
class AssetAssetReport(models.Model):
_name = "asset.asset.report"
_description = "Assets Analysis"
_auto = False
_columns = {
'name': fields.char('Year', required=False, readonly=True),
'purchase_date': fields.date('Purchase Date', readonly=True),
'depreciation_date': fields.date('Depreciation Date', readonly=True),
'asset_id': fields.many2one('account.asset.asset', string='Asset', readonly=True),
'asset_category_id': fields.many2one('account.asset.category',string='Asset category'),
'partner_id': fields.many2one('res.partner', 'Partner', readonly=True),
'state': fields.selection([('draft','Draft'),('open','Running'),('close','Close')], 'Status', readonly=True),
'depreciation_value': fields.float('Amount of Depreciation Lines', readonly=True),
'move_check': fields.boolean('Posted', readonly=True),
'nbr': fields.integer('# of Depreciation Lines', readonly=True),
'gross_value': fields.float('Gross Amount', readonly=True),
'posted_value': fields.float('Posted Amount', readonly=True),
'unposted_value': fields.float('Unposted Amount', readonly=True),
'company_id': fields.many2one('res.company', 'Company', readonly=True),
}
name = fields.Char(string='Year', required=False, readonly=True)
date = fields.Date(readonly=True)
depreciation_date = fields.Date(string='Depreciation Date', readonly=True)
asset_id = fields.Many2one('account.asset.asset', string='Asset', readonly=True)
asset_category_id = fields.Many2one('account.asset.category', string='Asset category', readonly=True)
partner_id = fields.Many2one('res.partner', string='Partner', readonly=True)
state = fields.Selection([('draft', 'Draft'), ('open', 'Running'), ('close', 'Close')], string='Status', readonly=True)
depreciation_value = fields.Float(string='Amount of Depreciation Lines', readonly=True)
installment_value = fields.Float(string='Amount of Installment Lines', readonly=True)
move_check = fields.Boolean(string='Posted', readonly=True)
installment_nbr = fields.Integer(string='# of Installment Lines', readonly=True)
depreciation_nbr = fields.Integer(string='# of Depreciation Lines', readonly=True)
gross_value = fields.Float(string='Gross Amount', readonly=True)
posted_value = fields.Float(string='Posted Amount', readonly=True)
unposted_value = fields.Float(string='Unposted Amount', readonly=True)
company_id = fields.Many2one('res.company', string='Company', readonly=True)
def init(self, cr):
tools.drop_view_if_exists(cr, 'asset_asset_report')
cr.execute("""
create or replace view asset_asset_report as (
select
tools.drop_view_if_exists(cr, 'asset_asset_report')
cr.execute("""
create or replace view asset_asset_report as (
select
min(dl.id) as id,
dl.name as name,
dl.depreciation_date as depreciation_date,
a.purchase_date as purchase_date,
a.date as date,
(CASE WHEN (select min(d.id) from account_asset_depreciation_line as d
left join account_asset_asset as ac ON (ac.id=d.asset_id)
where a.id=ac.id) = min(dl.id)
THEN a.purchase_value
THEN a.value
ELSE 0
END) as gross_value,
dl.amount as depreciation_value,
dl.amount as depreciation_value,
dl.amount as installment_value,
(CASE WHEN dl.move_check
THEN dl.amount
ELSE 0
@@ -72,13 +54,13 @@ class asset_asset_report(osv.osv):
a.category_id as asset_category_id,
a.partner_id as partner_id,
a.state as state,
count(dl.*) as nbr,
count(dl.*) as installment_nbr,
count(dl.*) as depreciation_nbr,
a.company_id as company_id
from account_asset_depreciation_line dl
left join account_asset_asset a on (dl.asset_id=a.id)
group by
group by
dl.amount,dl.asset_id,dl.depreciation_date,dl.name,
a.purchase_date, dl.move_check, a.state, a.category_id, a.partner_id, a.company_id,
a.purchase_value, a.id, a.salvage_value
a.date, dl.move_check, a.state, a.category_id, a.partner_id, a.company_id,
a.value, a.id, a.salvage_value
)""")
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<odoo>
<record model="ir.ui.view" id="action_account_asset_report_pivot">
<field name="name">asset.asset.report.pivot</field>
@@ -8,7 +7,7 @@
<field name="arch" type="xml">
<pivot string="Assets Analysis" disable_linking="True">
<field name="asset_category_id" type="row"/>
<field name="purchase_date" type="col"/>
<field name="date" type="col"/>
<field name="posted_value" type="measure"/>
<field name="gross_value" type="measure"/>
<field name="depreciation_value" type="measure"/>
@@ -21,18 +20,46 @@
<field name="arch" type="xml">
<graph string="Assets Analysis" type="pivot">
<field name="asset_category_id" type="row"/>
<field name="purchase_date" type="col"/>
<field name="date" type="col"/>
<field name="gross_value" type="measure"/>
</graph>
</field>
</record>
<!--
Asset Revenue Recognition Graph
-->
<record model="ir.ui.view" id="action_account_revenue_report_pivot">
<field name="name">asset.asset.report.pivot</field>
<field name="model">asset.asset.report</field>
<field name="arch" type="xml">
<pivot string="Deferred Revenues Analysis" disable_linking="True">
<field name="asset_category_id" type="row"/>
<field name="date" type="col"/>
<field name="gross_value" type="measure"/>
</pivot>
</field>
</record>
<record model="ir.ui.view" id="action_account_revenue_report_graph">
<field name="name">asset.revenue.report.graph</field>
<field name="model">asset.asset.report</field>
<field name="arch" type="xml">
<graph string="Deferred Revenues Analysis" type="pivot">
<field name="asset_id" type="row"/>
<field name="installment_nbr" type="measure"/>
<field name="gross_value" type="measure"/>
<field name="installment_value" type="measure"/>
<field name="posted_value" type="measure"/>
</graph>
</field>
</record>
<record id="view_asset_asset_report_search" model="ir.ui.view">
<field name="name">asset.asset.report.search</field>
<field name="model">asset.asset.report</field>
<field name="arch" type="xml">
<search string="Assets Analysis">
<field name="purchase_date"/>
<field name="date"/>
<field name="depreciation_date"/>
<filter string="Draft" domain="[('state','=','draft')]" help="Assets in draft state"/>
<filter string="Running" domain="[('state','=','open')]" help="Assets in running state"/>
@@ -50,13 +77,46 @@
<filter string="Company" context="{'group_by':'company_id'}" groups="base.group_multi_company"/>
<separator/>
<filter string="Purchase Month" help="Date of asset purchase"
context="{'group_by':'purchase_date:month'}"/>
context="{'group_by':'date:month'}"/>
<filter string="Depreciation Month" help="Date of depreciation"
context="{'group_by':'depreciation_date:month'}"/>
</group>
</search>
</field>
</record>
<!--
Asset Revenue Recognition Search
-->
<record id="view_asset_revenue_report_search" model="ir.ui.view">
<field name="name">asset.revenue.report.search</field>
<field name="model">asset.asset.report</field>
<field name="arch" type="xml">
<search string="Deferred Revenues Analysis">
<field name="date"/>
<field name="depreciation_date"/>
<filter string="Draft" domain="[('state','=','draft')]" help="Recognition in draft state"/>
<filter string="Running" domain="[('state','=','open')]" help="Assets in running state"/>
<separator/>
<filter string="Posted" name="posted" domain="[('move_check','=',True)]" help="Posted depreciation lines" context="{'unposted_value_visible': 0}"/>
<field name="asset_id"/>
<field name="asset_category_id"/>
<group expand="0" string="Extended Filters...">
<field name="partner_id" filter_domain="[('partner_id','child_of',self)]"/>
<field name="company_id" groups="base.group_multi_company"/>
</group>
<group expand="1" string="Group By...">
<filter string="Revenue Recognition" name="revenue" context="{'group_by':'asset_id'}"/>
<filter string="Category" name="category" context="{'group_by':'asset_category_id'}"/>
<filter string="Company" context="{'group_by':'company_id'}" groups="base.group_multi_company"/>
<filter string="Sales Month" domain="[('date','=',time.strftime('%%Y-%%m-%%d'))]" context="{'group_by':'date'}" help="Date of Revenue Sales"/>
<filter string="Revenue Month" name='rev_month'
context="{'group_by':'depreciation_date'}" help="Revenue Month"/>
</group>
</search>
</field>
</record>
<record model="ir.actions.act_window" id="action_asset_asset_report">
<field name="name">Assets Analysis</field>
@@ -64,18 +124,47 @@
<field name="view_type">form</field>
<field name="view_mode">pivot,graph</field>
<field name="search_view_id" ref="view_asset_asset_report_search"/>
<field name="domain">[('asset_category_id.type', '=', 'purchase')]</field>
<field name="context">{}</field> <!-- force empty -->
<field name="help" type="html">
<p>
From this report, you can have an overview on all depreciation. The
From this report, you can have an overview on all depreciations. The
tool search can also be used to personalise your Assets reports and
so, match this analysis to your needs;
so, match this analysis to your needs.
</p>
</field>
</record>
<!--
Asset Revenue Recognition Action
-->
<record model="ir.actions.act_window" id="action_asset_revenue_report">
<field name="name">Deferred Revenues Analysis</field>
<field name="res_model">asset.asset.report</field>
<field name="view_type">form</field>
<field name="view_mode">pivot,graph</field>
<field name="search_view_id" ref="view_asset_revenue_report_search"/>
<field name="domain">[('asset_category_id.type', '=', 'sale')]</field>
<field name="context">{}</field>
<field name="help" type="html">
<p>
From this report, you can have an overview on all depreciations. The
tool search can also be used to personalise your Revenue Recognition reports and
so, match this analysis to your needs.
</p>
</field>
</record>
<menuitem action="action_asset_asset_report"
id="menu_action_asset_asset_report"
parent="account.menu_finance_reporting"/>
</data>
</openerp>
parent="account.menu_finance_reporting" sequence="21"/>
<!--
Asset Revenue Recognition Menu
-->
<menuitem action="action_asset_revenue_report"
id="menu_action_asset_revenue_report"
parent="account.menu_finance_reporting" sequence="20"/>
</odoo>
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<odoo>
<data noupdate="1">
<record id="account_asset_category_multi_company_rule" model="ir.rule">
<field name="name">Account Asset Category multi-company</field>
@@ -16,4 +16,4 @@
</record>
</data>
</openerp>
</odoo>
@@ -0,0 +1,30 @@
/*
Purpose : show toggle button on depreciation/installment lines for posted/unposted line.
Details : called in list view with "<button name="create_move" type="object" widget="widgetonbutton"/>",
this will call the method create_move on the object account.asset.depreciation.line
*/
openerp.account_asset = function (instance) {
var _t = instance.web._t,
_lt = instance.web._lt;
var QWeb = instance.web.qweb;
instance.web.account_asset = instance.web.account_asset || {};
instance.web.account_asset.WidgetOnButton = instance.web.list.Column.extend({
format: function (row_data, options) {
this._super(row_data, options);
this.has_value = !!row_data.move_check.value;
this.parent_state = row_data.parent_state.value;
this.icon = this.has_value ? 'gtk-yes' : 'gtk-no'; // or STOCK_YES and STOCK_NO
this.string = this.has_value ? 'Posted' : 'Unposted'
var template = this.icon && 'ListView.row.buttonwidget';
return QWeb.render(template, {
widget: this,
prefix: instance.session.prefix,
disabled: this.has_value,
invisible : true ? this.parent_state !== 'open' : false
});
},
});
instance.web.list.columns.add("button.widgetonbutton", "instance.web.account_asset.WidgetOnButton");
};
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template">
<button t-name="ListView.row.buttonwidget" type="button"
t-att-title="widget.string" t-att-disabled="disabled || undefined"
t-att-class="disabled ? 'oe_list_button_disabled' : '',invisible ? 'oe_form_invisible' : ''"
><img t-attf-src="#{prefix}/web/static/src/img/icons/#{widget.icon}.png"
t-att-alt="widget.string"/></button>
</templates>
@@ -1,35 +0,0 @@
-
In order to test the process of Account Asset, I perform a action to confirm Account Asset.
-
!python {model: account.asset.asset}: |
self.validate(cr, uid, [ref("account_asset_asset_vehicles0")])
-
I check Asset is now in Open state.
-
!assert {model: account.asset.asset, id: account_asset_asset_vehicles0, severity: error, string: Asset should be in Open state}:
- state == 'open'
-
I compute depreciation lines for asset of CEO's Car .
-
!python {model: account.asset.asset}: |
self.compute_depreciation_board(cr, uid, [ref("account_asset_asset_vehicles0")])
# pressing computation button can be remove if creation of depreciation lines while asset is created
value = self.browse(cr, uid, [ref("account_asset_asset_vehicles0")])[0]
assert value.method_number == len(value.depreciation_line_ids), 'Depreciation lines not created correctly'
-
I create account move for all depreciation lines.
-
!python {model: account.asset.depreciation.line}: |
ids = self.search(cr, uid, [('asset_id','=',ref('account_asset_asset_vehicles0'))])
self.create_move(cr, uid, ids)
-
I check the move line is created.
-
!python {model: account.asset.asset}: |
asset = self.browse(cr, uid, [ref("account_asset_asset_vehicles0")])[0]
assert len(asset.depreciation_line_ids) == len(asset.account_move_line_ids), 'Move lines not created correctly'
-
I Check that After creating all the moves of depreciation lines the state "Close".
-
!assert {model: account.asset.asset, id: account_asset_asset_vehicles0}:
- state == 'close'
@@ -1,51 +0,0 @@
-
!record {model: account.asset.category, id: account_asset_category_fixedassets0}:
account_asset_id: account.xfa
-
!record {model: account.asset.asset, id: account_asset_asset_vehicles0}:
category_id: account_asset_category_sale
-
!record {model: account.asset.asset, id: account_asset_asset_vehicles0}:
method_number: 5
-
!record {model: account.fiscalyear, id: data_fiscalyear_plus1}:
company_id: base.main_company
date_start: !eval "'%s-01-01' %(datetime.now().year+1)"
date_stop: !eval "'%s-12-31' %(datetime.now().year+1)"
name: !eval "'Fiscal Year X %s' %(datetime.now().year+1)"
code: !eval "'FY%s' %(datetime.now().year+1)"
-
!record {model: account.fiscalyear, id: data_fiscalyear_plus2}:
company_id: base.main_company
date_start: !eval "'%s-01-01' %(datetime.now().year+2)"
date_stop: !eval "'%s-12-31' %(datetime.now().year+2)"
name: !eval "'Fiscal Year X %s' %(datetime.now().year+2)"
code: !eval "'FY%s' %(datetime.now().year+2)"
-
!record {model: account.fiscalyear, id: data_fiscalyear_plus3}:
company_id: base.main_company
date_start: !eval "'%s-01-01' %(datetime.now().year+3)"
date_stop: !eval "'%s-12-31' %(datetime.now().year+3)"
name: !eval "'Fiscal Year X %s' %(datetime.now().year+3)"
code: !eval "'FY%s' %(datetime.now().year+3)"
-
!record {model: account.fiscalyear, id: data_fiscalyear_plus4}:
company_id: base.main_company
date_start: !eval "'%s-01-01' %(datetime.now().year+4)"
date_stop: !eval "'%s-12-31' %(datetime.now().year+4)"
name: !eval "'Fiscal Year X %s' %(datetime.now().year+4)"
code: !eval "'FY%s' %(datetime.now().year+4)"
-
!record {model: account.fiscalyear, id: data_fiscalyear_plus5}:
company_id: base.main_company
date_start: !eval "'%s-01-01' %(datetime.now().year+5)"
date_stop: !eval "'%s-12-31' %(datetime.now().year+5)"
name: !eval "'Fiscal Year X %s' %(datetime.now().year+5)"
code: !eval "'FY%s' %(datetime.now().year+5)"
-
!python {model: account.fiscalyear}: |
self.create_period(cr, uid, [ref("data_fiscalyear_plus1")])
self.create_period(cr, uid, [ref("data_fiscalyear_plus2")])
self.create_period(cr, uid, [ref("data_fiscalyear_plus3")])
self.create_period(cr, uid, [ref("data_fiscalyear_plus4")])
self.create_period(cr, uid, [ref("data_fiscalyear_plus5")])
@@ -1,27 +0,0 @@
-
I create a record to change the duration of asset for calculating depreciation.
-
!record {model: asset.modify, id: asset_modify_number_0, context: "{'active_id': ref('account_asset_asset_office0')}"}:
method_number: 10.0
-
I change the duration.
-
!python {model: asset.modify}: |
context = {"active_id":ref('account_asset_asset_office0')}
self.modify(cr, uid, [ref("asset_modify_number_0")], context=context)
-
I check the proper depreciation lines created.
-
!assert {model: account.asset.asset, id: account_asset.account_asset_asset_office0}:
- method_number == len(depreciation_line_ids) -1
-
I create a period to compute a asset on period.
-
!record {model: asset.depreciation.confirmation.wizard, id: asset_compute_period_0}:
{}
-
I compute a asset on period.
-
!python {model: asset.depreciation.confirmation.wizard}: |
context = {"active_ids": [ref("menu_asset_depreciation_confirmation_wizard")], "active_id":ref('menu_asset_depreciation_confirmation_wizard')}
self.asset_compute(cr, uid, [ref("asset_compute_period_0")], context=context)
+5
View File
@@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
#
##############################################################################
from . import test_account_asset
@@ -0,0 +1,121 @@
# -*- coding: utf-8 -*-
from openerp.tests import common
class TestAccountAsset(common.TransactionCase):
def test_00_account_asset_asset(self):
self.browse_ref("account_asset.data_fiscalyear_plus1").create_period()
self.browse_ref("account_asset.data_fiscalyear_plus2").create_period()
self.browse_ref("account_asset.data_fiscalyear_plus3").create_period()
self.browse_ref("account_asset.data_fiscalyear_plus4").create_period()
self.browse_ref("account_asset.data_fiscalyear_plus5").create_period()
# In order to test the process of Account Asset, I perform a action to confirm Account Asset.
self.browse_ref("account_asset.account_asset_asset_vehicles0").validate()
# I check Asset is now in Open state.
self.assertEqual(self.browse_ref("account_asset.account_asset_asset_vehicles0").state, 'open',
'Asset should be in Open state')
# I compute depreciation lines for asset of CEOs Car.
self.browse_ref("account_asset.account_asset_asset_vehicles0").compute_depreciation_board()
value = self.browse_ref("account_asset.account_asset_asset_vehicles0")
self.assertEqual(value.method_number, len(value.depreciation_line_ids),
'Depreciation lines not created correctly')
# I create account move for all depreciation lines.
ids = self.env['account.asset.depreciation.line'].search([('asset_id', '=', self.ref('account_asset.account_asset_asset_vehicles0'))])
for line in ids:
line.create_move()
# I check the move line is created.
asset = self.env['account.asset.asset'].browse([self.ref("account_asset.account_asset_asset_vehicles0")])[0]
self.assertEqual(len(asset.depreciation_line_ids), len(asset.account_move_line_ids),
'Move lines not created correctly')
# I Check that After creating all the moves of depreciation lines the state "Close".
self.assertEqual(self.browse_ref("account_asset.account_asset_asset_vehicles0").state, 'close',
'State of asset should be close')
invoice = self.env['account.invoice'].create({
'partner_id': self.ref("base.res_partner_12"),
'account_id': self.ref("account.a_sale"),
})
self.env['account.invoice.line'].create({
'invoice_id': invoice.id,
'name': 'Insurance claim',
'price_unit': 450,
'quantity': 1,
'asset_category_id': self.ref("account_asset.account_asset_category_sale1"),
})
invoice.signal_workflow('invoice_open')
from datetime import datetime
from dateutil.relativedelta import relativedelta
line_obj = self.env['account.asset.depreciation.line']
recognition_ids = self.env['account.asset.asset'].search([('code', '=', invoice.number)])
self.assertTrue(recognition_ids,
'Revenue recognition has been not created from invoice.')
# I confirm revenue recognition.
for asset in recognition_ids:
asset.validate()
recognition = recognition_ids[0]
first_invoice_line = invoice.invoice_line[0]
self.assertTrue(recognition.state == 'open',
'Recognition should be in Open state')
self.assertEqual(recognition.value, first_invoice_line.price_subtotal,
'Recognition value is not same as invoice line.')
# I post installment lines.
line_ids = [rec for rec in recognition.depreciation_line_ids]
for line in line_ids:
line.create_move()
# I check that move line is created from posted installment lines.
self.assertEqual(len(recognition.depreciation_line_ids), len(recognition.account_move_line_ids),
'Move lines not created correctly.')
# I check data in move line and installment line.
first_installment_line = recognition.depreciation_line_ids[0]
first_move_line = recognition.account_move_line_ids[0]
self.assertEqual(first_installment_line.amount, first_move_line.credit,
'First installment line amount is incorrect.')
remaining_value = recognition.value - first_installment_line.amount
self.assertEqual(first_installment_line.remaining_value, recognition.value - first_installment_line.amount,
'Remaining value is incorrect.')
# I check next installment date.
last_installment_date = datetime.strptime(first_installment_line.depreciation_date, '%Y-%m-%d')
installment_date = (last_installment_date+relativedelta(months=+recognition.method_period))
self.assertEqual(recognition.depreciation_line_ids[1].depreciation_date, str(installment_date.date()),
'Installment date is incorrect.')
# WIZARD
# I create a record to change the duration of asset for calculating depreciation.
account_asset_asset_office0 = self.browse_ref('account_asset.account_asset_asset_office0')
asset_modify_number_0 = self.env['asset.modify'].create({
'name': 'Test reason',
'method_number': 10.0,
}).with_context({'active_id': account_asset_asset_office0.id})
# I change the duration.
asset_modify_number_0.with_context({'active_id': account_asset_asset_office0.id}).modify()
# I check the proper depreciation lines created.
self.assertEqual(account_asset_asset_office0.method_number, len(account_asset_asset_office0.depreciation_line_ids) - 1)
# I compute a asset on period.
context = {
"active_ids": [self.ref("account_asset.menu_asset_depreciation_confirmation_wizard")],
"active_id": self.ref('account_asset.menu_asset_depreciation_confirmation_wizard'),
'type': 'sale'
}
asset_compute_period_0 = self.env['asset.depreciation.confirmation.wizard'].create({
'period_id': self.env['account.period'].find()[0].id
})
asset_compute_period_0.with_context(context).asset_compute()
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="assets_backend" name="account assets" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<script type="text/javascript" src="/account_asset/static/src/js/account_asset.js"></script>
</xpath>
</template>
</odoo>
@@ -0,0 +1,39 @@
<?xml version="1.0"?>
<odoo>
<record model="ir.ui.view" id="view_account_invoice_asset_form">
<field name="name">account.invoice.line.form</field>
<field name="model">account.invoice.line</field>
<field name="inherit_id" ref="account.view_invoice_line_form"/>
<field name="arch" type="xml">
<field name="account_id" position="after">
<field name="asset_category_id" domain="[('type','=','sale')]" string="Revenue Recognition Category"/>
</field>
</field>
</record>
<!-- Add "Asset Category" to supplier invoices -->
<record model="ir.ui.view" id="view_invoice_asset_category">
<field name="name">account.invoice.supplier.form</field>
<field name="model">account.invoice</field>
<field name="inherit_id" ref="account.invoice_supplier_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='invoice_line']/tree/field[@name='quantity']" position="before">
<field string="Asset Category" name="asset_category_id" domain="[('type','=','purchase')]" context="{'default_type':'purchase'}"/>
</xpath>
</field>
</record>
<!-- Add "Asset Category" to customer invoices -->
<record model="ir.ui.view" id="view_invoice_revenue_recognition_category">
<field name="name">account.invoice.form</field>
<field name="model">account.invoice</field>
<field name="inherit_id" ref="account.invoice_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='invoice_line']/tree/field[@name='quantity']" position="before">
<field string="Deferred Revenue Category" name="asset_category_id" domain="[('type','=','sale')]" context="{'default_type':'sale'}"/>
</xpath>
</field>
</record>
</odoo>
@@ -1,5 +1,4 @@
<openerp>
<data>
<odoo>
<!--
Asset Category
@@ -13,25 +12,39 @@
<group>
<group>
<field name="name"/>
<field name="type" attrs="{'invisible': 1}"/>
<field name="company_id" options="{'no_create': True}" groups="base.group_multi_company"/>
</group>
<group>
<field name="journal_id"/>
<field name="account_asset_id" on_change="onchange_account_asset(account_asset_id)"/>
<field name="account_depreciation_id"/>
<field name="account_expense_depreciation_id"/>
<div>
<label for="account_asset_id" string="Asset Account" attrs="{'invisible': [('type','!=','purchase')]}"/>
<label for="account_asset_id" string="Deferred Revenue Account" attrs="{'invisible': [('type','!=','sale')]}"/>
</div>
<field name="account_asset_id" nolabel="1" attrs="{'invisible': [('type','=', False)]}"/>
<div>
<label for="account_depreciation_id" string="Depreciation Account" attrs="{'invisible': [('type','!=','purchase')]}"/>
<label for="account_depreciation_id" string="Income Account" attrs="{'invisible': [('type','!=','sale')]}"/>
</div>
<field name="account_depreciation_id" nolabel="1"/>
</group>
<group string="Depreciation Dates">
<field name="method_time"/>
<field name="method_number" attrs="{'invisible':[('method_time','=','end')], 'required':[('method_time','=','number')]}"/>
<field name="method_period"/>
<field name="method_end" attrs="{'required': [('method_time','=','end')], 'invisible':[('method_time','=','number')]}"/>
<group>
<separator string="Periodicity" colspan="2"/>
<field name="method_time" string="Time Method Based On" widget="radio" attrs="{'invisible': [('type','!=','purchase')]}"/>
<field name="method_number" string="Number of Entries" attrs="{'invisible':['|',('method_time','!=','number'),'&amp;',('type','=', False)], 'required':[('method_time','=','number')]}"/>
<label for="method_period" string="Every"/>
<div>
<field name="method_period" nolabel="1" attrs="{'invisible': [('type','=', False)]}" class="oe_inline"/>
months
</div>
<field name="method_end" attrs="{'required': [('method_time','=','end')], 'invisible':[('method_time','!=','end')]}"/>
<field name="open_asset"/>
</group>
<group string="Depreciation Method">
<group attrs="{'invisible': [('type','=','sale')]}">
<separator string="Depreciation Method" colspan="2"/>
<field name="method" widget="radio"/>
<field name="method_progress_factor" attrs="{'invisible':[('method','=','linear')], 'required':[('method','=','degressive')]}"/>
<field name="prorata"/>
<field name="open_asset"/>
</group>
<group groups="analytic.group_analytic_accounting" string="Analytic Information">
<field name="account_analytic_id"/>
@@ -61,25 +74,28 @@
<field name="model">account.asset.category</field>
<field name="arch" type="xml">
<search string="Search Asset Category">
<field name="name" string="Asset Category"/>
<filter string="Sales" domain="[('type','=', 'sale')]" help="Deferred Revenues"/>
<filter string="Purchase" domain="[('type','=', 'purchase')]" help="Assets"/>
<field name="name" string="Category"/>
<field name="journal_id"/>
<group expand="0" string="Group By...">
<filter string="Type" domain="[]" context="{'group_by':'type'}"/>
</group>
</search>
</field>
</record>
<!--
Asset
-->
<record model="ir.ui.view" id="view_account_asset_asset_form">
<field name="name">account.asset.asset.form</field>
<field name="model">account.asset.asset</field>
<field name="arch" type="xml">
<form string="Asset">
<header>
<button name="validate" states="draft" string="Confirm Asset" type="object" class="oe_highlight"/>
<button name="validate" states="draft" string="Confirm" type="object" class="oe_highlight"/>
<button type="object" name="compute_depreciation_board" string="Compute Depreciation" states="draft"/>
<button name="set_to_close" states="open" string="Set to Close" type="object" class="oe_highlight"/>
<button name="set_to_draft" states="open" string="Set to Draft" type="object" />
<button name="%(action_asset_modify)d" states="open" string="Modify Depreciation" type="action"/>
<field name="state" widget="statusbar" statusbar_visible="draft,open"/>
</header>
<sheet>
@@ -96,64 +112,46 @@
</div>
<group>
<group>
<field name="category_id" on_change="onchange_category_id(category_id)"/>
<field name="category_id" domain="[('type', '=', default_category_id_type)]" context="{'default_type': default_category_id_type}" help="Category of asset"/>
<field name="code"/>
<field name="parent_id"/>
<field name="date" help="Date of asset"/>
<field name="type" invisible="1"/>
</group>
<group>
<field name="purchase_date"/>
<field name="currency_id" groups="base.group_multi_currency"/>
<field name="company_id" options="{'no_create': True}" groups="base.group_multi_company" on_change="onchange_company_id(company_id)"/>
<field name="company_id" options="{'no_create': True}" groups="base.group_multi_company"/>
<field name="value" widget="monetary" options="{'currency_field': 'currency_id'}" help="Gross value of asset"/>
<field name="salvage_value" widget="monetary" options="{'currency_field': 'currency_id'}"/>
<field name="value_residual" widget="monetary" options="{'currency_field': 'currency_id'}"/>
<field name="partner_id" string="Partner"/>
<field name="invoice_id" string="Invoice" domain="[('invoice_line.asset_category_id.type','=','purchase')]"/>
</group>
</group>
<notebook colspan="4">
<page string="General">
<group>
<group>
<field name="purchase_value" widget="monetary" options="{'currency_field': 'currency_id'}" on_change="onchange_purchase_salvage_value(purchase_value, salvage_value)"/>
<field name="salvage_value" widget="monetary" options="{'currency_field': 'currency_id'}" on_change="onchange_purchase_salvage_value(purchase_value, salvage_value)"/>
<field name="value_residual" widget="monetary" options="{'currency_field': 'currency_id'}"/>
<field name="partner_id"/>
</group>
<group>
<field name="method" widget="radio"/>
<field name="method_progress_factor" attrs="{'invisible':[('method','=','linear')], 'required':[('method','=','degressive')]}"/>
<label for="method_time"/>
<div>
<field name="method_time" on_change="onchange_method_time(method_time)" class="oe_inline"/>
<button name="%(action_asset_modify)d" states="open" string="Change Duration" type="action" icon="terp-stock_effects-object-colorize" class="oe_inline" colspan="1"/>
</div>
<field name="prorata" attrs="{'invisible': [('method_time','=','end')]}"/>
<field name="method_number" attrs="{'invisible':[('method_time','=','end')], 'required':[('method_time','=','number')]}"/>
<field name="method_period"/>
<field name="method_end" attrs="{'required': [('method_time','=','end')], 'invisible':[('method_time','=','number')]}"/>
</group>
</group>
</page>
<page string="Depreciation Board">
<field name="depreciation_line_ids" mode="tree">
<tree string="Depreciation Lines" colors="blue:(move_check == False);black:(move_check == True)">
<field name="depreciation_line_ids" mode="tree" options="{'reload_whole_on_button': true}">
<tree string="Depreciation Lines" colors="blue:(move_check == False);black:(move_check == True)" create="false">
<field name="sequence" string="Serial Number"/>
<field name="depreciation_date"/>
<field name="sequence" invisible="1"/>
<field name="depreciated_value" readonly="1"/>
<field name="amount"/>
<field name="remaining_value" readonly="1"/>
<field name="move_check"/>
<field name="move_check" invisible="1"/>
<field name="parent_state" invisible="1"/>
<button name="create_move" attrs="{'invisible':['|',('move_check','!=',False),('parent_state','!=','open')]}" icon="gtk-execute" string="Create Move" type="object"/>
<button name="create_move" type="object" widget="widgetonbutton"/>
</tree>
<form string="Depreciation Lines">
<group>
<group>
<field name="parent_state" invisible="1"/>
<field name="name"/>
<field name="amount"/>
<field name="sequence"/>
<field name="move_id"/>
<field name="move_check"/>
<field name="parent_state" invisible="1"/>
</group>
<group>
<field name="sequence"/>
<field name="amount"/>
<field name="depreciation_date"/>
<field name="depreciated_value"/>
<field name="remaining_value"/>
@@ -161,17 +159,33 @@
</group>
</form>
</field>
<button type="object" name="compute_depreciation_board" string="Compute" icon="terp-stock_format-scientific" colspan="2" attrs="{'invisible':[('state','=','close')]}"/>
</page>
<page string="History">
<field name="account_move_line_ids" readonly="1"/>
<field name="history_ids" readonly="1"/>
</page>
<page string="Notes">
<field name="note" placeholder="Add an internal note here..."/>
</page>
</notebook>
<separator string="Depreciation Information" colspan="4"/>
<group>
<group>
<field name="method" widget="radio" attrs="{'invisible': [('type','=','sale')]}"/>
<field name="method_progress_factor" attrs="{'invisible':[('method','=','linear')], 'required':[('method','=','degressive')]}"/>
<label for="method_time"/>
<div>
<field name="method_time"/>
</div>
<field name="prorata" attrs="{'invisible': [('method_time','=','end')]}"/>
</group>
<group>
<field name="method_number" attrs="{'invisible':[('method_time','=','end')], 'required':[('method_time','=','number')]}"/>
<field name="method_period"/>
<field name="method_end" attrs="{'required': [('method_time','=','end')], 'invisible':[('method_time','=','number')]}"/>
</group>
</group>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/>
<field name="message_ids" widget="mail_thread"/>
</div>
</form>
</field>
</record>
@@ -179,33 +193,13 @@
<record model="ir.ui.view" id="view_account_asset_asset_tree">
<field name="name">account.asset.asset.tree</field>
<field name="model">account.asset.asset</field>
<field name="field_parent">child_ids</field>
<field name="arch" type="xml">
<tree string="Assets" colors="blue:(state == 'draft');grey:(state == 'close')">
<field name="name"/>
<field name="category_id"/>
<field name="purchase_date"/>
<field name="date"/>
<field name="partner_id"/>
<field name="purchase_value"/>
<field name="value_residual"/>
<field name="currency_id" groups="base.group_multi_currency"/>
<field name="company_id" groups="base.group_multi_company"/>
<field name="state"/>
</tree>
</field>
</record>
<record model="ir.ui.view" id="view_account_asset_asset_hierarchy_tree">
<field name="name">account.asset.asset.hierarchy</field>
<field name="model">account.asset.asset</field>
<field name="field_parent">child_ids</field>
<field name="arch" type="xml">
<tree string="Assets">
<field name="name"/>
<field name="code"/>
<field name="category_id"/>
<field name="purchase_date"/>
<field name="purchase_value"/>
<field name="value"/>
<field name="value_residual"/>
<field name="currency_id" groups="base.group_multi_currency"/>
<field name="company_id" groups="base.group_multi_company"/>
@@ -220,15 +214,34 @@
<field name="arch" type="xml">
<search string="Account Asset">
<field name="name" string="Asset"/>
<field name="purchase_date"/>
<filter icon="terp-check" string="Current" domain="[('state','in', ('draft','open'))]" help="Assets in draft and open states"/>
<filter icon="terp-dialog-close" string="Closed" domain="[('state','=', 'close')]" help="Assets in closed state"/>
<field name="date"/>
<filter string="Current" domain="[('state','in', ('draft','open'))]" help="Assets in draft and open states"/>
<filter string="Closed" domain="[('state','=', 'close')]" help="Assets in closed state"/>
<field name="category_id"/>
<field name="partner_id" filter_domain="[('partner_id','child_of',self)]"/>
<group expand="0" string="Group By...">
<filter string="Month" domain="[]" context="{'group_by':'date'}"/>
<filter string="Category" domain="[]" context="{'group_by':'category_id'}"/>
</group>
</search>
</field>
</record>
<!-- Product Template -->
<record id="view_product_template_form_inherit" model="ir.ui.view">
<field name="name">Product Template (form)</field>
<field name="model">product.template</field>
<field name="inherit_id" ref="product.product_template_form_view"/>
<field name="arch" type="xml">
<xpath expr="//group[@name='properties']" position="before">
<group name="asset types">
<field name="asset_category_id" domain="[('type','=','purchase')]" context="{'default_type':'purchase'}"/>
<field name="deferred_revenue_category_id" domain="[('type','=','sale')]" context="{'default_type':'sale'}"/>
</group>
</xpath>
</field>
</record>
<!--
Asset History
-->
@@ -272,15 +285,7 @@
</tree>
</field>
</record>
<record model="ir.actions.act_window" id="action_account_asset_asset_tree">
<field name="name">Asset Hierarchy</field>
<field name="res_model">account.asset.asset</field>
<field name="view_type">tree</field>
<field name="domain">[('parent_id','=',False)]</field>
<field name="view_id" ref="view_account_asset_asset_hierarchy_tree"/>
</record>
<record id="view_account_move_line_form_inherit" model="ir.ui.view">
<field name="name">Journal Items (form)</field>
<field name="model">account.move.line</field>
@@ -303,32 +308,52 @@
</field>
</record>
<menuitem id="menu_finance_assets" name="Assets" parent="account.menu_finance" sequence="7" groups="account.group_account_user"/>
<menuitem parent="menu_finance_assets" id="menu_action_account_asset_asset_tree"
sequence="100"
action="action_account_asset_asset_tree"/>
<menuitem id="menu_finance_assets" name="Assets and Revenues" parent="account.menu_finance" sequence="9" groups="account.group_account_user"/>
<record model="ir.actions.act_window" id="action_account_asset_asset_form">
<field name="name">Assets</field>
<field name="res_model">account.asset.asset</field>
<field name="view_type">form</field>
<field name="view_id" ref="view_account_asset_asset_tree"/>
<field name="search_view_id" ref="view_account_asset_search"/>
<field name="domain">[('category_id.type', '=', 'purchase')]</field>
<field name="context">{'default_type': 'purchase', 'default_category_id_type': 'purchase'}</field>
</record>
<menuitem parent="menu_finance_assets" id="menu_action_account_asset_asset_form" action="action_account_asset_asset_form"/>
<!-- Deferred Revenues Action -->
<act_window id="act_entries_open" name="Entries" res_model="account.move.line" src_model="account.asset.asset" context="{'search_default_asset_id': [active_id], 'default_asset_id': active_id}"/>
<record model="ir.actions.act_window" id="action_account_revenue_form">
<field name="name">Deferred Revenues</field>
<field name="res_model">account.asset.asset</field>
<field name="view_type">form</field>
<field name="domain">[('category_id.type', '=', 'sale')]</field>
<field name="context">{'default_type': 'sale', 'default_category_id_type': 'sale'}</field>
</record>
<menuitem id="menu_finance_config_assets" name="Assets" parent="account.menu_finance_configuration" sequence="7"/>
<record model="ir.actions.act_window" id="action_account_asset_asset_list_normal">
<field name="name">Asset Categories</field>
<menuitem parent="menu_finance_assets" id="menu_revenue_recognition" action="action_account_revenue_form" sequence="102"/>
<menuitem parent="menu_finance_assets" id="menu_action_account_asset_asset_form" action="action_account_asset_asset_form" sequence="104"/>
<!-- Configuration -->
<menuitem id="menu_finance_config_assets" name="Assets and Revenues" parent="account.menu_finance_configuration" sequence="25"/>
<record model="ir.actions.act_window" id="action_account_asset_asset_list_normal_sale">
<field name="name">Asset Types</field>
<field name="res_model">account.asset.category</field>
<field name="domain">[('type', '=', 'purchase')]</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="context">{'default_type': 'purchase'}</field>
</record>
<record model="ir.actions.act_window" id="action_account_asset_asset_list_normal_purchase">
<field name="name">Deferred Revenues Types</field>
<field name="res_model">account.asset.category</field>
<field name="domain">[('type', '=', 'sale')]</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="context">{'default_type': 'sale'}</field>
</record>
<menuitem parent="menu_finance_config_assets" id="menu_action_account_asset_asset_list_normal" action="action_account_asset_asset_list_normal"/>
<menuitem parent="menu_finance_config_assets" id="menu_action_account_asset_asset_list_normal_sale" action="action_account_asset_asset_list_normal_sale" sequence="1"/>
<menuitem parent="menu_finance_config_assets" id="menu_action_account_asset_asset_list_normal_purchase" action="action_account_asset_asset_list_normal_purchase" sequence="2"/>
</data>
</openerp>
</odoo>
+1 -20
View File
@@ -1,23 +1,4 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
# -*- coding: utf-8 -*-
import account_asset_change_duration
import wizard_asset_compute
@@ -1,63 +1,51 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import time
# -*- coding: utf-8 -*-
from lxml import etree
from openerp.osv import fields, osv
from openerp import api, fields, models
from openerp.osv.orm import setup_modifiers
class asset_modify(osv.osv_memory):
class AssetModify(models.TransientModel):
_name = 'asset.modify'
_description = 'Modify Asset'
def _get_asset_method_time(self, cr, uid, ids, field_name, arg, context=None):
if ids and len(ids) == 1 and context.get('active_id'):
asset = self.pool['account.asset.asset'].browse(cr, uid, context.get('active_id'), context=context)
return {ids[0]: asset.method_time}
else:
return dict.fromkeys(ids, False)
name = fields.Char(string='Reason', required=True)
method_number = fields.Integer(string='Number of Depreciations', required=True)
method_period = fields.Integer(string='Period Length')
method_end = fields.Date(string='Ending date')
note = fields.Text(string='Notes')
asset_method_time = fields.Char(compute='_get_asset_method_time', string='Asset Method Time', readonly=True)
_columns = {
'name': fields.char('Reason', required=True),
'method_number': fields.integer('Number of Depreciations', required=True),
'method_period': fields.integer('Period Length'),
'method_end': fields.date('Ending date'),
'note': fields.text('Notes'),
'asset_method_time': fields.function(_get_asset_method_time, type='char', string='Asset Method Time', readonly=True),
}
@api.one
def _get_asset_method_time(self):
if self.env.context.get('active_id'):
asset = self.env['account.asset.asset'].browse(self.env.context.get('active_id'))
self.asset_method_time = asset.method_time
def default_get(self, cr, uid, fields, context=None):
""" To get default values for the object.
@param self: The object pointer.
@param cr: A database cursor
@param uid: ID of the user currently logged in
@param fields: List of fields for which we want default values
@param context: A standard dictionary
@return: A dictionary which of fields with values.
"""
if not context:
context = {}
asset_obj = self.pool.get('account.asset.asset')
res = super(asset_modify, self).default_get(cr, uid, fields, context=context)
asset_id = context.get('active_id', False)
asset = asset_obj.browse(cr, uid, asset_id, context=context)
@api.model
def fields_view_get(self, view_id=None, view_type='form', toolbar=False, submenu=False):
result = super(AssetModify, self).fields_view_get(view_id, view_type, toolbar=toolbar, submenu=submenu)
asset_id = self.env.context.get('active_id')
active_model = self.env.context.get('active_model')
if active_model == 'account.asset.asset' and asset_id:
asset = self.env['account.asset.asset'].browse(asset_id)
doc = etree.XML(result['arch'])
if asset.method_time == 'number' and doc.xpath("//field[@name='method_end']"):
node = doc.xpath("//field[@name='method_end']")[0]
node.set('invisible', '1')
setup_modifiers(node, result['fields']['method_end'])
elif asset.method_time == 'end' and doc.xpath("//field[@name='method_number']"):
node = doc.xpath("//field[@name='method_number']")[0]
node.set('invisible', '1')
setup_modifiers(node, result['fields']['method_number'])
result['arch'] = etree.tostring(doc)
return result
@api.model
def default_get(self, fields):
res = super(AssetModify, self).default_get(fields)
asset_id = self.env.context.get('active_id')
asset = self.env['account.asset.asset'].browse(asset_id)
if 'name' in fields:
res.update({'name': asset.name})
if 'method_number' in fields and asset.method_time == 'number':
@@ -66,44 +54,34 @@ class asset_modify(osv.osv_memory):
res.update({'method_period': asset.method_period})
if 'method_end' in fields and asset.method_time == 'end':
res.update({'method_end': asset.method_end})
if context.get('active_id'):
res['asset_method_time'] = self._get_asset_method_time(cr, uid, [0], 'asset_method_time', [], context=context)[0]
if self.env.context.get('active_id'):
res['asset_method_time'] = self._get_asset_method_time()
return res
def modify(self, cr, uid, ids, context=None):
@api.multi
def modify(self):
""" Modifies the duration of asset for calculating depreciation
and maintains the history of old values.
@param self: The object pointer.
@param cr: A database cursor
@param uid: ID of the user currently logged in
@param ids: List of Ids
@param context: A standard dictionary
@return: Close the wizard.
"""
if not context:
context = {}
asset_obj = self.pool.get('account.asset.asset')
history_obj = self.pool.get('account.asset.history')
asset_id = context.get('active_id', False)
asset = asset_obj.browse(cr, uid, asset_id, context=context)
data = self.browse(cr, uid, ids[0], context=context)
"""
asset_id = self.env.context.get('active_id', False)
asset = self.env['account.asset.asset'].browse(asset_id)
history_vals = {
'asset_id': asset_id,
'name': data.name,
'name': self.name,
'method_time': asset.method_time,
'method_number': asset.method_number,
'method_period': asset.method_period,
'method_end': asset.method_end,
'user_id': uid,
'date': time.strftime('%Y-%m-%d'),
'note': data.note,
'user_id': self.env.uid,
'date': fields.Date.context_today(self),
'note': self.note,
}
history_obj.create(cr, uid, history_vals, context=context)
self.env['account.asset.history'].create(history_vals)
asset_vals = {
'method_number': data.method_number,
'method_period': data.method_period,
'method_end': data.method_end,
'method_number': self.method_number,
'method_period': self.method_period,
'method_end': self.method_end,
}
asset_obj.write(cr, uid, [asset_id], asset_vals, context=context)
asset_obj.compute_depreciation_board(cr, uid, [asset_id], context=context)
asset.write(asset_vals)
asset.compute_depreciation_board()
return {'type': 'ir.actions.act_window_close'}
@@ -1,46 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<odoo>
<record model="ir.ui.view" id="asset_modify_form">
<field name="name">wizard.asset.modify.form</field>
<field name="model">asset.modify</field>
<field name="arch" type="xml">
<form string="Modify Asset">
<field name="asset_method_time" invisible="1"/>
<group string="Asset Durations to Modify" col="4">
<group colspan="2" col="2">
<field name="name"/>
<field name="method_number" attrs="{'invisible': [('asset_method_time', '=', 'end')]}"/>
</group>
<group colspan="2" col="2">
<field name="method_end" attrs="{'invisible': [('asset_method_time', '=', 'number')]}"/>
<label for="method_period"/>
<div>
<field name="method_period" class="oe_inline"/> months
</div>
</group>
<record model="ir.ui.view" id="asset_modify_form">
<field name="name">wizard.asset.modify.form</field>
<field name="model">asset.modify</field>
<field name="arch" type="xml">
<form string="Modify Asset">
<field name="asset_method_time" invisible="1"/>
<group string="Asset Durations to Modify" col="4">
<group colspan="2" col="2">
<field name="name"/>
<field name="method_number" attrs="{'invisible': [('asset_method_time', '=', 'end')]}"/>
</group>
<separator string="Notes"/>
<field name="note"/>
<footer>
<button name="modify" string="Modify" type="object" class="oe_highlight"/>
or
<button string="Cancel" class="oe_link" special="cancel"/>
</footer>
</form>
</field>
</record>
<record id="action_asset_modify" model="ir.actions.act_window">
<field name="name">Modify Asset</field>
<field name="res_model">asset.modify</field>
<field name="type">ir.actions.act_window</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="view_id" ref="asset_modify_form"/>
<field name="target">new</field>
</record>
<group colspan="2" col="2">
<field name="method_end" attrs="{'invisible': [('asset_method_time', '=', 'number')]}"/>
<label for="method_period"/>
<div>
<field name="method_period" class="oe_inline"/> months
</div>
</group>
</group>
<separator string="Notes"/>
<field name="note"/>
<footer>
<button name="modify" string="Modify" type="object" class="oe_highlight"/>
or
<button string="Cancel" class="oe_link" special="cancel"/>
</footer>
</form>
</field>
</record>
</data>
</openerp>
<record id="action_asset_modify" model="ir.actions.act_window">
<field name="name">Modify Asset</field>
<field name="res_model">asset.modify</field>
<field name="type">ir.actions.act_window</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="view_id" ref="asset_modify_form"/>
<field name="target">new</field>
</record>
</odoo>
@@ -1,56 +1,37 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
# -*- coding: utf-8 -*-
from openerp import api, fields, models, _
from openerp.osv import fields, osv
from openerp.tools.translate import _
class asset_depreciation_confirmation_wizard(osv.osv_memory):
class AssetDepreciationConfirmationWizard(models.TransientModel):
_name = "asset.depreciation.confirmation.wizard"
_description = "asset.depreciation.confirmation.wizard"
_columns = {
'period_id': fields.many2one('account.period', 'Period', required=True, help="Choose the period for which you want to automatically post the depreciation lines of running assets"),
}
def _get_period(self, cr, uid, context=None):
periods = self.pool.get('account.period').find(cr, uid, context=context)
period_id = fields.Many2one('account.period', string='Period', default='_get_period', required=True,
help="Choose the period for which you want to automatically post the depreciation lines of running assets")
def _get_period(self):
periods = self.env['account.period'].find()
if periods:
return periods[0]
return False
_defaults = {
'period_id': _get_period,
}
else:
raise UserError(_('You do not have any period. Please configure them.'))
def asset_compute(self, cr, uid, ids, context):
ass_obj = self.pool.get('account.asset.asset')
asset_ids = ass_obj.search(cr, uid, [('state','=','open')], context=context)
data = self.browse(cr, uid, ids, context=context)
period_id = data[0].period_id.id
created_move_ids = ass_obj._compute_entries(cr, uid, asset_ids, period_id, context=context)
@api.multi
def asset_compute(self):
self.ensure_one()
context = self._context
assets = self.env['account.asset.asset'].search([('state', '=', 'open'), ('category_id.type', '=', context.get('asset_type'))])
created_move_ids = assets._compute_entries(self.period_id.id)
if context.get('asset_type') == 'purchase':
title = _('Created Asset Moves')
else:
title = _('Created Revenue Moves')
return {
'name': _('Created Asset Moves'),
'name': title,
'view_type': 'form',
'view_mode': 'tree,form',
'res_model': 'account.move',
'view_id': False,
'domain': "[('id','in',["+','.join(map(str,created_move_ids))+"])]",
'domain': "[('id','in',["+','.join(map(str, created_move_ids))+"])]",
'type': 'ir.actions.act_window',
}
@@ -1,35 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="view_asset_depreciation_confirmation_wizard" model="ir.ui.view">
<field name="name">asset.depreciation.confirmation.wizard</field>
<field name="model">asset.depreciation.confirmation.wizard</field>
<field name="arch" type="xml">
<form string="Compute Asset">
<group>
<field name="period_id"/>
</group>
<footer>
<button string="Compute" name="asset_compute" type="object" class="oe_highlight"/>
or
<button string="Cancel" class="oe_link" special="cancel"/>
</footer>
</form>
</field>
</record>
<odoo>
<record id="view_asset_depreciation_confirmation_wizard" model="ir.ui.view">
<field name="name">asset.depreciation.confirmation.wizard</field>
<field name="model">asset.depreciation.confirmation.wizard</field>
<field name="arch" type="xml">
<form string="Compute Asset">
<div>
<p>
This wizard will post installment/depreciation lines for the selected month.<br/>
This will generate journal entries for all related installment lines on this period of asset/revenue recognition as well.
</p>
</div>
<group>
<field name="period_id"/>
</group>
<footer>
<button string="Generate Entries" name="asset_compute" type="object" class="oe_highlight"/>
or
<button string="Cancel" class="oe_link" special="cancel"/>
</footer>
</form>
</field>
</record>
<record id="action_asset_depreciation_confirmation_wizard" model="ir.actions.act_window">
<field name="name">Compute Assets</field>
<field name="res_model">asset.depreciation.confirmation.wizard</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="view_id" ref="view_asset_depreciation_confirmation_wizard"/>
<field name="target">new</field>
</record>
<record id="action_asset_depreciation_confirmation_wizard" model="ir.actions.act_window">
<field name="name">Post Depreciation Lines</field>
<field name="res_model">asset.depreciation.confirmation.wizard</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="view_id" ref="view_asset_depreciation_confirmation_wizard"/>
<field name="target">new</field>
<field name="context">{'asset_type': 'purchase'}</field>
</record>
<menuitem action="action_asset_depreciation_confirmation_wizard"
id="menu_asset_depreciation_confirmation_wizard"
parent="account.periodical_processing_journal_entries_validation" />
<record id="action_recognition_depreciation_confirmation_wizard" model="ir.actions.act_window">
<field name="name">Post Installment Lines</field>
<field name="res_model">asset.depreciation.confirmation.wizard</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="view_id" ref="view_asset_depreciation_confirmation_wizard"/>
<field name="target">new</field>
<field name="context">{'asset_type': 'sale'}</field>
</record>
</data>
</openerp>
<menuitem name="Deferred Revenue Entries" action="action_recognition_depreciation_confirmation_wizard"
id="menu_recognition_depreciation_confirmation_wizard"
parent="account.periodical_processing_journal_entries_validation" sequence="2"/>
<menuitem name="Assets Entries" action="action_asset_depreciation_confirmation_wizard"
id="menu_asset_depreciation_confirmation_wizard"
parent="account.periodical_processing_journal_entries_validation" sequence="1"/>
</odoo>