diff --git a/account_cutoff_base/__manifest__.py b/account_cutoff_base/__manifest__.py index 29dbc6ec6a6..7caa1a36793 100644 --- a/account_cutoff_base/__manifest__.py +++ b/account_cutoff_base/__manifest__.py @@ -9,7 +9,7 @@ "license": "AGPL-3", "summary": "Base module for Account Cut-offs", "author": "Akretion,Odoo Community Association (OCA)", - "maintainers": ["alexis-via"], + "maintainers": ["alexis-via", "jbaudoux"], "website": "https://github.com/OCA/account-closing", "depends": ["account"], "data": [ diff --git a/account_cutoff_base/models/account_cutoff.py b/account_cutoff_base/models/account_cutoff.py index 4118e5d448d..8257594b64a 100644 --- a/account_cutoff_base/models/account_cutoff.py +++ b/account_cutoff_base/models/account_cutoff.py @@ -1,4 +1,5 @@ -# Copyright 2013-2021 Akretion (http://www.akretion.com/) +# Copyright 2013 Akretion (http://www.akretion.com/) +# Copyright 2018 Jacques-Etienne Baudoux (BCIM) # @author: Alexis de Lattre # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). @@ -109,6 +110,24 @@ def _default_cutoff_account_id(self): copy=False, check_company=True, ) + auto_reverse = fields.Boolean( + help="Automatically reverse created move on following day. Use this " + "if you accrue a value end of period that you want to reverse " + "begin of next period", + ) + move_reversal_id = fields.Many2one( + "account.move", + string="Cut-off Journal Entry Reversal", + compute="_compute_move_reversal_id", + ) + + @api.depends("move_id.reversal_move_id", "move_id.reversal_move_id.state") + def _compute_move_reversal_id(self): + for rec in self: + rec.move_reversal_id = rec.move_id.reversal_move_id.filtered( + lambda m: m.state != "cancel" + )[:1] + move_ref = fields.Char( string="Reference of the Cut-off Journal Entry", states={"done": [("readonly", True)]}, @@ -191,6 +210,10 @@ def name_get(self): def back2draft(self): self.ensure_one() + if self.move_reversal_id: + self.move_reversal_id.line_ids.remove_move_reconcile() + self.move_reversal_id.unlink() + self.move_id.line_ids.remove_move_reconcile() if self.move_id: self.move_id.unlink() self.write({"state": "draft"}) @@ -325,6 +348,20 @@ def create_move(self): move = move_obj.create(vals) if self.company_id.post_cutoff_move: move._post(soft=False) + + if self.auto_reverse: + next_day = fields.Date.from_string(self.cutoff_date) + relativedelta(days=1) + rev_move = move._reverse_moves( + [ + { + "date": next_day, + "ref": _("reversal of: ") + move.ref, + } + ] + ) + if self.company_id.post_cutoff_move: + rev_move._post(soft=False) + self.write({"move_id": move.id, "state": "done"}) self.message_post(body=_("Journal entry generated")) diff --git a/account_cutoff_base/readme/CONTRIBUTORS.rst b/account_cutoff_base/readme/CONTRIBUTORS.rst index 740c34299d1..6a7d85d9f00 100644 --- a/account_cutoff_base/readme/CONTRIBUTORS.rst +++ b/account_cutoff_base/readme/CONTRIBUTORS.rst @@ -7,3 +7,4 @@ * Jim Hoefnagels * `Trobz `_: * Dzung Tran +* Jacques-Etienne Baudoux (BCIM) diff --git a/account_cutoff_base/tests/test_account_cutoff.py b/account_cutoff_base/tests/test_account_cutoff.py index 22709a9b95a..de9cd5d8981 100644 --- a/account_cutoff_base/tests/test_account_cutoff.py +++ b/account_cutoff_base/tests/test_account_cutoff.py @@ -1,9 +1,33 @@ +# Copyright 2018 Jacques-Etienne Baudoux (BCIM) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from odoo import Command, fields from odoo.tests.common import TransactionCase class TestAccountCutoff(TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True)) + cls.company = cls.env.ref("base.main_company") + cls.cutoff_journal = cls.env["account.journal"].create( + { + "code": "cop0", + "company_id": cls.company.id, + "name": "Cutoff Journal Base", + "type": "general", + } + ) + cls.cutoff_account = cls.env["account.account"].create( + { + "name": "Cutoff Base Account", + "code": "ACB480000", + "company_id": cls.company.id, + "account_type": "liability_current", + } + ) + def test_default_cutoff_account_id(self): account_id = self.env["account.cutoff"]._default_cutoff_account_id() self.assertEqual(account_id, False) @@ -36,3 +60,87 @@ def test_default_cutoff_account_id(self): random_account.id, "The account must be equals to %s" % random_account.id, ) + + def test_create_move(self): + type_cutoff = "accrued_revenue" + cutoff = ( + self.env["account.cutoff"] + .with_context(default_cutoff_type=type_cutoff) + .create( + { + "cutoff_type": type_cutoff, + "company_id": 1, + "cutoff_date": fields.Date.today(), + "cutoff_account_id": self.cutoff_account.id, + "cutoff_journal_id": self.cutoff_journal.id, + } + ) + ) + account = self.env["account.account"].create( + { + "name": "Base account", + "code": "ACB220000", + "company_id": self.company.id, + "account_type": "liability_current", + } + ) + cutoff.line_ids = [ + Command.create( + { + "parent_id": cutoff.id, + "account_id": account.id, + "cutoff_account_id": self.cutoff_account.id, + "cutoff_amount": 50, + }, + ) + ] + self.company.post_cutoff_move = False + cutoff.auto_reverse = False + cutoff.create_move() + self.assertEqual( + cutoff.move_id.state, + "draft", + "A draft move is expected", + ) + self.assertFalse( + cutoff.move_reversal_id, + "No reversal move is expected", + ) + cutoff.back2draft() + self.assertFalse( + cutoff.move_id, + "No move is expected", + ) + cutoff.auto_reverse = True + cutoff.create_move() + self.assertEqual( + cutoff.move_id.state, + "draft", + "A draft move is expected", + ) + self.assertEqual( + cutoff.move_reversal_id.state, + "draft", + "A draft reversal move is expected", + ) + cutoff.back2draft() + self.assertFalse( + cutoff.move_id, + "No move is expected", + ) + self.assertFalse( + cutoff.move_reversal_id, + "No reversal move is expected", + ) + self.company.post_cutoff_move = True + cutoff.create_move() + self.assertEqual( + cutoff.move_id.state, + "posted", + "A posted move is expected", + ) + self.assertEqual( + cutoff.move_id.state, + "posted", + "A posted reversal move is expected", + ) diff --git a/account_cutoff_base/views/account_cutoff.xml b/account_cutoff_base/views/account_cutoff.xml index 3dbfd9ddd0b..475e9aa6f8c 100644 --- a/account_cutoff_base/views/account_cutoff.xml +++ b/account_cutoff_base/views/account_cutoff.xml @@ -67,6 +67,7 @@ options="{'datepicker': {'warn_future': true}}" /> + @@ -85,6 +86,7 @@ +