Skip to content

Commit

Permalink
[IMP] l10n_it_asset_management: Recharge asset
Browse files Browse the repository at this point in the history
  • Loading branch information
SirAionTech committed Jul 10, 2024
1 parent 7aacda4 commit 672f0fa
Show file tree
Hide file tree
Showing 7 changed files with 330 additions and 14 deletions.
1 change: 1 addition & 0 deletions l10n_it_asset_management/models/account_move.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ def open_wizard_manage_asset(self):
{
"default_company_id": self.company_id.id,
"default_dismiss_date": self.invoice_date or self.invoice_date_due,
"default_recharge_date": self.invoice_date or self.invoice_date_due,
"default_move_ids": [Command.set(self.ids)],
"default_move_line_ids": [Command.set(lines.ids)],
"default_purchase_date": self.invoice_date or self.invoice_date_due,
Expand Down
1 change: 1 addition & 0 deletions l10n_it_asset_management/models/asset_accounting_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class AssetAccountingInfo(models.Model):
relation_type = fields.Selection(
[
("create", "Asset Creation"),
("partial_recharge", "Partial Recharge"),
("update", "Asset Update"),
("partial_dismiss", "Asset Partial Dismissal"),
("dismiss", "Asset Dismissal"),
Expand Down
10 changes: 10 additions & 0 deletions l10n_it_asset_management/models/asset_depreciation_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -495,3 +495,13 @@ def post_partial_dismiss_asset(self):
)
if to_create_move:
to_create_move.generate_account_move()

def post_partial_recharge_asset(self):
dep = self.mapped("depreciation_id")
dep.ensure_one()
types = ("depreciated", "gain", "loss")
to_create_move = self.filtered(
lambda line: line.needs_account_move() and line.move_type in types
)
if to_create_move:
to_create_move.generate_account_move()
79 changes: 67 additions & 12 deletions l10n_it_asset_management/tests/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from datetime import date

from odoo.fields import Command, first
from odoo.tests.common import TransactionCase, Form
from odoo.tests.common import Form, TransactionCase


class Common(TransactionCase):
Expand Down Expand Up @@ -65,6 +65,12 @@ def setUpClass(cls):
],
limit=1,
)
cls.sale_journal = cls.env["account.journal"].search(
[
("type", "=", "sale"),
],
limit=1,
)

