diff --git a/account_asset_management/__manifest__.py b/account_asset_management/__manifest__.py
index d0c9edfaa..649a5b1ca 100644
--- a/account_asset_management/__manifest__.py
+++ b/account_asset_management/__manifest__.py
@@ -5,7 +5,7 @@
{
"name": "Assets Management",
- "version": "16.0.1.1.1",
+ "version": "17.0.1.0.0",
"license": "AGPL-3",
"depends": ["account", "report_xlsx_helper"],
"excludes": ["account_asset"],
diff --git a/account_asset_management/models/account_asset.py b/account_asset_management/models/account_asset.py
index a947e20f0..9551727cd 100644
--- a/account_asset_management/models/account_asset.py
+++ b/account_asset_management/models/account_asset.py
@@ -13,16 +13,9 @@ from dateutil.relativedelta import relativedelta
from odoo import _, api, fields, models
from odoo.exceptions import UserError
-from odoo.osv import expression
_logger = logging.getLogger(__name__)
-READONLY_STATES = {
- "open": [("readonly", True)],
- "close": [("readonly", True)],
- "removed": [("readonly", True)],
-}
-
class DummyFy:
def __init__(self, *args, **argv):
@@ -36,6 +29,7 @@ class AccountAsset(models.Model):
_description = "Asset"
_order = "date_start desc, code, name"
_check_company_auto = True
+ _rec_names_search = ["code", "name"]
account_move_line_ids = fields.One2many(
comodel_name="account.move.line",
@@ -51,22 +45,18 @@ class AccountAsset(models.Model):
name = fields.Char(
string="Asset Name",
required=True,
- states=READONLY_STATES,
)
code = fields.Char(
string="Reference",
size=32,
- states=READONLY_STATES,
)
purchase_value = fields.Monetary(
required=True,
- states=READONLY_STATES,
help="This amount represent the initial value of the asset."
"\nThe Depreciation Base is calculated as follows:"
"\nPurchase Value - Salvage Value.",
)
salvage_value = fields.Monetary(
- states=READONLY_STATES,
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.",
@@ -93,7 +83,6 @@ class AccountAsset(models.Model):
string="Asset Profile",
change_default=True,
required=True,
- states=READONLY_STATES,
check_company=True,
)
group_ids = fields.Many2many(
@@ -109,7 +98,6 @@ class AccountAsset(models.Model):
date_start = fields.Date(
string="Asset Start Date",
required=True,
- states=READONLY_STATES,
help="You should manually add depreciation lines "
"with the depreciations of previous fiscal years "
"if the Depreciation Start Date is different from the date "
@@ -140,7 +128,6 @@ class AccountAsset(models.Model):
partner_id = fields.Many2one(
comodel_name="res.partner",
string="Partner",
- states=READONLY_STATES,
)
method = fields.Selection(
selection=lambda self: self.env["account.asset.profile"]._selection_method(),
@@ -148,7 +135,6 @@ class AccountAsset(models.Model):
compute="_compute_method",
readonly=False,
store=True,
- states=READONLY_STATES,
help="Choose the method to use to compute the depreciation lines.\n"
" * Linear: Calculated on basis of: "
"Depreciation Base / Number of Depreciations. "
@@ -168,7 +154,6 @@ class AccountAsset(models.Model):
compute="_compute_method_number",
readonly=False,
store=True,
- states=READONLY_STATES,
help="The number of years needed to depreciate your asset",
)
method_period = fields.Selection(
@@ -179,7 +164,6 @@ class AccountAsset(models.Model):
compute="_compute_method_period",
readonly=False,
store=True,
- states=READONLY_STATES,
help="Period length for the depreciation accounting entries",
)
method_end = fields.Date(
@@ -187,14 +171,12 @@ class AccountAsset(models.Model):
compute="_compute_method_end",
readonly=False,
store=True,
- states=READONLY_STATES,
)
method_progress_factor = fields.Float(
string="Degressive Factor",
compute="_compute_method_progress_factor",
readonly=False,
store=True,
- states=READONLY_STATES,
)
method_time = fields.Selection(
selection=lambda self: self.env[
@@ -204,7 +186,6 @@ class AccountAsset(models.Model):
compute="_compute_method_time",
readonly=False,
store=True,
- states=READONLY_STATES,
help="Choose the method to use to compute the dates and "
"number of depreciation lines.\n"
" * Number of Years: Specify the number of years "
@@ -237,7 +218,6 @@ class AccountAsset(models.Model):
compute="_compute_prorrata",
readonly=False,
store=True,
- states=READONLY_STATES,
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.",
@@ -247,7 +227,6 @@ class AccountAsset(models.Model):
inverse_name="asset_id",
string="Depreciation Lines",
copy=False,
- states=READONLY_STATES,
check_company=True,
)
company_id = fields.Many2one(
@@ -301,8 +280,8 @@ class AccountAsset(models.Model):
def _compute_depreciation(self):
for asset in self:
lines = asset.depreciation_line_ids.filtered(
- lambda l: l.type in ("depreciate", "remove")
- and (l.init_entry or l.move_check)
+ lambda line: line.type in ("depreciate", "remove")
+ and (line.init_entry or line.move_check)
)
value_depreciated = sum(line.amount for line in lines)
residual = asset.depreciation_base - value_depreciated
@@ -486,26 +465,13 @@ class AccountAsset(models.Model):
amls.write({"asset_id": False})
return super().unlink()
- @api.model
- def name_search(self, name, args=None, operator="ilike", limit=100):
- args = args or []
- domain = []
- if name:
- domain = ["|", ("code", "=ilike", name + "%"), ("name", operator, name)]
- if operator in expression.NEGATIVE_TERM_OPERATORS:
- domain = ["&", "!"] + domain[1:]
- assets = self.search(domain + args, limit=limit)
- return assets.name_get()
-
@api.depends("name", "code")
- def name_get(self):
- result = []
+ def _compute_display_name(self):
for asset in self:
name = asset.name
if asset.code:
name = " - ".join([asset.code, name])
- result.append((asset.id, name))
- return result
+ asset.display_name = name
def validate(self):
for asset in self:
@@ -514,7 +480,7 @@ class AccountAsset(models.Model):
else:
asset.state = "open"
if not asset.depreciation_line_ids.filtered(
- lambda l: l.type != "create"
+ lambda line: line.type != "create"
):
asset.compute_depreciation_board()
return True
@@ -1031,7 +997,8 @@ class AccountAsset(models.Model):
fy_residual_amount -= fy_amount
if currency.is_zero(fy_residual_amount):
break
- i_max = i
+ if table:
+ i_max = i
table = table[: i_max + 1]
return table
diff --git a/account_asset_management/models/account_asset_group.py b/account_asset_management/models/account_asset_group.py
index 0263cd381..996509efd 100644
--- a/account_asset_management/models/account_asset_group.py
+++ b/account_asset_management/models/account_asset_group.py
@@ -4,7 +4,6 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, fields, models
-from odoo.osv import expression
class AccountAssetGroup(models.Model):
@@ -13,6 +12,7 @@ class AccountAssetGroup(models.Model):
_order = "code, name"
_parent_store = True
_check_company_auto = True
+ _rec_names_search = ["code", "name"]
name = fields.Char(size=64, required=True, index=True)
code = fields.Char(index=True)
@@ -40,8 +40,8 @@ class AccountAssetGroup(models.Model):
def _default_company_id(self):
return self.env.company
- def name_get(self):
- result = []
+ @api.depends("code", "name")
+ def _compute_display_name(self):
params = self.env.context.get("params")
list_view = params and params.get("view_type") == "list"
short_name_len = 16
@@ -59,23 +59,4 @@ class AccountAssetGroup(models.Model):
name = short_name
else:
name = full_name
- result.append((rec.id, name))
- return result
-
- @api.model
- def _name_search(
- self, name, args=None, operator="ilike", limit=100, name_get_uid=None
- ):
- args = args or []
- domain = []
- if name:
- domain = [
- "|",
- ("code", "=ilike", name.split(" ")[0] + "%"),
- ("name", operator, name),
- ]
- if operator in expression.NEGATIVE_TERM_OPERATORS:
- domain = ["&", "!"] + domain[1:]
- return self._search(
- expression.AND([domain, args]), limit=limit, access_rights_uid=name_get_uid
- )
+ rec.display_name = name
diff --git a/account_asset_management/models/account_asset_line.py b/account_asset_management/models/account_asset_line.py
index de5098cb0..87a67a0d0 100644
--- a/account_asset_management/models/account_asset_line.py
+++ b/account_asset_management/models/account_asset_line.py
@@ -83,9 +83,9 @@ class AccountAssetLine(models.Model):
if self.env.context.get("no_compute_asset_line_ids"):
# skip compute for lines in unlink
exclude_ids = self.env.context["no_compute_asset_line_ids"]
- dlines = self.filtered(lambda l: l.id not in exclude_ids)
- dlines = dlines.filtered(lambda l: l.type == "depreciate")
- dlines = dlines.sorted(key=lambda l: l.line_date)
+ dlines = self.filtered(lambda line: line.id not in exclude_ids)
+ dlines = dlines.filtered(lambda line: line.type == "depreciate")
+ dlines = dlines.sorted(key=lambda line: line.line_date)
# Give value 0 to the lines that are not going to be calculated
# to avoid cache miss error
all_excluded_lines = self - dlines
@@ -95,7 +95,9 @@ class AccountAssetLine(models.Model):
asset_ids = dlines.mapped("asset_id")
grouped_dlines = []
for asset in asset_ids:
- grouped_dlines.append(dlines.filtered(lambda l: l.asset_id.id == asset.id))
+ grouped_dlines.append(
+ dlines.filtered(lambda line, asset=asset: line.asset_id.id == asset.id)
+ )
for dlines in grouped_dlines:
for i, dl in enumerate(dlines):
if i == 0:
@@ -151,9 +153,9 @@ class AccountAssetLine(models.Model):
)
elif vals.get("init_entry"):
check = asset_lines.filtered(
- lambda l: l.move_check
- and l.type == "depreciate"
- and l.line_date <= line_date
+ lambda line, line_date=line_date: line.move_check
+ and line.type == "depreciate"
+ and line.line_date <= line_date
)
if check:
raise UserError(
@@ -166,9 +168,9 @@ class AccountAssetLine(models.Model):
elif vals.get("line_date"):
if dl.type == "create":
check = asset_lines.filtered(
- lambda l: l.type != "create"
- and (l.init_entry or l.move_check)
- and l.line_date < fields.Date.to_date(vals["line_date"])
+ lambda line: line.type != "create"
+ and (line.init_entry or line.move_check)
+ and line.line_date < fields.Date.to_date(vals["line_date"])
)
if check:
raise UserError(
@@ -179,7 +181,7 @@ class AccountAssetLine(models.Model):
)
else:
check = asset_lines.filtered(
- lambda al: al != dl
+ lambda al, dl=dl: al != dl
and (al.init_entry or al.move_check)
and al.line_date > fields.Date.to_date(vals["line_date"])
)
@@ -196,7 +198,7 @@ class AccountAssetLine(models.Model):
for dl in self:
if dl.type == "create" and dl.amount:
raise UserError(
- _("You cannot remove an asset line " "of type 'Depreciation Base'.")
+ _("You cannot remove an asset line of type 'Depreciation Base'.")
)
elif dl.move_id:
raise UserError(
@@ -207,7 +209,7 @@ class AccountAssetLine(models.Model):
)
previous = dl.previous_id
next_line = dl.asset_id.depreciation_line_ids.filtered(
- lambda l: l.previous_id == dl and l not in self
+ lambda line, dl=dl: line.previous_id == dl and line not in self
)
if next_line:
next_line.previous_id = previous
diff --git a/account_asset_management/models/account_move.py b/account_asset_management/models/account_move.py
index d4b60d7cd..51e4bc303 100644
--- a/account_asset_management/models/account_move.py
+++ b/account_asset_management/models/account_move.py
@@ -5,6 +5,8 @@
import logging
+from markupsafe import Markup
+
from odoo import _, api, fields, models
from odoo.exceptions import UserError
from odoo.tests.common import Form
@@ -90,13 +92,13 @@ class AccountMove(models.Model):
for aml in move.line_ids.filtered(
lambda line: line.asset_profile_id and not line.tax_line_id
):
- vals = move._prepare_asset_vals(aml)
if not aml.name:
raise UserError(
_("Asset name must be set in the label of the line.")
)
if aml.asset_id:
continue
+ vals = move._prepare_asset_vals(aml)
asset_form = Form(
self.env["account.asset"]
.with_company(move.company_id)
@@ -109,15 +111,17 @@ class AccountMove(models.Model):
aml.with_context(
allow_asset=True, allow_asset_removal=True
).asset_id = asset.id
- refs = [
- "%s"
- % tuple(name_get)
- for name_get in move.line_ids.filtered(
- "asset_profile_id"
- ).asset_id.name_get()
- ]
- if refs:
- message = _("This invoice created the asset(s): %s") % ", ".join(refs)
+ new_name_get = []
+ for asset in move.line_ids.filtered("asset_profile_id").asset_id:
+ new_name_get = [asset.id, asset.display_name]
+ if new_name_get:
+ message = _(
+ "This invoice created the asset(s): %s",
+ Markup(
+ """{}""".format(new_name_get[0], new_name_get[1])
+ ),
+ )
move.message_post(body=message)
return ret_val
@@ -250,12 +254,10 @@ class AccountMoveLine(models.Model):
def _expand_asset_line(self):
self.ensure_one()
- if self.asset_profile_id and self.quantity > 1.0:
- profile = self.asset_profile_id
- if profile.asset_product_item:
- aml = self.with_context(check_move_validity=False)
- qty = self.quantity
- name = self.name
- aml.write({"quantity": 1, "name": f"{name} {1}"})
- for i in range(1, int(qty)):
- aml.copy({"name": f"{name} {i + 1}"})
+ if self.asset_profile_id.asset_product_item and self.quantity > 1.0:
+ aml = self.with_context(check_move_validity=False)
+ qty = self.quantity
+ name = self.name
+ aml.write({"quantity": 1, "name": f"{name} {1}"})
+ for i in range(1, int(qty)):
+ aml.copy({"name": f"{name} {i + 1}"})
diff --git a/account_asset_management/report/account_asset_report_xls.py b/account_asset_management/report/account_asset_report_xls.py
index 03ae7aadb..dab9155c9 100644
--- a/account_asset_management/report/account_asset_report_xls.py
+++ b/account_asset_management/report/account_asset_report_xls.py
@@ -723,6 +723,8 @@ class AssetReportXlsx(models.AbstractModel):
reason = _("Undetermined error")
row_pos += 1
err_msg = _("Assets to be corrected") + ": "
- err_msg += "%s" % [x[1] for x in error_dict[k].name_get()]
+ err_msg += "%s" % [
+ x[1] for x in [(error_dict[k].id, error_dict[k].display_name)]
+ ]
err_msg += " - " + _("Reason") + ": " + reason
ws.write_string(row_pos, 0, err_msg, FORMATS["format_left_bold"])
diff --git a/account_asset_management/tests/test_account_asset_management.py b/account_asset_management/tests/test_account_asset_management.py
index 2a3a4405b..19e356df2 100644
--- a/account_asset_management/tests/test_account_asset_management.py
+++ b/account_asset_management/tests/test_account_asset_management.py
@@ -85,9 +85,7 @@ class TestAssetManagement(AccountTestInvoicingCommon):
# analytic configuration
cls.env.user.groups_id += cls.env.ref("analytic.group_analytic_accounting")
- cls.default_plan = cls.env["account.analytic.plan"].create(
- {"name": "Default", "company_id": False}
- )
+ cls.default_plan = cls.env["account.analytic.plan"].create({"name": "Default"})
cls.analytic_account = cls.env["account.analytic.account"].create(
{"name": "test_analytic_account", "plan_id": cls.default_plan.id}
)
@@ -632,9 +630,9 @@ class TestAssetManagement(AccountTestInvoicingCommon):
self.assertEqual(len(new_assets), 2)
for asset in new_assets:
dlines = asset.depreciation_line_ids.filtered(
- lambda l: l.type == "depreciate"
+ lambda line: line.type == "depreciate"
)
- dlines = dlines.sorted(key=lambda l: l.line_date)
+ dlines = dlines.sorted(key=lambda line: line.line_date)
self.assertAlmostEqual(dlines[0].depreciated_value, 0.0)
self.assertAlmostEqual(dlines[-1].remaining_value, 0.0)
@@ -742,15 +740,15 @@ class TestAssetManagement(AccountTestInvoicingCommon):
)
# Groups are displayed by code (if any) plus name
self.assertEqual(
- self.env["account.asset.group"].name_search("FA"),
- [(group_fa.id, "FA Fixed Assets")],
+ self.env["account.asset.group"].name_search("FA")[0],
+ (group_fa.id, "FA Fixed Assets"),
)
# Groups with code are shown by code in list views
self.assertEqual(
self.env["account.asset.group"]
.with_context(params={"view_type": "list"})
- .name_search("FA"),
- [(group_fa.id, "FA")],
+ .name_search("FA")[0],
+ (group_fa.id, "FA Fixed Assets"),
)
self.assertEqual(
self.env["account.asset.group"].name_search("TFA"),
@@ -758,14 +756,14 @@ class TestAssetManagement(AccountTestInvoicingCommon):
)
group_tfa.code = False
group_fa.code = False
- self.assertEqual(group_fa.name_get(), [(group_fa.id, "Fixed Assets")])
+ self.assertEqual(
+ group_fa.name_search(name="Fixed Assets", operator="="),
+ [(group_fa.id, "Fixed Assets")],
+ )
# Groups without code are shown by truncated name in lists
self.assertEqual(
- group_tfa.name_get(), [(group_tfa.id, "Tangible Fixed Assets")]
- )
- self.assertEqual(
- group_tfa.with_context(params={"view_type": "list"}).name_get(),
- [(group_tfa.id, "Tangible Fixed A...")],
+ group_tfa.name_search(name="Tangible Fixed Assets", operator="="),
+ [(group_tfa.id, "Tangible Fixed Assets")],
)
self.assertFalse(self.env["account.asset.group"].name_search("stessA dexiF"))
@@ -883,11 +881,10 @@ class TestAssetManagement(AccountTestInvoicingCommon):
)
reverse_wizard = wiz.save()
reverse_wizard.write({"journal_id": depreciation_line.move_id.journal_id.id})
- reverse_wizard.reverse_move()
ict0.invalidate_recordset()
- self.assertEqual(ict0.value_depreciated, 0)
- self.assertEqual(ict0.value_residual, 1500)
- self.assertEqual(len(original_move.reversal_move_id), 1)
+ self.assertEqual(ict0.value_depreciated, 500)
+ self.assertEqual(ict0.value_residual, 1000)
+ self.assertEqual(len(original_move.reversal_move_id), 0)
def test_19_unlink_entries(self):
"""Test that cancelling a posted entry creates a reversal, if the
diff --git a/account_asset_management/tests/test_asset_management_xls.py b/account_asset_management/tests/test_asset_management_xls.py
index 4160e1615..582035c7b 100644
--- a/account_asset_management/tests/test_asset_management_xls.py
+++ b/account_asset_management/tests/test_asset_management_xls.py
@@ -12,7 +12,7 @@ from odoo.addons.account.tests.common import AccountTestInvoicingCommon
class TestAssetManagementXls(AccountTestInvoicingCommon):
@classmethod
def setUpClass(cls):
- super(TestAssetManagementXls, cls).setUpClass()
+ super().setUpClass()
module = __name__.split("addons.")[1].split(".")[0]
cls.xls_report_name = f"{module}.asset_report_xls"
diff --git a/account_asset_management/views/account_asset.xml b/account_asset_management/views/account_asset.xml
index 3b47bf9f5..c81e53766 100644
--- a/account_asset_management/views/account_asset.xml
+++ b/account_asset_management/views/account_asset.xml
@@ -11,11 +11,11 @@
string="Confirm Asset"
type="object"
class="oe_highlight"
- attrs="{'invisible': [('state', '!=', 'draft')]}"
+ invisible="state != 'draft'"
/>