Initial commit
This commit is contained in:
650
Fusion Accounting/wizard/asset_modify.py
Normal file
650
Fusion Accounting/wizard/asset_modify.py
Normal file
@@ -0,0 +1,650 @@
|
||||
# Fusion Accounting - Asset Modification Wizard
|
||||
# Enables users to modify, dispose, sell, pause, or resume
|
||||
# fixed assets with full depreciation board recalculation.
|
||||
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
from odoo import api, fields, models, _, Command
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.tools import float_is_zero
|
||||
from odoo.tools.misc import format_date
|
||||
|
||||
|
||||
class AssetModify(models.TransientModel):
|
||||
"""Wizard for modifying running assets, including value changes,
|
||||
depreciation parameter adjustments, disposal, and sales."""
|
||||
|
||||
_name = 'asset.modify'
|
||||
_description = 'Modify Asset'
|
||||
|
||||
# --- Core Fields ---
|
||||
name = fields.Text(string='Note')
|
||||
asset_id = fields.Many2one(
|
||||
string="Asset",
|
||||
comodel_name='account.asset',
|
||||
required=True,
|
||||
help="The target asset to modify.",
|
||||
ondelete="cascade",
|
||||
)
|
||||
currency_id = fields.Many2one(
|
||||
related='asset_id.currency_id',
|
||||
)
|
||||
company_id = fields.Many2one(
|
||||
comodel_name='res.company',
|
||||
related='asset_id.company_id',
|
||||
)
|
||||
date = fields.Date(
|
||||
default=lambda self: fields.Date.today(),
|
||||
string='Date',
|
||||
)
|
||||
|
||||
# --- Depreciation Parameters ---
|
||||
method_number = fields.Integer(
|
||||
string='Duration',
|
||||
required=True,
|
||||
)
|
||||
method_period = fields.Selection(
|
||||
selection=[('1', 'Months'), ('12', 'Years')],
|
||||
string='Number of Months in a Period',
|
||||
help="Interval between successive depreciation entries.",
|
||||
)
|
||||
value_residual = fields.Monetary(
|
||||
string="Depreciable Amount",
|
||||
help="Updated depreciable amount for the asset.",
|
||||
compute="_compute_value_residual",
|
||||
store=True,
|
||||
readonly=False,
|
||||
)
|
||||
salvage_value = fields.Monetary(
|
||||
string="Not Depreciable Amount",
|
||||
help="Updated non-depreciable (salvage) amount.",
|
||||
)
|
||||
|
||||
# --- Action Selection ---
|
||||
modify_action = fields.Selection(
|
||||
selection="_get_selection_modify_options",
|
||||
string="Action",
|
||||
)
|
||||
|
||||
# --- Gross Increase Accounts ---
|
||||
account_asset_id = fields.Many2one(
|
||||
comodel_name='account.account',
|
||||
string="Gross Increase Account",
|
||||
check_company=True,
|
||||
domain="[]",
|
||||
)
|
||||
account_asset_counterpart_id = fields.Many2one(
|
||||
comodel_name='account.account',
|
||||
check_company=True,
|
||||
domain="[]",
|
||||
string="Asset Counterpart Account",
|
||||
)
|
||||
account_depreciation_id = fields.Many2one(
|
||||
comodel_name='account.account',
|
||||
check_company=True,
|
||||
domain="[]",
|
||||
string="Depreciation Account",
|
||||
)
|
||||
account_depreciation_expense_id = fields.Many2one(
|
||||
comodel_name='account.account',
|
||||
check_company=True,
|
||||
domain="[]",
|
||||
string="Expense Account",
|
||||
)
|
||||
|
||||
# --- Sale / Disposal Fields ---
|
||||
invoice_ids = fields.Many2many(
|
||||
comodel_name='account.move',
|
||||
string="Customer Invoice",
|
||||
check_company=True,
|
||||
domain="[('move_type', '=', 'out_invoice'), ('state', '=', 'posted')]",
|
||||
help="Invoice(s) linked to this disposal or sale.",
|
||||
)
|
||||
invoice_line_ids = fields.Many2many(
|
||||
comodel_name='account.move.line',
|
||||
check_company=True,
|
||||
domain="[('move_id', '=', invoice_id), ('display_type', '=', 'product')]",
|
||||
help="Specific invoice line(s) related to this asset.",
|
||||
)
|
||||
select_invoice_line_id = fields.Boolean(
|
||||
compute="_compute_select_invoice_line_id",
|
||||
)
|
||||
gain_value = fields.Boolean(
|
||||
compute="_compute_gain_value",
|
||||
)
|
||||
|
||||
# --- Gain/Loss Accounts ---
|
||||
gain_account_id = fields.Many2one(
|
||||
comodel_name='account.account',
|
||||
check_company=True,
|
||||
domain="[]",
|
||||
compute="_compute_accounts",
|
||||
inverse="_inverse_gain_account",
|
||||
readonly=False,
|
||||
compute_sudo=True,
|
||||
help="Account for recording gains on asset disposal.",
|
||||
)
|
||||
loss_account_id = fields.Many2one(
|
||||
comodel_name='account.account',
|
||||
check_company=True,
|
||||
domain="[]",
|
||||
compute="_compute_accounts",
|
||||
inverse="_inverse_loss_account",
|
||||
readonly=False,
|
||||
compute_sudo=True,
|
||||
help="Account for recording losses on asset disposal.",
|
||||
)
|
||||
|
||||
# --- Informational ---
|
||||
informational_text = fields.Html(
|
||||
compute='_compute_informational_text',
|
||||
)
|
||||
gain_or_loss = fields.Selection(
|
||||
selection=[('gain', 'Gain'), ('loss', 'Loss'), ('no', 'No')],
|
||||
compute='_compute_gain_or_loss',
|
||||
)
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Selection Helpers
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
def _compute_modify_action(self):
|
||||
"""Determine the default action based on context."""
|
||||
if self.env.context.get('resume_after_pause'):
|
||||
return 'resume'
|
||||
return 'dispose'
|
||||
|
||||
@api.depends('asset_id')
|
||||
def _get_selection_modify_options(self):
|
||||
"""Return available modification actions."""
|
||||
if self.env.context.get('resume_after_pause'):
|
||||
return [('resume', _('Resume'))]
|
||||
return [
|
||||
('dispose', _("Dispose")),
|
||||
('sell', _("Sell")),
|
||||
('modify', _("Re-evaluate")),
|
||||
('pause', _("Pause")),
|
||||
]
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Compute Methods
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
@api.depends('company_id')
|
||||
def _compute_accounts(self):
|
||||
for rec in self:
|
||||
rec.gain_account_id = rec.company_id.gain_account_id
|
||||
rec.loss_account_id = rec.company_id.loss_account_id
|
||||
|
||||
@api.depends('date')
|
||||
def _compute_value_residual(self):
|
||||
for rec in self:
|
||||
rec.value_residual = rec.asset_id._get_residual_value_at_date(rec.date)
|
||||
|
||||
def _inverse_gain_account(self):
|
||||
for rec in self:
|
||||
rec.company_id.sudo().gain_account_id = rec.gain_account_id
|
||||
|
||||
def _inverse_loss_account(self):
|
||||
for rec in self:
|
||||
rec.company_id.sudo().loss_account_id = rec.loss_account_id
|
||||
|
||||
@api.depends('asset_id', 'invoice_ids', 'invoice_line_ids', 'modify_action', 'date')
|
||||
def _compute_gain_or_loss(self):
|
||||
"""Determine whether disposing/selling results in a gain or loss."""
|
||||
for rec in self:
|
||||
invoice_total = abs(sum(
|
||||
ln.balance for ln in rec.invoice_line_ids
|
||||
))
|
||||
book_val = rec.asset_id._get_own_book_value(rec.date)
|
||||
cmp_result = rec.company_id.currency_id.compare_amounts(
|
||||
book_val, invoice_total,
|
||||
)
|
||||
if rec.modify_action in ('sell', 'dispose') and cmp_result < 0:
|
||||
rec.gain_or_loss = 'gain'
|
||||
elif rec.modify_action in ('sell', 'dispose') and cmp_result > 0:
|
||||
rec.gain_or_loss = 'loss'
|
||||
else:
|
||||
rec.gain_or_loss = 'no'
|
||||
|
||||
@api.depends('asset_id', 'value_residual', 'salvage_value')
|
||||
def _compute_gain_value(self):
|
||||
"""Check whether the modification increases the asset's book value."""
|
||||
for rec in self:
|
||||
rec.gain_value = rec.currency_id.compare_amounts(
|
||||
rec._get_own_book_value(),
|
||||
rec.asset_id._get_own_book_value(rec.date),
|
||||
) > 0
|
||||
|
||||
@api.depends('loss_account_id', 'gain_account_id', 'gain_or_loss',
|
||||
'modify_action', 'date', 'value_residual', 'salvage_value')
|
||||
def _compute_informational_text(self):
|
||||
"""Generate user-facing description of what will happen."""
|
||||
for wiz in self:
|
||||
formatted_date = format_date(self.env, wiz.date)
|
||||
|
||||
if wiz.modify_action == 'dispose':
|
||||
acct_name, result_label = '', _('gain/loss')
|
||||
if wiz.gain_or_loss == 'gain':
|
||||
acct_name = wiz.gain_account_id.display_name or ''
|
||||
result_label = _('gain')
|
||||
elif wiz.gain_or_loss == 'loss':
|
||||
acct_name = wiz.loss_account_id.display_name or ''
|
||||
result_label = _('loss')
|
||||
wiz.informational_text = _(
|
||||
"Depreciation will be posted through %(date)s."
|
||||
"<br/> A disposal entry will go to the %(account_type)s "
|
||||
"account <b>%(account)s</b>.",
|
||||
date=formatted_date,
|
||||
account_type=result_label,
|
||||
account=acct_name,
|
||||
)
|
||||
|
||||
elif wiz.modify_action == 'sell':
|
||||
acct_name = ''
|
||||
if wiz.gain_or_loss == 'gain':
|
||||
acct_name = wiz.gain_account_id.display_name or ''
|
||||
elif wiz.gain_or_loss == 'loss':
|
||||
acct_name = wiz.loss_account_id.display_name or ''
|
||||
wiz.informational_text = _(
|
||||
"Depreciation will be posted through %(date)s."
|
||||
"<br/> A secondary entry will neutralize the original "
|
||||
"revenue and post the sale outcome to account "
|
||||
"<b>%(account)s</b>.",
|
||||
date=formatted_date,
|
||||
account=acct_name,
|
||||
)
|
||||
|
||||
elif wiz.modify_action == 'pause':
|
||||
wiz.informational_text = _(
|
||||
"Depreciation will be posted through %s.",
|
||||
formatted_date,
|
||||
)
|
||||
|
||||
elif wiz.modify_action == 'modify':
|
||||
increase_note = (
|
||||
_("A child asset will be created for the value increase. <br/>")
|
||||
if wiz.gain_value else ""
|
||||
)
|
||||
wiz.informational_text = _(
|
||||
"Depreciation will be posted through %(date)s. <br/> "
|
||||
"%(extra_text)s Future entries will be recalculated to "
|
||||
"reflect the updated parameters.",
|
||||
date=formatted_date,
|
||||
extra_text=increase_note,
|
||||
)
|
||||
|
||||
else:
|
||||
# Resume or other
|
||||
increase_note = (
|
||||
_("A child asset will be created for the value increase. <br/>")
|
||||
if wiz.gain_value else ""
|
||||
)
|
||||
wiz.informational_text = _(
|
||||
"%s Future entries will be recalculated to reflect "
|
||||
"the updated parameters.",
|
||||
increase_note,
|
||||
)
|
||||
|
||||
@api.depends('invoice_ids', 'modify_action')
|
||||
def _compute_select_invoice_line_id(self):
|
||||
for rec in self:
|
||||
rec.select_invoice_line_id = (
|
||||
rec.modify_action == 'sell'
|
||||
and len(rec.invoice_ids.invoice_line_ids) > 1
|
||||
)
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Onchange
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
@api.onchange('modify_action')
|
||||
def _onchange_action(self):
|
||||
if (
|
||||
self.modify_action == 'sell'
|
||||
and self.asset_id.children_ids.filtered(
|
||||
lambda child: child.state in ('draft', 'open')
|
||||
or child.value_residual > 0
|
||||
)
|
||||
):
|
||||
raise UserError(_(
|
||||
"Cannot automate the sale journal entry for an asset "
|
||||
"with active gross increases. Please dispose of the "
|
||||
"increase(s) first."
|
||||
))
|
||||
if self.modify_action not in ('modify', 'resume'):
|
||||
self.write({
|
||||
'value_residual': self.asset_id._get_residual_value_at_date(self.date),
|
||||
'salvage_value': self.asset_id.salvage_value,
|
||||
})
|
||||
|
||||
@api.onchange('invoice_ids')
|
||||
def _onchange_invoice_ids(self):
|
||||
"""Keep invoice_line_ids in sync when invoices change."""
|
||||
valid_line_ids = self.invoice_ids.invoice_line_ids.filtered(
|
||||
lambda ln: ln._origin.id in self.invoice_line_ids.ids,
|
||||
)
|
||||
self.invoice_line_ids = valid_line_ids
|
||||
# Auto-select lines for single-line invoices
|
||||
for inv in self.invoice_ids.filtered(lambda i: len(i.invoice_line_ids) == 1):
|
||||
self.invoice_line_ids += inv.invoice_line_ids
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# CRUD Override
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
"""Populate defaults from the linked asset when not provided."""
|
||||
AssetModel = self.env['account.asset']
|
||||
for vals in vals_list:
|
||||
if 'asset_id' not in vals:
|
||||
continue
|
||||
asset = AssetModel.browse(vals['asset_id'])
|
||||
# Block if future posted depreciation exists
|
||||
future_posted = asset.depreciation_move_ids.filtered(
|
||||
lambda mv: (
|
||||
mv.state == 'posted'
|
||||
and not mv.reversal_move_ids
|
||||
and mv.date > fields.Date.today()
|
||||
)
|
||||
)
|
||||
if future_posted:
|
||||
raise UserError(_(
|
||||
'Please reverse any future-dated depreciation entries '
|
||||
'before modifying this asset.'
|
||||
))
|
||||
# Fill in missing defaults from the asset
|
||||
field_defaults = {
|
||||
'method_number': asset.method_number,
|
||||
'method_period': asset.method_period,
|
||||
'salvage_value': asset.salvage_value,
|
||||
'account_asset_id': asset.account_asset_id.id,
|
||||
'account_depreciation_id': asset.account_depreciation_id.id,
|
||||
'account_depreciation_expense_id': asset.account_depreciation_expense_id.id,
|
||||
}
|
||||
for fld, default_val in field_defaults.items():
|
||||
if fld not in vals:
|
||||
vals[fld] = default_val
|
||||
return super().create(vals_list)
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Main Business Actions
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
def modify(self):
|
||||
"""Re-evaluate the asset: update depreciation parameters,
|
||||
handle value increases/decreases, and recompute the schedule."""
|
||||
lock_threshold = self.asset_id.company_id._get_user_fiscal_lock_date(
|
||||
self.asset_id.journal_id,
|
||||
)
|
||||
if self.date <= lock_threshold:
|
||||
raise UserError(_(
|
||||
"The selected date is on or before the fiscal lock date. "
|
||||
"Re-evaluation is not permitted."
|
||||
))
|
||||
|
||||
# Snapshot current values for change tracking
|
||||
prior_vals = {
|
||||
'method_number': self.asset_id.method_number,
|
||||
'method_period': self.asset_id.method_period,
|
||||
'value_residual': self.asset_id.value_residual,
|
||||
'salvage_value': self.asset_id.salvage_value,
|
||||
}
|
||||
|
||||
updated_vals = {
|
||||
'method_number': self.method_number,
|
||||
'method_period': self.method_period,
|
||||
'salvage_value': self.salvage_value,
|
||||
'account_asset_id': self.account_asset_id,
|
||||
'account_depreciation_id': self.account_depreciation_id,
|
||||
'account_depreciation_expense_id': self.account_depreciation_expense_id,
|
||||
}
|
||||
|
||||
# Handle resume-after-pause scenario
|
||||
is_resuming = self.env.context.get('resume_after_pause')
|
||||
if is_resuming:
|
||||
latest_depr = self.asset_id.depreciation_move_ids
|
||||
last_depr_date = (
|
||||
max(latest_depr, key=lambda m: m.date).date
|
||||
if latest_depr else self.asset_id.acquisition_date
|
||||
)
|
||||
gap_days = self.asset_id._get_delta_days(last_depr_date, self.date) - 1
|
||||
if self.currency_id.compare_amounts(gap_days, 0) < 0:
|
||||
raise UserError(_(
|
||||
"Resume date must be after the pause date."
|
||||
))
|
||||
updated_vals['asset_paused_days'] = (
|
||||
self.asset_id.asset_paused_days + gap_days
|
||||
)
|
||||
updated_vals['state'] = 'open'
|
||||
self.asset_id.message_post(
|
||||
body=_("Asset resumed. %s", self.name),
|
||||
)
|
||||
|
||||
# Compute value changes
|
||||
current_book = self.asset_id._get_own_book_value(self.date)
|
||||
target_book = self._get_own_book_value()
|
||||
book_increase = target_book - current_book
|
||||
|
||||
new_residual, new_salvage = self._get_new_asset_values(current_book)
|
||||
residual_diff = max(0, self.value_residual - new_residual)
|
||||
salvage_diff = max(0, self.salvage_value - new_salvage)
|
||||
|
||||
# Create depreciation up to modification date (unless resuming)
|
||||
if not is_resuming:
|
||||
draft_before = self.env['account.move'].search_count([
|
||||
('asset_id', '=', self.asset_id.id),
|
||||
('state', '=', 'draft'),
|
||||
('date', '<=', self.date),
|
||||
], limit=1)
|
||||
if draft_before:
|
||||
raise UserError(_(
|
||||
'Unposted depreciation entries exist before the '
|
||||
'selected date. Please process them first.'
|
||||
))
|
||||
self.asset_id._create_move_before_date(self.date)
|
||||
|
||||
updated_vals['salvage_value'] = new_salvage
|
||||
|
||||
# Detect if child assets need recomputation
|
||||
schedule_changed = (
|
||||
updated_vals['method_number'] != self.asset_id.method_number
|
||||
or updated_vals['method_period'] != self.asset_id.method_period
|
||||
or (
|
||||
updated_vals.get('asset_paused_days')
|
||||
and not float_is_zero(
|
||||
updated_vals['asset_paused_days']
|
||||
- self.asset_id.asset_paused_days, 8,
|
||||
)
|
||||
)
|
||||
)
|
||||
self.asset_id.write(updated_vals)
|
||||
|
||||
# Create gross increase asset if value went up
|
||||
total_increase = residual_diff + salvage_diff
|
||||
if self.currency_id.compare_amounts(total_increase, 0) > 0:
|
||||
increase_date = self.date + relativedelta(days=1)
|
||||
increase_entry = self.env['account.move'].create({
|
||||
'journal_id': self.asset_id.journal_id.id,
|
||||
'date': increase_date,
|
||||
'move_type': 'entry',
|
||||
'asset_move_type': 'positive_revaluation',
|
||||
'line_ids': [
|
||||
Command.create({
|
||||
'account_id': self.account_asset_id.id,
|
||||
'debit': total_increase,
|
||||
'credit': 0,
|
||||
'name': _(
|
||||
'Value increase for: %(asset)s',
|
||||
asset=self.asset_id.name,
|
||||
),
|
||||
}),
|
||||
Command.create({
|
||||
'account_id': self.account_asset_counterpart_id.id,
|
||||
'debit': 0,
|
||||
'credit': total_increase,
|
||||
'name': _(
|
||||
'Value increase for: %(asset)s',
|
||||
asset=self.asset_id.name,
|
||||
),
|
||||
}),
|
||||
],
|
||||
})
|
||||
increase_entry._post()
|
||||
|
||||
child_asset = self.env['account.asset'].create({
|
||||
'name': (
|
||||
self.asset_id.name + ': ' + self.name
|
||||
if self.name else ""
|
||||
),
|
||||
'currency_id': self.asset_id.currency_id.id,
|
||||
'company_id': self.asset_id.company_id.id,
|
||||
'method': self.asset_id.method,
|
||||
'method_number': self.method_number,
|
||||
'method_period': self.method_period,
|
||||
'method_progress_factor': self.asset_id.method_progress_factor,
|
||||
'acquisition_date': increase_date,
|
||||
'value_residual': residual_diff,
|
||||
'salvage_value': salvage_diff,
|
||||
'prorata_date': increase_date,
|
||||
'prorata_computation_type': (
|
||||
'daily_computation'
|
||||
if self.asset_id.prorata_computation_type == 'daily_computation'
|
||||
else 'constant_periods'
|
||||
),
|
||||
'original_value': self._get_increase_original_value(
|
||||
residual_diff, salvage_diff,
|
||||
),
|
||||
'account_asset_id': self.account_asset_id.id,
|
||||
'account_depreciation_id': self.account_depreciation_id.id,
|
||||
'account_depreciation_expense_id': self.account_depreciation_expense_id.id,
|
||||
'journal_id': self.asset_id.journal_id.id,
|
||||
'parent_id': self.asset_id.id,
|
||||
'original_move_line_ids': [
|
||||
(6, 0, increase_entry.line_ids.filtered(
|
||||
lambda ln: ln.account_id == self.account_asset_id,
|
||||
).ids),
|
||||
],
|
||||
})
|
||||
child_asset.validate()
|
||||
|
||||
link_html = child_asset._get_html_link()
|
||||
self.asset_id.message_post(
|
||||
body=_('Gross increase created: %(link)s', link=link_html),
|
||||
)
|
||||
|
||||
# Create negative revaluation entry if value went down
|
||||
if self.currency_id.compare_amounts(book_increase, 0) < 0:
|
||||
depr_vals = self.env['account.move']._prepare_move_for_asset_depreciation({
|
||||
'amount': -book_increase,
|
||||
'asset_id': self.asset_id,
|
||||
'move_ref': _(
|
||||
'Value decrease for: %(asset)s', asset=self.asset_id.name,
|
||||
),
|
||||
'depreciation_beginning_date': self.date,
|
||||
'depreciation_end_date': self.date,
|
||||
'date': self.date,
|
||||
'asset_number_days': 0,
|
||||
'asset_value_change': True,
|
||||
'asset_move_type': 'negative_revaluation',
|
||||
})
|
||||
self.env['account.move'].create(depr_vals)._post()
|
||||
|
||||
# Recompute depreciation schedule
|
||||
board_start = self.date if is_resuming else self.date + relativedelta(days=1)
|
||||
if self.asset_id.depreciation_move_ids:
|
||||
self.asset_id.compute_depreciation_board(board_start)
|
||||
else:
|
||||
self.asset_id.compute_depreciation_board()
|
||||
|
||||
# Propagate changes to child assets if schedule params changed
|
||||
if schedule_changed:
|
||||
child_assets = self.asset_id.children_ids
|
||||
child_assets.write({
|
||||
'method_number': updated_vals['method_number'],
|
||||
'method_period': updated_vals['method_period'],
|
||||
'asset_paused_days': self.asset_id.asset_paused_days,
|
||||
})
|
||||
for child in child_assets:
|
||||
if not is_resuming:
|
||||
child._create_move_before_date(self.date)
|
||||
if child.depreciation_move_ids:
|
||||
child.compute_depreciation_board(board_start)
|
||||
else:
|
||||
child.compute_depreciation_board()
|
||||
child._check_depreciations()
|
||||
child.depreciation_move_ids.filtered(
|
||||
lambda mv: mv.state != 'posted',
|
||||
)._post()
|
||||
|
||||
# Log tracked changes in the chatter
|
||||
tracked_fields = self.env['account.asset'].fields_get(prior_vals.keys())
|
||||
changes, tracking_vals = self.asset_id._mail_track(
|
||||
tracked_fields, prior_vals,
|
||||
)
|
||||
if changes:
|
||||
self.asset_id.message_post(
|
||||
body=_('Depreciation board modified %s', self.name),
|
||||
tracking_value_ids=tracking_vals,
|
||||
)
|
||||
|
||||
self.asset_id._check_depreciations()
|
||||
self.asset_id.depreciation_move_ids.filtered(
|
||||
lambda mv: mv.state != 'posted',
|
||||
)._post()
|
||||
|
||||
return {'type': 'ir.actions.act_window_close'}
|
||||
|
||||
def pause(self):
|
||||
"""Pause depreciation for the asset."""
|
||||
for rec in self:
|
||||
rec.asset_id.pause(pause_date=rec.date, message=self.name)
|
||||
|
||||
def sell_dispose(self):
|
||||
"""Dispose of or sell the asset, generating closing entries."""
|
||||
self.ensure_one()
|
||||
if (
|
||||
self.gain_account_id == self.asset_id.account_depreciation_id
|
||||
or self.loss_account_id == self.asset_id.account_depreciation_id
|
||||
):
|
||||
raise UserError(_(
|
||||
"The gain/loss account cannot be the same as the "
|
||||
"Depreciation Account."
|
||||
))
|
||||
disposal_lines = (
|
||||
self.env['account.move.line']
|
||||
if self.modify_action == 'dispose'
|
||||
else self.invoice_line_ids
|
||||
)
|
||||
return self.asset_id.set_to_close(
|
||||
invoice_line_ids=disposal_lines,
|
||||
date=self.date,
|
||||
message=self.name,
|
||||
)
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Utility Methods
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
def _get_own_book_value(self):
|
||||
"""Return the wizard's configured book value (residual + salvage)."""
|
||||
return self.value_residual + self.salvage_value
|
||||
|
||||
def _get_increase_original_value(self, residual_increase, salvage_increase):
|
||||
"""Compute the original value for a gross increase child asset."""
|
||||
return residual_increase + salvage_increase
|
||||
|
||||
def _get_new_asset_values(self, current_asset_book):
|
||||
"""Calculate capped residual and salvage values to ensure
|
||||
they don't exceed the current book value."""
|
||||
self.ensure_one()
|
||||
capped_residual = min(
|
||||
current_asset_book - min(self.salvage_value, self.asset_id.salvage_value),
|
||||
self.value_residual,
|
||||
)
|
||||
capped_salvage = min(
|
||||
current_asset_book - capped_residual,
|
||||
self.salvage_value,
|
||||
)
|
||||
return capped_residual, capped_salvage
|
||||
Reference in New Issue
Block a user