2
0
account-financial-tools/account_asset_management/models/account_asset_profile.py
ps-tubtim 92e9d246ef [ENH] account_asset_management: default salvage value on profile
This PR enables the configuration of salvage value in the asset profile.
Users can configure it with a fixed amount or a percentage of the salvage value.
2024-02-15 18:52:42 +07:00

242 lines
9.2 KiB
Python

# Copyright 2009-2018 Noviat
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import _, api, fields, models
from odoo.exceptions import UserError
class AccountAssetProfile(models.Model):
_name = "account.asset.profile"
_inherit = "analytic.mixin"
_check_company_auto = True
_description = "Asset profile"
_order = "name"
name = fields.Char(size=64, required=True, index=True)
note = fields.Text()
account_asset_id = fields.Many2one(
comodel_name="account.account",
domain="[('deprecated', '=', False), ('company_id', '=', company_id)]",
string="Asset Account",
check_company=True,
required=True,
)
account_depreciation_id = fields.Many2one(
comodel_name="account.account",
domain="[('deprecated', '=', False), ('company_id', '=', company_id)]",
string="Depreciation Account",
check_company=True,
required=True,
)
account_expense_depreciation_id = fields.Many2one(
comodel_name="account.account",
domain="[('deprecated', '=', False), ('company_id', '=', company_id)]",
string="Depr. Expense Account",
check_company=True,
required=True,
)
account_plus_value_id = fields.Many2one(
comodel_name="account.account",
domain="[('deprecated', '=', False), ('company_id', '=', company_id)]",
check_company=True,
string="Plus-Value Account",
)
account_min_value_id = fields.Many2one(
comodel_name="account.account",
domain="[('deprecated', '=', False), ('company_id', '=', company_id)]",
check_company=True,
string="Min-Value Account",
)
account_residual_value_id = fields.Many2one(
comodel_name="account.account",
domain="[('deprecated', '=', False), ('company_id', '=', company_id)]",
check_company=True,
string="Residual Value Account",
)
journal_id = fields.Many2one(
comodel_name="account.journal",
domain="[('type', '=', 'general'), ('company_id', '=', company_id)]",
string="Journal",
check_company=True,
required=True,
)
company_id = fields.Many2one(
comodel_name="res.company",
string="Company",
required=True,
default=lambda self: self._default_company_id(),
)
group_ids = fields.Many2many(
comodel_name="account.asset.group",
relation="account_asset_profile_group_rel",
column1="profile_id",
column2="group_id",
check_company=True,
string="Asset Groups",
)
salvage_value = fields.Float(
digits="Account",
help="The estimated value that an asset will realize upon "
"its sale at the end of its useful life.\n"
"This value is used to determine the depreciation amounts.",
)
salvage_type = fields.Selection(
selection=[("fixed", "Fixed"), ("percent", "Percentage of Price")]
)
method = fields.Selection(
selection=lambda self: self._selection_method(),
string="Computation Method",
required=True,
help="Choose the method to use to compute the depreciation lines.\n"
" * Linear: Calculated on basis of: "
"Depreciation Base / Number of Depreciations. "
"Depreciation Base = Purchase Value - Salvage Value.\n"
" * Linear-Limit: Linear up to Salvage Value. "
"Depreciation Base = Purchase Value.\n"
" * Degressive: Calculated on basis of: "
"Residual Value * Degressive Factor.\n"
" * Degressive-Linear (only for Time Method = Year): "
"Degressive becomes linear when the annual linear "
"depreciation exceeds the annual degressive depreciation.\n"
" * Degressive-Limit: Degressive up to Salvage Value. "
"The Depreciation Base is equal to the asset value.",
default="linear",
)
method_number = fields.Integer(
string="Number of Years",
help="The number of years needed to depreciate your asset",
default=5,
)
method_period = fields.Selection(
selection=lambda self: self._selection_method_period(),
string="Period Length",
required=True,
default="year",
help="Period length for the depreciation accounting entries",
)
method_progress_factor = fields.Float(string="Degressive Factor", default=0.3)
method_time = fields.Selection(
selection=lambda self: self._selection_method_time(),
string="Time Method",
required=True,
default="year",
help="Choose the method to use to compute the dates and "
"number of depreciation lines.\n"
" * Number of Years: Specify the number of years "
"for the depreciation.\n"
" * Number of Depreciations: Fix the number of "
"depreciation lines and the time between 2 depreciations.\n",
)
days_calc = fields.Boolean(
string="Calculate by days",
default=False,
help="Use number of days to calculate depreciation amount",
)
use_leap_years = fields.Boolean(
default=False,
help="If not set, the system will distribute evenly the amount to "
"amortize across the years, based on the number of years. "
"So the amount per year will be the "
"depreciation base / number of years.\n "
"If set, the system will consider if the current year "
"is a leap year. The amount to depreciate per year will be "
"calculated as depreciation base / (depreciation end date - "
"start date + 1) * days in the current year.",
)
prorata = fields.Boolean(
string="Prorata Temporis",
compute="_compute_prorrata",
readonly=False,
store=True,
help="Indicates that the first depreciation entry for this asset "
"has to be done from the depreciation start date instead of "
"the first day of the fiscal year.",
)
open_asset = fields.Boolean(
string="Skip Draft State",
help="Check this if you want to automatically confirm the assets "
"of this profile when created by invoices.",
)
asset_product_item = fields.Boolean(
string="Create an asset by product item",
help="By default during the validation of an invoice, an asset "
"is created by invoice line as long as an accounting entry is "
"created by invoice line. "
"With this setting, an accounting entry will be created by "
"product item. So, there will be an asset by product item.",
)
active = fields.Boolean(default=True)
allow_reversal = fields.Boolean(
"Allow Reversal of journal entries",
help="If set, when pressing the Delete/Reverse Move button in a "
"posted depreciation line will prompt the option to reverse the "
"journal entry, instead of deleting them.",
)
@api.model
def _default_company_id(self):
return self.env.company
@api.model
def _selection_method(self):
return [
("linear", _("Linear")),
("linear-limit", _("Linear up to Salvage Value")),
("degressive", _("Degressive")),
("degr-linear", _("Degressive-Linear")),
("degr-limit", _("Degressive up to Salvage Value")),
]
@api.model
def _selection_method_period(self):
return [("month", _("Month")), ("quarter", _("Quarter")), ("year", _("Year"))]
@api.model
def _selection_method_time(self):
return [
("year", _("Number of Years or end date")),
("number", _("Number of Depreciations")),
]
@api.constrains("method", "method_time")
def _check_method(self):
if any(a.method == "degr-linear" and a.method_time != "year" for a in self):
raise UserError(
_("Degressive-Linear is only supported for Time Method = Year.")
)
@api.depends("method_time")
def _compute_prorrata(self):
for profile in self:
if profile.method_time != "year":
profile.prorata = True
@api.model_create_multi
def create(self, vals_list):
for vals in vals_list:
if vals.get("method_time") != "year" and not vals.get("prorata"):
vals["prorata"] = True
profile_ids = super().create(vals_list)
account_dict = {}
for profile_id in profile_ids.filtered(
lambda x: not x.account_asset_id.asset_profile_id
):
account_dict.setdefault(profile_id.account_asset_id, []).append(
profile_id.id
)
for account, profile_list in account_dict.items():
account.write({"asset_profile_id": profile_list[-1]})
return profile_ids
def write(self, vals):
if vals.get("method_time"):
if vals["method_time"] != "year" and not vals.get("prorata"):
vals["prorata"] = True
res = super().write(vals)
# TODO last profile in self is defined as default on the related
# account. must be improved.
account = self.env["account.account"].browse(vals.get("account_asset_id"))
if self and account and not account.asset_profile_id:
account.write({"asset_profile_id": self[-1].id})
return res