[IMP] account_asset_management: Allow to reverse the posting of a depreciation line
instead of deleting the journal entry. This will be done when the company has activated the inalterability hash on the original journal entry.
This commit is contained in:
parent
c62bab7c9e
commit
92e7f1cee5
@ -28,5 +28,6 @@
|
||||
"views/menuitem.xml",
|
||||
"data/cron.xml",
|
||||
"wizard/wiz_account_asset_report.xml",
|
||||
"wizard/wiz_asset_move_reverse.xml",
|
||||
],
|
||||
}
|
||||
|
@ -296,16 +296,38 @@ class AccountAssetLine(models.Model):
|
||||
"context": self.env.context,
|
||||
}
|
||||
|
||||
def update_asset_line_after_unlink_move(self):
|
||||
self.write({"move_id": False})
|
||||
if self.parent_state == "close":
|
||||
self.asset_id.write({"state": "open"})
|
||||
elif self.parent_state == "removed" and self.type == "remove":
|
||||
self.asset_id.write({"state": "close", "date_remove": False})
|
||||
self.unlink()
|
||||
|
||||
def unlink_move(self):
|
||||
for line in self:
|
||||
move = line.move_id
|
||||
move.button_draft()
|
||||
move.with_context(force_delete=True, unlink_from_asset=True).unlink()
|
||||
# trigger store function
|
||||
line.with_context(unlink_from_asset=True).write({"move_id": False})
|
||||
if line.parent_state == "close":
|
||||
line.asset_id.write({"state": "open"})
|
||||
elif line.parent_state == "removed" and line.type == "remove":
|
||||
line.asset_id.write({"state": "close", "date_remove": False})
|
||||
line.unlink()
|
||||
if line.asset_id.profile_id.allow_reversal:
|
||||
context = dict(self._context or {})
|
||||
context.update(
|
||||
{
|
||||
"active_model": self._name,
|
||||
"active_ids": line.ids,
|
||||
"active_id": line.id,
|
||||
}
|
||||
)
|
||||
return {
|
||||
"name": _("Reverse Move"),
|
||||
"view_mode": "form",
|
||||
"res_model": "wiz.asset.move.reverse",
|
||||
"target": "new",
|
||||
"type": "ir.actions.act_window",
|
||||
"context": context,
|
||||
}
|
||||
else:
|
||||
move = line.move_id
|
||||
move.button_draft()
|
||||
move.with_context(force_delete=True, unlink_from_asset=True).unlink()
|
||||
line.with_context(
|
||||
unlink_from_asset=True
|
||||
).update_asset_line_after_unlink_move()
|
||||
return True
|
||||
|
@ -163,6 +163,12 @@ class AccountAssetProfile(models.Model):
|
||||
"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):
|
||||
|
@ -130,8 +130,15 @@ class AccountMove(models.Model):
|
||||
for line_command in move_vals.get("line_ids", []):
|
||||
line_vals = line_command[2] # (0, 0, {...})
|
||||
asset = self.env["account.asset"].browse(line_vals["asset_id"])
|
||||
asset.unlink()
|
||||
line_vals.update(asset_profile_id=False, asset_id=False)
|
||||
# We remove the asset if we recognize that we are reversing
|
||||
# the asset creation
|
||||
if asset:
|
||||
asset_line = self.env["account.asset.line"].search(
|
||||
[("asset_id", "=", asset.id), ("type", "=", "create")], limit=1
|
||||
)
|
||||
if asset_line and asset_line.move_id == self:
|
||||
asset.unlink()
|
||||
line_vals.update(asset_profile_id=False, asset_id=False)
|
||||
return move_vals
|
||||
|
||||
def action_view_assets(self):
|
||||
|
@ -15,3 +15,8 @@
|
||||
* Pedro M. Baeza
|
||||
* João Marques
|
||||
* Víctor Martínez
|
||||
|
||||
* `ForgeFlow <https://www.forgeflow.com>`_:
|
||||
|
||||
* Jordi Ballester <jordi.ballester@forgeflow.com>
|
||||
* Miquel Raïch <miquel.raich@forgeflow.com>
|
||||
|
@ -3,6 +3,12 @@
|
||||
|
||||
* [BREAKING] Removed all functionality associated with `account.fiscal.year`
|
||||
|
||||
13.0.3.0.0 (2021-07-06)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Allow to reverse the posting of a depreciation line instead of deleting the
|
||||
journal entry.
|
||||
|
||||
13.0.2.0.0 (2021-02-19)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -16,3 +16,4 @@ access_account_asset_group_manager,account.asset.group,model_account_asset_group
|
||||
access_account_asset_remove_user,account.asset.remove,model_account_asset_remove,account.group_account_user,1,1,1,1
|
||||
access_account_asset_compute_user,account.asset.compute,model_account_asset_compute,account.group_account_user,1,1,1,1
|
||||
access_wiz_account_asset_report,wiz.account.asset.report,model_wiz_account_asset_report,account.group_account_readonly,1,1,1,0
|
||||
access_wiz_asset_move_reverse_user,wiz.asset.move.reverse,model_wiz_asset_move_reverse,account.group_account_user,1,1,1,1
|
||||
|
|
@ -803,6 +803,88 @@ class TestAssetManagement(AccountTestInvoicingCommon):
|
||||
# In the last month the small deviations are compensated
|
||||
self.assertAlmostEqual(d_lines[12].amount, 416.63, places=2)
|
||||
|
||||
def test_18_reverse_entries(self):
|
||||
"""Test that cancelling a posted entry creates a reversal."""
|
||||
ict0 = self.asset_model.create(
|
||||
{
|
||||
"state": "draft",
|
||||
"method_time": "year",
|
||||
"method_number": 3,
|
||||
"method_period": "year",
|
||||
"name": "Laptop",
|
||||
"code": "PI00101",
|
||||
"purchase_value": 1500.0,
|
||||
"profile_id": self.ict3Y.id,
|
||||
"date_start": time.strftime("%Y-01-01"),
|
||||
}
|
||||
)
|
||||
ict0.profile_id.allow_reversal = True
|
||||
# compute the depreciation boards
|
||||
ict0.compute_depreciation_board()
|
||||
ict0.refresh()
|
||||
# post the first depreciation line
|
||||
ict0.validate()
|
||||
ict0.depreciation_line_ids[1].create_move()
|
||||
original_move = ict0.depreciation_line_ids[1].move_id
|
||||
ict0.refresh()
|
||||
self.assertEqual(ict0.state, "open")
|
||||
self.assertEqual(ict0.value_depreciated, 500)
|
||||
self.assertEqual(ict0.value_residual, 1000)
|
||||
depreciation_line = ict0.depreciation_line_ids[1]
|
||||
wiz_res = depreciation_line.unlink_move()
|
||||
self.assertTrue(
|
||||
"res_model" in wiz_res and wiz_res["res_model"] == "wiz.asset.move.reverse"
|
||||
)
|
||||
wiz = Form(
|
||||
self.env["wiz.asset.move.reverse"].with_context(
|
||||
{
|
||||
"active_model": depreciation_line._name,
|
||||
"active_id": depreciation_line.id,
|
||||
"active_ids": [depreciation_line.id],
|
||||
}
|
||||
)
|
||||
)
|
||||
reverse_wizard = wiz.save()
|
||||
reverse_wizard.reverse_move()
|
||||
ict0.refresh()
|
||||
self.assertEqual(ict0.value_depreciated, 0)
|
||||
self.assertEqual(ict0.value_residual, 1500)
|
||||
self.assertEqual(len(original_move.reversal_move_id), 1)
|
||||
|
||||
def test_19_unlink_entries(self):
|
||||
"""Test that cancelling a posted entry creates a reversal, if the
|
||||
journal entry has the inalterability hash."""
|
||||
ict0 = self.asset_model.create(
|
||||
{
|
||||
"state": "draft",
|
||||
"method_time": "year",
|
||||
"method_number": 3,
|
||||
"method_period": "year",
|
||||
"name": "Laptop",
|
||||
"code": "PI00101",
|
||||
"purchase_value": 1500.0,
|
||||
"profile_id": self.ict3Y.id,
|
||||
"date_start": time.strftime("%Y-01-01"),
|
||||
}
|
||||
)
|
||||
# compute the depreciation boards
|
||||
ict0.compute_depreciation_board()
|
||||
ict0.refresh()
|
||||
# post the first depreciation line
|
||||
ict0.validate()
|
||||
ict0.depreciation_line_ids[1].create_move()
|
||||
original_move_id = ict0.depreciation_line_ids[1].move_id.id
|
||||
ict0.refresh()
|
||||
self.assertEqual(ict0.state, "open")
|
||||
self.assertEqual(ict0.value_depreciated, 500)
|
||||
self.assertEqual(ict0.value_residual, 1000)
|
||||
ict0.depreciation_line_ids[1].unlink_move()
|
||||
ict0.refresh()
|
||||
self.assertEqual(ict0.value_depreciated, 0)
|
||||
self.assertEqual(ict0.value_residual, 1500)
|
||||
move = self.env["account.move"].search([("id", "=", original_move_id)])
|
||||
self.assertFalse(move)
|
||||
|
||||
def test_20_asset_removal_with_value_residual(self):
|
||||
"""Asset removal with value residual"""
|
||||
asset = self.asset_model.create(
|
||||
|
@ -204,7 +204,7 @@
|
||||
<button
|
||||
name="unlink_move"
|
||||
icon="fa-times"
|
||||
string="Delete Move"
|
||||
string="Delete/Reverse Move"
|
||||
type="object"
|
||||
confirm="Are you sure ?"
|
||||
groups="account.group_account_manager"
|
||||
|
@ -38,6 +38,7 @@
|
||||
<field name="account_plus_value_id" />
|
||||
<field name="account_min_value_id" />
|
||||
<field name="account_residual_value_id" />
|
||||
<field name="allow_reversal" />
|
||||
</group>
|
||||
<group string="Depreciation Dates">
|
||||
<field name="method_time" />
|
||||
|
@ -1,3 +1,4 @@
|
||||
from . import account_asset_compute
|
||||
from . import account_asset_remove
|
||||
from . import wiz_account_asset_report
|
||||
from . import wiz_asset_move_reverse
|
||||
|
59
account_asset_management/wizard/wiz_asset_move_reverse.py
Normal file
59
account_asset_management/wizard/wiz_asset_move_reverse.py
Normal file
@ -0,0 +1,59 @@
|
||||
# Copyright 2021 ForgeFlow, S.L.
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class WizAssetMoveReverse(models.TransientModel):
|
||||
_name = "wiz.asset.move.reverse"
|
||||
_description = "Reverse posted journal entry on depreciation line"
|
||||
|
||||
line_id = fields.Many2one(
|
||||
comodel_name="account.asset.line",
|
||||
string="Asset Line",
|
||||
readonly=True,
|
||||
required=True,
|
||||
)
|
||||
date_reversal = fields.Date(
|
||||
string="Reversal date",
|
||||
required=True,
|
||||
default=fields.Date.context_today,
|
||||
)
|
||||
reason = fields.Char(string="Reason")
|
||||
journal_id = fields.Many2one(
|
||||
"account.journal",
|
||||
string="Use Specific Journal",
|
||||
help="If empty, uses the journal of the journal entry to be reversed.",
|
||||
)
|
||||
|
||||
@api.model
|
||||
def default_get(self, fields):
|
||||
res = super(WizAssetMoveReverse, self).default_get(fields)
|
||||
line_ids = (
|
||||
self.env["account.asset.line"].browse(self.env.context["active_ids"])
|
||||
if self.env.context.get("active_model") == "account.asset.line"
|
||||
else self.env["account.asset.line"]
|
||||
)
|
||||
res["line_id"] = line_ids[0].id if line_ids else False
|
||||
return res
|
||||
|
||||
def reverse_move(self):
|
||||
move = self.line_id.move_id
|
||||
move_reversal = (
|
||||
self.env["account.move.reversal"]
|
||||
.with_context(active_model="account.move", active_ids=move.ids)
|
||||
.create(
|
||||
{
|
||||
"date": fields.Date.today(),
|
||||
"reason": self.reason,
|
||||
"refund_method": "refund",
|
||||
"journal_id": self.journal_id.id,
|
||||
}
|
||||
)
|
||||
)
|
||||
reversal = move_reversal.with_context(allow_asset=True).reverse_moves()
|
||||
reverse_move = self.env["account.move"].browse(reversal["res_id"])
|
||||
reverse_move.action_post()
|
||||
self.line_id.with_context(
|
||||
unlink_from_asset=True
|
||||
).update_asset_line_after_unlink_move()
|
||||
return True
|
27
account_asset_management/wizard/wiz_asset_move_reverse.xml
Normal file
27
account_asset_management/wizard/wiz_asset_move_reverse.xml
Normal file
@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<record id="wiz_asset_move_reverse_view_form" model="ir.ui.view">
|
||||
<field name="name">wiz.asset.move.reverse.form</field>
|
||||
<field name="model">wiz.asset.move.reverse</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Reverse Journal Entry">
|
||||
<group>
|
||||
<field name="line_id" invisible="True" />
|
||||
<field name="date_reversal" />
|
||||
<field name="journal_id" />
|
||||
<field name="reason" />
|
||||
</group>
|
||||
<newline />
|
||||
<footer>
|
||||
<button
|
||||
string="Confirm"
|
||||
name="reverse_move"
|
||||
type="object"
|
||||
class="oe_highlight"
|
||||
/>
|
||||
<button string="Cancel" class="oe_link" special="cancel" />
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
Loading…
Reference in New Issue
Block a user