2
0
account-financial-tools/account_asset_management/models/account_move.py
Bejaoui Souheil 8fa0de5226 Finish 12.0 migration of account_asset_management
* account_asset: Do not loop on all the lines to search for one linked asset

Before this change, the use of `mapped` on self did loop on all the move
lines that are included in self to get the assets, what could be very
costly for a simple write on a lot of move lines. As the goal is to raise
an error only if at least one move is linked to an asset, we break the
loop if the condition is fulfilled.

* performance improvement

* [RMV] - Remove useless dependency

In 12.0 account_fiscal_year is a standard feature no need to depend on oca
module account_fiscal_year
2022-12-24 00:42:21 +01:00

170 lines
6.6 KiB
Python

# Copyright 2009-2018 Noviat
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import logging
from odoo import api, fields, models, _
from odoo.exceptions import UserError
_logger = logging.getLogger(__name__)
# List of move's fields that can't be modified if move is linked
# with a depreciation line
FIELDS_AFFECTS_ASSET_MOVE = set(['journal_id', 'date'])
# List of move line's fields that can't be modified if move is linked
# with a depreciation line
FIELDS_AFFECTS_ASSET_MOVE_LINE = \
set(['credit', 'debit', 'account_id', 'journal_id', 'date',
'asset_profile_id', 'asset_id'])
class AccountMove(models.Model):
_inherit = 'account.move'
@api.multi
def unlink(self):
# for move in self:
deprs = self.env['account.asset.line'].search(
[('move_id', 'in', self.ids),
('type', 'in', ['depreciate', 'remove'])])
if deprs and not self.env.context.get('unlink_from_asset'):
raise UserError(
_("You are not allowed to remove an accounting entry "
"linked to an asset."
"\nYou should remove such entries from the asset."))
# trigger store function
deprs.write({'move_id': False})
return super().unlink()
@api.multi
def write(self, vals):
if set(vals).intersection(FIELDS_AFFECTS_ASSET_MOVE):
deprs = self.env['account.asset.line'].search(
[('move_id', 'in', self.ids), ('type', '=', 'depreciate')])
if deprs:
raise UserError(
_("You cannot change an accounting entry "
"linked to an asset depreciation line."))
return super().write(vals)
class AccountMoveLine(models.Model):
_inherit = 'account.move.line'
asset_profile_id = fields.Many2one(
comodel_name='account.asset.profile',
string='Asset Profile')
asset_id = fields.Many2one(
comodel_name='account.asset',
string='Asset', ondelete='restrict')
@api.onchange('account_id')
def _onchange_account_id(self):
self.asset_profile_id = self.account_id.asset_profile_id
@api.model
def create(self, vals):
if vals.get('asset_id') and not self.env.context.get('allow_asset'):
raise UserError(
_("You are not allowed to link "
"an accounting entry to an asset."
"\nYou should generate such entries from the asset."))
if vals.get('asset_profile_id'):
# create asset
asset_obj = self.env['account.asset']
move = self.env['account.move'].browse(vals['move_id'])
depreciation_base = vals['debit'] or -vals['credit']
temp_vals = {
'name': vals['name'],
'profile_id': vals['asset_profile_id'],
'purchase_value': depreciation_base,
'partner_id': vals['partner_id'],
'date_start': move.date,
}
if self.env.context.get('company_id'):
temp_vals['company_id'] = self.env.context['company_id']
temp_asset = asset_obj.new(temp_vals)
temp_asset._onchange_profile_id()
asset_vals = temp_asset._convert_to_write(temp_asset._cache)
self._get_asset_analytic_values(vals, asset_vals)
asset = asset_obj.with_context(
create_asset_from_move_line=True,
move_id=vals['move_id']).create(asset_vals)
vals['asset_id'] = asset.id
return super().create(vals)
@api.multi
def _prepare_asset_create(self, vals):
self.ensure_one()
debit = 'debit' in vals and vals.get('debit', 0.0) or self.debit
credit = 'credit' in vals and \
vals.get('credit', 0.0) or self.credit
depreciation_base = debit - credit
partner_id = 'partner' in vals and \
vals.get('partner', False) or self.partner_id.id
date_start = 'date' in vals and \
vals.get('date', False) or self.date
return {
'name': vals.get('name') or self.name,
'profile_id': vals['asset_profile_id'],
'purchase_value': depreciation_base,
'partner_id': partner_id,
'date_start': date_start,
'company_id': vals.get('company_id') or self.company_id.id,
}
@api.multi
def write(self, vals):
if (
set(vals).intersection(FIELDS_AFFECTS_ASSET_MOVE_LINE) and
not (
self.env.context.get('allow_asset_removal') and
list(vals.keys()) == ['asset_id'])
):
# Check if at least one asset is linked to a move
linked_asset = False
for move in self:
linked_asset = move.asset_id
if linked_asset:
raise UserError(
_("You cannot change an accounting item "
"linked to an asset depreciation line."))
if vals.get('asset_id'):
raise UserError(
_("You are not allowed to link "
"an accounting entry to an asset."
"\nYou should generate such entries from the asset."))
if vals.get('asset_profile_id'):
if len(self) == 1:
raise AssertionError(_(
'This option should only be used for a single id at a '
'time.'))
asset_obj = self.env['account.asset']
for aml in self:
if vals['asset_profile_id'] == aml.asset_profile_id.id:
continue
# create asset
asset_vals = aml._prepare_asset_create(vals)
self._play_onchange_profile_id(asset_vals)
self._get_asset_analytic_values(vals, asset_vals)
asset = asset_obj.with_context(
create_asset_from_move_line=True,
move_id=aml.move_id.id).create(asset_vals)
vals['asset_id'] = asset.id
return super().write(vals)
@api.model
def _get_asset_analytic_values(self, vals, asset_vals):
asset_vals['account_analytic_id'] = vals.get(
'analytic_account_id', False)
@api.model
def _play_onchange_profile_id(self, vals):
asset_obj = self.env['account.asset']
asset_temp = asset_obj.new(vals)
asset_temp._onchange_profile_id()
for field in asset_temp._fields:
if field not in vals and asset_temp[field]:
vals[field] = asset_temp._fields[field].\
convert_to_write(asset_temp[field], asset_temp)