From 129435339749b234bbe779ceb4fea69df517f96d Mon Sep 17 00:00:00 2001 From: Simone Rubino Date: Mon, 25 Mar 2024 17:45:06 +0100 Subject: [PATCH] [IMP] l10n_it_asset_management: Max depreciable amount --- l10n_it_asset_management/models/__init__.py | 4 +- l10n_it_asset_management/models/asset.py | 4 +- .../asset_category_depreciation_type.py | 11 ++- .../asset_compute_depreciable_amount.py | 28 ++++++++ .../models/asset_depreciation.py | 17 +++-- .../tests/test_assets_management.py | 68 ++++++++++++++++++- .../views/asset_category.xml | 1 + .../views/asset_depreciation.xml | 14 +++- 8 files changed, 126 insertions(+), 21 deletions(-) create mode 100644 l10n_it_asset_management/models/asset_compute_depreciable_amount.py diff --git a/l10n_it_asset_management/models/__init__.py b/l10n_it_asset_management/models/__init__.py index 9e043ec0841c..9f5013acbc28 100644 --- a/l10n_it_asset_management/models/__init__.py +++ b/l10n_it_asset_management/models/__init__.py @@ -1,7 +1,7 @@ -# Author(s): Silvio Gregorini (silviogregorini@openforce.it) -# Copyright 2019 Openforce Srls Unipersonale (www.openforce.it) # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +from . import asset_compute_depreciable_amount + from . import account_account from . import account_fiscal_year from . import account_journal diff --git a/l10n_it_asset_management/models/asset.py b/l10n_it_asset_management/models/asset.py index 949605621e62..f340bd3a5024 100644 --- a/l10n_it_asset_management/models/asset.py +++ b/l10n_it_asset_management/models/asset.py @@ -179,7 +179,9 @@ def onchange_company_currency(self): def onchange_purchase_amount(self): if self.purchase_amount: for dep in self.depreciation_ids: - dep.amount_depreciable = self.purchase_amount * dep.base_coeff + dep.amount_depreciable = dep._get_depreciable_amount( + self.purchase_amount + ) if self.depreciation_ids.mapped("line_ids").filtered( lambda line: line.move_type == "depreciated" ): diff --git a/l10n_it_asset_management/models/asset_category_depreciation_type.py b/l10n_it_asset_management/models/asset_category_depreciation_type.py index 0b81fa7b8061..af1586555895 100644 --- a/l10n_it_asset_management/models/asset_category_depreciation_type.py +++ b/l10n_it_asset_management/models/asset_category_depreciation_type.py @@ -1,5 +1,6 @@ # Author(s): Silvio Gregorini (silviogregorini@openforce.it) # Copyright 2019 Openforce Srls Unipersonale (www.openforce.it) +# Copyright 2024 Simone Rubino - Aion Tech # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). from odoo import fields, models @@ -7,14 +8,9 @@ class AssetCategoryDepreciationType(models.Model): _name = "asset.category.depreciation.type" + _inherit = "l10n_it_asset_management.compute.depreciable_amount" _description = "Asset Category - Depreciation Type" - base_coeff = fields.Float( - default=1, - help="Coeff to compute depreciable amount from purchase amount", - string="Dep Base Coeff", - ) - category_id = fields.Many2one( "asset.category", ondelete="cascade", @@ -46,8 +42,9 @@ class AssetCategoryDepreciationType(models.Model): def get_depreciation_vals(self, amount_depreciable=0): self.ensure_one() return { - "amount_depreciable": amount_depreciable * self.base_coeff, + "amount_depreciable": self._get_depreciable_amount(amount_depreciable), "base_coeff": self.base_coeff, + "base_max_amount": self.base_max_amount, "mode_id": self.mode_id.id, "percentage": self.percentage, "pro_rata_temporis": self.pro_rata_temporis, diff --git a/l10n_it_asset_management/models/asset_compute_depreciable_amount.py b/l10n_it_asset_management/models/asset_compute_depreciable_amount.py new file mode 100644 index 000000000000..c85b68948536 --- /dev/null +++ b/l10n_it_asset_management/models/asset_compute_depreciable_amount.py @@ -0,0 +1,28 @@ +# Copyright 2024 Simone Rubino - Aion Tech +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class AssetComputeDepreciableAmount(models.AbstractModel): + _name = "l10n_it_asset_management.compute.depreciable_amount" + _description = "Compute depreciable amount" + + base_coeff = fields.Float( + default=1, + help="Coeff to compute depreciable amount from purchase amount", + string="Dep Base Coeff", + ) + base_max_amount = fields.Float( + string="Maximum depreciable amount", + ) + + def _get_depreciable_amount(self, base_amount): + """Compute how much of `base_amount` can be depreciated.""" + self.ensure_one() + depreciable_amount = base_amount + if self.base_coeff: + depreciable_amount = base_amount * self.base_coeff + if self.base_max_amount: + depreciable_amount = min(depreciable_amount, self.base_max_amount) + return depreciable_amount diff --git a/l10n_it_asset_management/models/asset_depreciation.py b/l10n_it_asset_management/models/asset_depreciation.py index 994d50671c25..5be42b5c1e92 100644 --- a/l10n_it_asset_management/models/asset_depreciation.py +++ b/l10n_it_asset_management/models/asset_depreciation.py @@ -11,6 +11,7 @@ class AssetDepreciation(models.Model): _name = "asset.depreciation" + _inherit = "l10n_it_asset_management.compute.depreciable_amount" _description = "Assets Depreciations" amount_depreciable = fields.Monetary(string="Initial Depreciable Amount") @@ -71,12 +72,6 @@ class AssetDepreciation(models.Model): string="Asset", ) - base_coeff = fields.Float( - default=1, - help="Coeff to compute amount depreciable from purchase amount", - string="Depreciable Base Coeff", - ) - company_id = fields.Many2one( "res.company", readonly=True, related="asset_id.company_id", string="Company" ) @@ -196,10 +191,14 @@ def _compute_state(self): for dep in self: dep.state = dep.get_depreciation_state() - @api.onchange("asset_id", "base_coeff") - def onchange_base_coeff(self): + @api.onchange( + "asset_id", + "base_coeff", + "base_max_amount", + ) + def onchange_depreciable_amount_computation(self): purchase_amount = self.asset_id.purchase_amount - self.amount_depreciable = self.base_coeff * purchase_amount + self.amount_depreciable = self._get_depreciable_amount(purchase_amount) @api.onchange("first_dep_nr") def onchange_normalize_first_dep_nr(self): diff --git a/l10n_it_asset_management/tests/test_assets_management.py b/l10n_it_asset_management/tests/test_assets_management.py index 4a62c4bb4a1b..159dbdf1e090 100644 --- a/l10n_it_asset_management/tests/test_assets_management.py +++ b/l10n_it_asset_management/tests/test_assets_management.py @@ -7,7 +7,7 @@ from odoo import fields from odoo.exceptions import ValidationError from odoo.fields import Command, first -from odoo.tests.common import TransactionCase +from odoo.tests.common import Form, TransactionCase from odoo.tools.date_utils import relativedelta @@ -642,6 +642,72 @@ def test_04_asset_partial_depreciate_from_purchase_invoice_increment(self): sum(civ_dep_lines.mapped("amount")), 7000 * 0.6 + 9000 * 0.4 ) + def _create_asset_wizard(self, move, wizard_values=None): + """Create the asset management wizard on `move`.""" + if wizard_values is None: + wizard_values = dict() + + wizard_action = move.open_wizard_manage_asset() + wizard_model_name = wizard_action["res_model"] + wizard_context = wizard_action["context"] + wizard_model = self.env[wizard_model_name].with_context(**wizard_context) + + wizard_form = Form(wizard_model) + for field, value in wizard_values.items(): + setattr(wizard_form, field, value) + return wizard_form.save() + + def _run_asset_wizard(self, move, wizard_values=None): + """Execute the asset management wizard on `move`.""" + wizard = self._create_asset_wizard(move, wizard_values=wizard_values) + return wizard.link_asset() + + def test_max_amount_depreciable(self): + """ + Set max amount depreciable in category line, + if the asset has a higher amount, the max amount is set as depreciable instead. + """ + # Arrange + purchase_amount = 1000 + max_depreciable_amount = 120 + category = self.asset_category_1 + civ_type = self.env.ref("l10n_it_asset_management.ad_type_civilistico") + category_civ_depreciation_type = category.type_ids.filtered( + lambda x: x.depreciation_type_id == civ_type + ) + category_civ_depreciation_type.update( + { + "base_max_amount": max_depreciable_amount, + } + ) + purchase_invoice = self._create_purchase_invoice( + fields.Date.today(), amount=purchase_amount + ) + # pre-condition + self.assertEqual(purchase_invoice.amount_untaxed, purchase_amount) + self.assertEqual( + category_civ_depreciation_type.base_max_amount, max_depreciable_amount + ) + self.assertGreater(purchase_amount, max_depreciable_amount) + + # Act + asset = self._run_asset_wizard( + purchase_invoice, + wizard_values={ + "management_type": "create", + "name": "Test asset", + "category_id": category, + }, + ) + + # Assert + self.assertEqual(asset.category_id, category) + civ_depreciation = asset.depreciation_ids.filtered( + lambda x: x.type_id == civ_type + ) + self.assertEqual(civ_depreciation.base_max_amount, max_depreciable_amount) + self.assertEqual(civ_depreciation.amount_depreciable, max_depreciable_amount) + def _civil_depreciate_asset(self, asset): # Keep only one civil depreciation civil_depreciation_type = self.env.ref( diff --git a/l10n_it_asset_management/views/asset_category.xml b/l10n_it_asset_management/views/asset_category.xml index 25f52490e213..fd2959baeba0 100644 --- a/l10n_it_asset_management/views/asset_category.xml +++ b/l10n_it_asset_management/views/asset_category.xml @@ -40,6 +40,7 @@ + diff --git a/l10n_it_asset_management/views/asset_depreciation.xml b/l10n_it_asset_management/views/asset_depreciation.xml index 3193b56bd33a..c11cf1741c81 100644 --- a/l10n_it_asset_management/views/asset_depreciation.xml +++ b/l10n_it_asset_management/views/asset_depreciation.xml @@ -44,7 +44,19 @@ /> +