# 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