mirror of
https://github.com/OCA/account-financial-tools.git
synced 2025-02-02 12:47:26 +02:00
@@ -26,5 +26,6 @@
|
||||
"views/menuitem.xml",
|
||||
"data/cron.xml",
|
||||
"wizard/wiz_account_asset_report.xml",
|
||||
"wizard/wiz_asset_move_reverse.xml",
|
||||
],
|
||||
}
|
||||
|
||||
@@ -292,16 +292,38 @@ class AccountAssetLine(models.Model):
|
||||
"domain": [("id", "=", self.move_id.id)],
|
||||
}
|
||||
|
||||
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):
|
||||
|
||||
@@ -125,8 +125,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,7 @@
|
||||
* Pedro M. Baeza
|
||||
* Víctor Martínez
|
||||
* João Marques
|
||||
|
||||
* `ForgeFlow <https://www.forgeflow.com>`_:
|
||||
|
||||
* Jordi Ballester <jordi.ballester@forgeflow.com>
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
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)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
@@ -794,3 +794,75 @@ class TestAssetManagement(SavepointCase):
|
||||
self.assertAlmostEqual(d_lines[_i].amount, 416.67, places=2)
|
||||
# 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."""
|
||||
#
|
||||
# first load demo assets and do some sanity checks
|
||||
#
|
||||
ict0 = self.browse_ref("account_asset_management.account_asset_asset_ict0")
|
||||
ict0.profile_id.allow_reversal = True
|
||||
#
|
||||
# I compute the depreciation boards
|
||||
#
|
||||
ict0.compute_depreciation_board()
|
||||
ict0.refresh()
|
||||
#
|
||||
# I 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."""
|
||||
#
|
||||
# first load demo assets and do some sanity checks
|
||||
#
|
||||
ict0 = self.browse_ref("account_asset_management." "account_asset_asset_ict0")
|
||||
#
|
||||
# I compute the depreciation boards
|
||||
#
|
||||
ict0.compute_depreciation_board()
|
||||
ict0.refresh()
|
||||
#
|
||||
# I 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)
|
||||
|
||||
@@ -206,7 +206,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"
|
||||
|
||||
@@ -26,6 +26,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
|
||||
|
||||
57
account_asset_management/wizard/wiz_asset_move_reverse.py
Normal file
57
account_asset_management/wizard/wiz_asset_move_reverse.py
Normal file
@@ -0,0 +1,57 @@
|
||||
# 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.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>
|
||||
Reference in New Issue
Block a user