[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",
|
"views/menuitem.xml",
|
||||||
"data/cron.xml",
|
"data/cron.xml",
|
||||||
"wizard/wiz_account_asset_report.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,
|
"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):
|
def unlink_move(self):
|
||||||
for line in self:
|
for line in self:
|
||||||
|
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 = line.move_id
|
||||||
move.button_draft()
|
move.button_draft()
|
||||||
move.with_context(force_delete=True, unlink_from_asset=True).unlink()
|
move.with_context(force_delete=True, unlink_from_asset=True).unlink()
|
||||||
# trigger store function
|
line.with_context(
|
||||||
line.with_context(unlink_from_asset=True).write({"move_id": False})
|
unlink_from_asset=True
|
||||||
if line.parent_state == "close":
|
).update_asset_line_after_unlink_move()
|
||||||
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()
|
|
||||||
return True
|
return True
|
||||||
|
@ -163,6 +163,12 @@ class AccountAssetProfile(models.Model):
|
|||||||
"product item. So, there will be an asset by product item.",
|
"product item. So, there will be an asset by product item.",
|
||||||
)
|
)
|
||||||
active = fields.Boolean(default=True)
|
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
|
@api.model
|
||||||
def _default_company_id(self):
|
def _default_company_id(self):
|
||||||
|
@ -130,6 +130,13 @@ class AccountMove(models.Model):
|
|||||||
for line_command in move_vals.get("line_ids", []):
|
for line_command in move_vals.get("line_ids", []):
|
||||||
line_vals = line_command[2] # (0, 0, {...})
|
line_vals = line_command[2] # (0, 0, {...})
|
||||||
asset = self.env["account.asset"].browse(line_vals["asset_id"])
|
asset = self.env["account.asset"].browse(line_vals["asset_id"])
|
||||||
|
# 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()
|
asset.unlink()
|
||||||
line_vals.update(asset_profile_id=False, asset_id=False)
|
line_vals.update(asset_profile_id=False, asset_id=False)
|
||||||
return move_vals
|
return move_vals
|
||||||
|
@ -15,3 +15,8 @@
|
|||||||
* Pedro M. Baeza
|
* Pedro M. Baeza
|
||||||
* João Marques
|
* João Marques
|
||||||
* Víctor Martínez
|
* 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`
|
* [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)
|
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_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_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_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
|
# In the last month the small deviations are compensated
|
||||||
self.assertAlmostEqual(d_lines[12].amount, 416.63, places=2)
|
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):
|
def test_20_asset_removal_with_value_residual(self):
|
||||||
"""Asset removal with value residual"""
|
"""Asset removal with value residual"""
|
||||||
asset = self.asset_model.create(
|
asset = self.asset_model.create(
|
||||||
|
@ -204,7 +204,7 @@
|
|||||||
<button
|
<button
|
||||||
name="unlink_move"
|
name="unlink_move"
|
||||||
icon="fa-times"
|
icon="fa-times"
|
||||||
string="Delete Move"
|
string="Delete/Reverse Move"
|
||||||
type="object"
|
type="object"
|
||||||
confirm="Are you sure ?"
|
confirm="Are you sure ?"
|
||||||
groups="account.group_account_manager"
|
groups="account.group_account_manager"
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
<field name="account_plus_value_id" />
|
<field name="account_plus_value_id" />
|
||||||
<field name="account_min_value_id" />
|
<field name="account_min_value_id" />
|
||||||
<field name="account_residual_value_id" />
|
<field name="account_residual_value_id" />
|
||||||
|
<field name="allow_reversal" />
|
||||||
</group>
|
</group>
|
||||||
<group string="Depreciation Dates">
|
<group string="Depreciation Dates">
|
||||||
<field name="method_time" />
|
<field name="method_time" />
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
from . import account_asset_compute
|
from . import account_asset_compute
|
||||||
from . import account_asset_remove
|
from . import account_asset_remove
|
||||||
from . import wiz_account_asset_report
|
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