cls.civilistico_asset_dep_type = cls.env.ref(
"l10n_it_asset_management.ad_type_civilistico"
Expand Down Expand Up @@ -208,6 +214,49 @@ def _create_purchase_invoice(self, invoice_date, tax_ids=False, amount=7000):
self.assertEqual(purchase_invoice.state, "posted")
return purchase_invoice

def _create_sale_invoice(self, asset, amount=7000, invoice_date=None, post=True):
sale_invoice = self.env["account.move"].create(
{
"move_type": "out_invoice",
"invoice_date": invoice_date,
"partner_id": self.env.ref("base.partner_demo").id,
"journal_id": self.sale_journal.id,
"invoice_line_ids": [
Command.create(
{
"account_id": asset.category_id.asset_account_id.id,
"quantity": 1,
"price_unit": amount,
},
)
],
}
)
if post:
sale_invoice.action_post()
return sale_invoice

def _refund_move(self, move, method="cancel", ref_date=None):
reverse_context = {
"active_model": move._name,
"active_ids": move.ids,
}
refund_wizard_form = Form(
self.env["account.move.reversal"].with_context(**reverse_context)
)
refund_wizard_form.reason = "test"
if ref_date:
refund_wizard_form.date_mode = "custom"
refund_wizard_form.date = ref_date
refund_wizard_form.refund_method = method
refund_wizard = refund_wizard_form.save()

refund_action = refund_wizard.reverse_moves()
refund_move = self.env[refund_action["res_model"]].browse(
refund_action["res_id"]
)
return refund_move

def _civil_depreciate_asset(self, asset):
# Keep only one civil depreciation
civil_depreciation_type = self.env.ref(
Expand Down Expand Up @@ -298,15 +347,21 @@ def _create_entry(self, account, amount, post=True):
self.assertEqual(entry.move_type, "entry")
return entry

def _update_asset(self, entry, asset):
"""Execute the wizard on `entry` to update `asset`."""
wizard_action = entry.open_wizard_manage_asset()
wizard_model = self.env[wizard_action["res_model"]]
wizard_context = wizard_action["context"]
def _link_asset_move(self, move, link_management_type, wiz_values=None):
"""Link `asset` to `move` with mode `link_management_type`.
`wiz_values` are values to be set in the wizard.
"""
if wiz_values is None:
wiz_values = {}

wizard_form = Form(wizard_model.with_context(**wizard_context))
wizard_form.management_type = "update"
wizard_form.asset_id = asset
wizard = wizard_form.save()

return wizard.link_asset()
wiz_action_values = move.open_wizard_manage_asset()
wiz_form = Form(
self.env["wizard.account.move.manage.asset"].with_context(
**wiz_action_values["context"]
)
)
wiz_form.management_type = link_management_type
for field_name, field_value in wiz_values.items():
setattr(wiz_form, field_name, field_value)
wiz = wiz_form.save()
return wiz.link_asset()
76 changes: 74 additions & 2 deletions l10n_it_asset_management/tests/test_assets_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# Copyright 2023 Simone Rubino - Aion Tech
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

import datetime
from datetime import date

from odoo import fields
Expand Down Expand Up @@ -456,7 +457,13 @@ def test_entry_in_update_asset(self):
self.assertFalse(asset.asset_accounting_info_ids)

# Act
self._update_asset(entry, asset)
self._link_asset_move(
entry,
"update",
wiz_values={
"asset_id": asset,
},
)

# Assert
accounting_info = asset.asset_accounting_info_ids
Expand All @@ -476,7 +483,13 @@ def test_entry_out_update_asset(self):
self.assertFalse(asset.asset_accounting_info_ids)

# Act
self._update_asset(entry, asset)
self._link_asset_move(
entry,
"update",
wiz_values={
"asset_id": asset,
},
)

# Assert
accounting_info = asset.asset_accounting_info_ids
Expand Down Expand Up @@ -508,3 +521,62 @@ def test_journal_prev_year(self):
total = report.report_total_ids
self.assertEqual(total.amount_depreciation_fund_curr_year, 1000)
self.assertEqual(total.amount_depreciation_fund_prev_year, 1000)

def test_purchase_sale_refund_recharge(self):
"""A sale refund can be used to restore asset value."""
# Create with purchase
purchase_amount = 2500
purchase_invoice = self._create_purchase_invoice(
datetime.date(2020, month=1, day=1), amount=purchase_amount
)
asset = self._link_asset_move(
purchase_invoice,
"create",
{
"category_id": self.asset_category_1,
"name": "Test recharge asset",
},
)
civ_depreciation = asset.depreciation_ids.filtered(
lambda x: x.type_id
== self.env.ref("l10n_it_asset_management.ad_type_civilistico")
)
self.assertEqual(civ_depreciation.amount_depreciable_updated, purchase_amount)

# Partial dismiss with sale
asset_account_amount = asset_fund_amount = 1000
sale_invoice = self._create_sale_invoice(
asset, amount=8000, invoice_date=datetime.date(2020, month=3, day=1)
)
self._link_asset_move(
sale_invoice,
"partial_dismiss",
wiz_values={
"asset_id": asset,
"depreciated_fund_amount": asset_account_amount,
"asset_purchase_amount": asset_fund_amount,
},
)
self.assertEqual(
civ_depreciation.amount_depreciable_updated,
purchase_amount - asset_account_amount,
)

# Refund and recharge
sale_refund = self._refund_move(
sale_invoice, ref_date=datetime.date(2020, month=7, day=1)
)
recharge_purchase_amount = recharge_fund_amount = 1000
self._link_asset_move(
sale_refund,
"partial_recharge",
wiz_values={
"asset_id": asset,
"recharge_purchase_amount": recharge_purchase_amount,
"recharge_fund_amount": recharge_fund_amount,
},
)
self.assertEqual(
civ_depreciation.amount_depreciable_updated,
purchase_amount,
)
139 changes: 139 additions & 0 deletions l10n_it_asset_management/wizard/account_move_manage_asset.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ def get_default_move_ids(self):
management_type = fields.Selection(
[
("create", "Create New"),
("partial_recharge", "Partial Recharge"),
("update", "Update Existing"),
("partial_dismiss", "Partial Dismiss"),
("dismiss", "Dismiss Asset"),
Expand Down Expand Up @@ -104,6 +105,12 @@ def get_default_move_ids(self):

used = fields.Boolean()

recharge_date = fields.Date(
default=fields.Date.today(),
)
recharge_purchase_amount = fields.Monetary()
recharge_fund_amount = fields.Monetary()

# Mapping between move journal type and depreciation line type
_move_journal_type_2_dep_line_type = {
"purchase": "in",
Expand All @@ -117,6 +124,7 @@ def get_default_move_ids(self):
# Every method used in here must return an asset
_management_type_2_method = {
"create": lambda w: w.create_asset(),
"partial_recharge": lambda w: w.partial_recharge_asset(),
"dismiss": lambda w: w.dismiss_asset(),
"partial_dismiss": lambda w: w.partial_dismiss_asset(),
"update": lambda w: w.update_asset(),
Expand Down Expand Up @@ -735,3 +743,134 @@ def update_asset(self):
self.check_pre_update_asset()
self.asset_id.write(self.get_update_asset_vals())
return self.asset_id

def check_pre_partial_recharge_asset(self):
self.ensure_one()
asset = self.asset_id
if not asset:
raise ValidationError(_("Please choose an asset before continuing!"))

move_lines = self.move_line_ids
if not move_lines:
raise ValidationError(
_(
"At least one move line is needed"
" to partial recharge asset %(asset)s!",
asset=asset,
)
)

asset_account = asset.category_id.asset_account_id
if not all(line.account_id == asset_account for line in move_lines):
raise ValidationError(
_(
"You need to choose move lines with account `%(ass_acc)s`"
" if you need them to partial recharge asset `%(ass_name)s`!",
ass_acc=asset_account.display_name,
ass_name=asset.display_name,
)
)

def get_partial_recharge_asset_vals(self):
self.ensure_one()
asset = self.asset_id
currency = self.asset_id.currency_id
recharge_date = self.recharge_date
digits = self.env["decimal.precision"].precision_get("Account")
fund_amt = self.recharge_fund_amount
purchase_amt = self.recharge_purchase_amount

move = self.move_line_ids.mapped("move_id")
move_nums = move.name

writeoff = 0
for line in self.move_line_ids:
writeoff += line.currency_id._convert(
line.credit - line.debit, currency, line.company_id, line.date
)
writeoff = round(writeoff, digits)

vals = {"depreciation_ids": []}
for dep in asset.depreciation_ids:
dep_writeoff = writeoff
if dep.pro_rata_temporis:
dep_writeoff *= dep.get_pro_rata_temporis_multiplier(
recharge_date, "std"
)

name = _(
"Partial recharge from move(s) %(move_nums)s",
move_nums=move_nums,
)

out_line_vals = {
"asset_accounting_info_ids": [
Command.create(
{
"move_line_id": line.id,
"relation_type": self.management_type,
},
)
for line in self.move_line_ids
],
"amount": purchase_amt,
"date": recharge_date,
"move_type": "in",
"name": name,
}
dep_line_vals = {
"asset_accounting_info_ids": [
Command.create(
{
"move_line_id": line.id,
"relation_type": self.management_type,
},
)
for line in self.move_line_ids
],
"amount": -fund_amt,
"date": recharge_date,
"move_type": "depreciated",
"name": name,
}

dep_vals = {
"line_ids": [
Command.create(out_line_vals),
Command.create(dep_line_vals),
]
}

balance = purchase_amt + dep_writeoff - fund_amt
if not float_is_zero(balance, digits):
loss_gain_vals = {
"asset_accounting_info_ids": [
Command.create(
{
"move_line_id": line.id,
"relation_type": self.management_type,
},
)
for line in self.move_line_ids
],
"amount": abs(balance),
"date": recharge_date,
"move_type": "gain" if balance > 0 else "loss",
"name": name,
}
dep_vals["line_ids"].append(Command.create(loss_gain_vals))

vals["depreciation_ids"].append(Command.update(dep.id, dep_vals))
return vals

def partial_recharge_asset(self):
"""Recharge asset partially and return it."""
self.ensure_one()
self.check_pre_partial_recharge_asset()
old_dep_lines = self.asset_id.mapped("depreciation_ids.line_ids")
self.asset_id.write(self.get_partial_recharge_asset_vals())

for dep in self.asset_id.depreciation_ids:
(dep.line_ids - old_dep_lines).post_partial_dismiss_asset()

return self.asset_id
Loading

0 comments on commit 672f0fa

Please sign in to comment.