diff --git a/account_analytic_line_split/README.rst b/account_analytic_line_split/README.rst new file mode 100644 index 0000000000..e485d239ce --- /dev/null +++ b/account_analytic_line_split/README.rst @@ -0,0 +1,98 @@ +=========================== +Account Analytic Line Split +=========================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:51841c6908ca68e10fec816309262b08de0c26c69a85b25e60ade24c8b007b58 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Faccount--analytic-lightgray.png?logo=github + :target: https://github.com/OCA/account-analytic/tree/14.0/account_analytic_line_split + :alt: OCA/account-analytic +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/account-analytic-14-0/account-analytic-14-0-account_analytic_line_split + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/account-analytic&target_branch=14.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module allows to split analytic lines in two or more lines. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +To split an analytic line: + +#. Go to Invoicing > Configuration > Management > Analytic Items. +#. Open an Anlytic Entry. +#. Click on "Split Line" button to open the wizard. +#. Create the lines setting the Analytic Account and Percentage of the amount. +#. The new lines will be created and displayed in "Child Lines" notebook. + +To split an analytic line directly from the Account Move: + +#. Open one Account Move (a Journal Entry, Bill or Invoice). +#. Go to "Analytic Lines" notebook. +#. Click on "Split Line" button inside the line to open the wizard. +#. Create the lines setting the Analytic Account and Percentage of the amount. +#. The new lines will be created and displayed in notebook. + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Escodoo + +Contributors +~~~~~~~~~~~~ + +* `Escodoo `_: + + * Marcel Savegnago + * Wesley Oliveira + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/account-analytic `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/account_analytic_line_split/__init__.py b/account_analytic_line_split/__init__.py new file mode 100644 index 0000000000..9b4296142f --- /dev/null +++ b/account_analytic_line_split/__init__.py @@ -0,0 +1,2 @@ +from . import models +from . import wizard diff --git a/account_analytic_line_split/__manifest__.py b/account_analytic_line_split/__manifest__.py new file mode 100644 index 0000000000..4a5906623c --- /dev/null +++ b/account_analytic_line_split/__manifest__.py @@ -0,0 +1,19 @@ +# Copyright 2024 - TODAY, Escodoo +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +{ + "name": "Account Analytic Line Split", + "summary": """ + Account Analytic Line Split""", + "version": "14.0.1.0.0", + "license": "AGPL-3", + "author": "Escodoo, Odoo Community Association (OCA)", + "website": "https://github.com/OCA/account-analytic", + "depends": ["account", "analytic"], + "data": [ + "views/account_analytic_line.xml", + "views/account_move.xml", + "wizard/analytic_line_split_wizard.xml", + "security/ir.model.access.csv", + ], +} diff --git a/account_analytic_line_split/models/__init__.py b/account_analytic_line_split/models/__init__.py new file mode 100644 index 0000000000..8bc61027ea --- /dev/null +++ b/account_analytic_line_split/models/__init__.py @@ -0,0 +1,2 @@ +from . import account_analytic_line +from . import account_move diff --git a/account_analytic_line_split/models/account_analytic_line.py b/account_analytic_line_split/models/account_analytic_line.py new file mode 100644 index 0000000000..dbbc3c55cd --- /dev/null +++ b/account_analytic_line_split/models/account_analytic_line.py @@ -0,0 +1,43 @@ +# Copyright 2024 - TODAY, Wesley Oliveira +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class AccountAnalyticLine(models.Model): + _inherit = "account.analytic.line" + + parent_line_id = fields.Many2one( + comodel_name="account.analytic.line", + string="Origin", + ondelete="cascade", + readonly=True, + ) + child_line_ids = fields.One2many( + comodel_name="account.analytic.line", + inverse_name="parent_line_id", + string="Child Lines", + readonly=True, + ) + + def action_edit_analytic_line(self): + context = dict(self.env.context) + context["form_view_initial_mode"] = "edit" + action = self.env["ir.actions.act_window"]._for_xml_id( + "analytic.account_analytic_line_action_entries" + ) + action["context"] = context + action["views"] = [(False, "form")] + action["res_id"] = self.id + return action + + def action_split_analytic_line(self): + action = self.env["ir.actions.act_window"]._for_xml_id( + "account_analytic_line_split.analytic_line_split_wizard_action" + ) + action["context"] = { + "active_id": self.id, + "amount": self.amount, + "account_id": self.account_id.id, + } + return action diff --git a/account_analytic_line_split/models/account_move.py b/account_analytic_line_split/models/account_move.py new file mode 100644 index 0000000000..386647e2e6 --- /dev/null +++ b/account_analytic_line_split/models/account_move.py @@ -0,0 +1,19 @@ +# Copyright 2024 - TODAY, Wesley Oliveira +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models + + +class AccountMove(models.Model): + _inherit = "account.move" + + analytic_line_ids = fields.Many2many( + comodel_name="account.analytic.line", + string="Analytic Lines", + compute="_compute_analytic_line_ids", + ) + + @api.depends("line_ids.analytic_line_ids") + def _compute_analytic_line_ids(self): + for move in self: + move.analytic_line_ids = move.line_ids.mapped("analytic_line_ids") diff --git a/account_analytic_line_split/readme/CONTRIBUTORS.rst b/account_analytic_line_split/readme/CONTRIBUTORS.rst new file mode 100644 index 0000000000..9617554c22 --- /dev/null +++ b/account_analytic_line_split/readme/CONTRIBUTORS.rst @@ -0,0 +1,4 @@ +* `Escodoo `_: + + * Marcel Savegnago + * Wesley Oliveira diff --git a/account_analytic_line_split/readme/DESCRIPTION.rst b/account_analytic_line_split/readme/DESCRIPTION.rst new file mode 100644 index 0000000000..34b517836a --- /dev/null +++ b/account_analytic_line_split/readme/DESCRIPTION.rst @@ -0,0 +1 @@ +This module allows to split analytic lines in two or more lines. diff --git a/account_analytic_line_split/readme/USAGE.rst b/account_analytic_line_split/readme/USAGE.rst new file mode 100644 index 0000000000..b517c417a3 --- /dev/null +++ b/account_analytic_line_split/readme/USAGE.rst @@ -0,0 +1,15 @@ +To split an analytic line: + +#. Go to Invoicing > Configuration > Management > Analytic Items. +#. Open an Anlytic Entry. +#. Click on "Split Line" button to open the wizard. +#. Create the lines setting the Analytic Account and Percentage of the amount. +#. The new lines will be created and displayed in "Child Lines" notebook. + +To split an analytic line directly from the Account Move: + +#. Open one Account Move (a Journal Entry, Bill or Invoice). +#. Go to "Analytic Lines" notebook. +#. Click on "Split Line" button inside the line to open the wizard. +#. Create the lines setting the Analytic Account and Percentage of the amount. +#. The new lines will be created and displayed in notebook. diff --git a/account_analytic_line_split/security/ir.model.access.csv b/account_analytic_line_split/security/ir.model.access.csv new file mode 100644 index 0000000000..bc1f6c0957 --- /dev/null +++ b/account_analytic_line_split/security/ir.model.access.csv @@ -0,0 +1,3 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_analytic_line_split_wizard,analytic.line.split.wizard,model_analytic_line_split_wizard,analytic.group_analytic_accounting,1,1,1,1 +access_analytic_line_split,analytic.line.split,model_analytic_line_split,analytic.group_analytic_accounting,1,1,1,1 diff --git a/account_analytic_line_split/static/description/icon.png b/account_analytic_line_split/static/description/icon.png new file mode 100644 index 0000000000..3a0328b516 Binary files /dev/null and b/account_analytic_line_split/static/description/icon.png differ diff --git a/account_analytic_line_split/static/description/index.html b/account_analytic_line_split/static/description/index.html new file mode 100644 index 0000000000..fc1473216e --- /dev/null +++ b/account_analytic_line_split/static/description/index.html @@ -0,0 +1,447 @@ + + + + + +Account Analytic Line Split + + + +
+

Account Analytic Line Split

+ + +

Beta License: AGPL-3 OCA/account-analytic Translate me on Weblate Try me on Runboat

+

This module allows to split analytic lines in two or more lines.

+

Table of contents

+ +
+

Usage

+

To split an analytic line:

+
    +
  1. Go to Invoicing > Configuration > Management > Analytic Items.
  2. +
  3. Open an Anlytic Entry.
  4. +
  5. Click on “Split Line” button to open the wizard.
  6. +
  7. Create the lines setting the Analytic Account and Percentage of the amount.
  8. +
  9. The new lines will be created and displayed in “Child Lines” notebook.
  10. +
+

To split an analytic line directly from the Account Move:

+
    +
  1. Open one Account Move (a Journal Entry, Bill or Invoice).
  2. +
  3. Go to “Analytic Lines” notebook.
  4. +
  5. Click on “Split Line” button inside the line to open the wizard.
  6. +
  7. Create the lines setting the Analytic Account and Percentage of the amount.
  8. +
  9. The new lines will be created and displayed in notebook.
  10. +
+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Escodoo
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/account-analytic project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/account_analytic_line_split/tests/__init__.py b/account_analytic_line_split/tests/__init__.py new file mode 100644 index 0000000000..f145efd678 --- /dev/null +++ b/account_analytic_line_split/tests/__init__.py @@ -0,0 +1,3 @@ +from . import test_account_analytic_line +from . import test_account_move +from . import test_analytic_line_split_wizard diff --git a/account_analytic_line_split/tests/test_account_analytic_line.py b/account_analytic_line_split/tests/test_account_analytic_line.py new file mode 100644 index 0000000000..03cecd199b --- /dev/null +++ b/account_analytic_line_split/tests/test_account_analytic_line.py @@ -0,0 +1,34 @@ +# Copyright 2024 - TODAY, Wesley Oliveira +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo.tests.common import SavepointCase + + +class TestAccountAnalyticLine(SavepointCase): + @classmethod + def setUpClass(cls): + super(TestAccountAnalyticLine, cls).setUpClass() + + cls.analytic_account = cls.env["account.analytic.account"].create( + { + "name": "Test Analytic Account", + } + ) + cls.analytic_line = cls.env["account.analytic.line"].create( + { + "name": "Test Analytic Line", + "amount": 100, + "account_id": cls.analytic_account.id, + } + ) + + def test_action_edit_analytic_line(self): + action = self.analytic_line.action_edit_analytic_line() + self.assertEqual(action["res_id"], self.analytic_line.id) + self.assertEqual(action["views"], [(False, "form")]) + + def test_action_split_analytic_line(self): + action = self.analytic_line.action_split_analytic_line() + self.assertEqual(action["context"]["active_id"], self.analytic_line.id) + self.assertEqual(action["context"]["account_id"], self.analytic_account.id) + self.assertEqual(action["context"]["amount"], self.analytic_line.amount) diff --git a/account_analytic_line_split/tests/test_account_move.py b/account_analytic_line_split/tests/test_account_move.py new file mode 100644 index 0000000000..a518b33317 --- /dev/null +++ b/account_analytic_line_split/tests/test_account_move.py @@ -0,0 +1,72 @@ +# Copyright 2024 - TODAY, Wesley Oliveira +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo.tests.common import SavepointCase + + +class TestAccountMove(SavepointCase): + @classmethod + def setUpClass(cls): + super(TestAccountMove, cls).setUpClass() + + cls.account = cls.env["account.account"].create( + { + "code": "test_account_01", + "name": "test account", + "user_type_id": cls.env.ref("account.data_account_type_receivable").id, + "reconcile": True, + } + ) + cls.account_2 = cls.env["account.account"].create( + { + "code": "test_account_02", + "name": "test account 2", + "user_type_id": cls.env.ref("account.data_account_type_payable").id, + "reconcile": True, + } + ) + cls.analytic_account = cls.env["account.analytic.account"].create( + { + "name": "Test Analytic Account", + } + ) + cls.analytic_line = cls.env["account.analytic.line"].create( + { + "name": "Test Analytic Line", + "amount": 100, + "account_id": cls.analytic_account.id, + } + ) + cls.account_move = cls.env["account.move"].create( + { + "name": "Test Move", + "line_ids": [ + ( + 0, + 0, + { + "name": "Test Move Line", + "debit": 50, + "credit": 0, + "account_id": cls.account.id, + "analytic_account_id": cls.analytic_account.id, + "analytic_line_ids": [(6, 0, [cls.analytic_line.id])], + }, + ), + ( + 0, + 0, + { + "name": "Test Move Line", + "debit": 0, + "credit": 50, + "account_id": cls.account_2.id, + }, + ), + ], + } + ) + + def test_compute_analytic_line_ids(self): + self.account_move._compute_analytic_line_ids() + self.assertIn(self.analytic_line, self.account_move.analytic_line_ids) diff --git a/account_analytic_line_split/tests/test_analytic_line_split_wizard.py b/account_analytic_line_split/tests/test_analytic_line_split_wizard.py new file mode 100644 index 0000000000..69e4ba7113 --- /dev/null +++ b/account_analytic_line_split/tests/test_analytic_line_split_wizard.py @@ -0,0 +1,99 @@ +# Copyright 2024 - TODAY, Wesley Oliveira +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo.exceptions import ValidationError +from odoo.tests.common import SavepointCase + + +class TestAnalyticLineSplitWizard(SavepointCase): + @classmethod + def setUpClass(cls): + super(TestAnalyticLineSplitWizard, cls).setUpClass() + + cls.wizard_obj = cls.env["analytic.line.split.wizard"] + cls.split_obj = cls.env["analytic.line.split"] + cls.analytic_account = cls.env["account.analytic.account"].create( + { + "name": "Test Analytic Account", + } + ) + cls.analytic_line = cls.env["account.analytic.line"].create( + { + "name": "Test Analytic Line", + "amount": 100, + "account_id": cls.analytic_account.id, + } + ) + cls.wizard = cls.wizard_obj.with_context(active_id=cls.analytic_line.id).create( + { + "amount_total": 100, + } + ) + + def test_compute_percentage(self): + line_split = self.split_obj.create( + { + "wizard_id": self.wizard.id, + "account_id": self.analytic_account.id, + "percentage": 30, + } + ) + self.wizard._compute_percentage() + self.assertEqual(self.wizard.percentage, 70) + self.assertEqual(line_split.percentage, 30) + + def test_compute_amount(self): + line_split = self.split_obj.create( + { + "wizard_id": self.wizard.id, + "account_id": self.analytic_account.id, + "percentage": 30, + } + ) + self.wizard._compute_amount() + self.assertEqual(self.wizard.amount, 70) + self.assertEqual(line_split.amount, 30) + + def test_action_split_line(self): + line_split = self.split_obj.create( + { + "wizard_id": self.wizard.id, + "account_id": self.analytic_account.id, + "percentage": 30, + } + ) + self.wizard.action_split_line() + self.assertEqual(self.analytic_line.amount, 70) + self.assertEqual(line_split.amount, 30) + new_line = self.env["account.analytic.line"].search( + [("parent_line_id", "=", self.analytic_line.id)] + ) + self.assertIn(new_line, self.analytic_line.child_line_ids) + + def test_check_percentage(self): + with self.assertRaises(ValidationError): + self.split_obj.create( + { + "wizard_id": self.wizard.id, + "account_id": self.analytic_account.id, + "percentage": 110, + } + ) + + def test_onchange_analytic_line_split_ids(self): + with self.assertRaises(ValidationError): + self.split_obj.create( + { + "wizard_id": self.wizard.id, + "account_id": self.analytic_account.id, + "percentage": 50, + } + ) + self.split_obj.create( + { + "wizard_id": self.wizard.id, + "account_id": self.analytic_account.id, + "percentage": 60, + } + ) + self.wizard._onchange_analytic_line_split_ids() diff --git a/account_analytic_line_split/views/account_analytic_line.xml b/account_analytic_line_split/views/account_analytic_line.xml new file mode 100644 index 0000000000..c74dd7c33c --- /dev/null +++ b/account_analytic_line_split/views/account_analytic_line.xml @@ -0,0 +1,41 @@ + + + + + + account.analytic.line.form (in account_analytic_line_split) + account.analytic.line + + + +
+
+
+ + + + + + + + + + + +
+ +
diff --git a/account_analytic_line_split/views/account_move.xml b/account_analytic_line_split/views/account_move.xml new file mode 100644 index 0000000000..4288fa5292 --- /dev/null +++ b/account_analytic_line_split/views/account_move.xml @@ -0,0 +1,69 @@ + + + + + + account.move.form (in account_analytic_line_split) + account.move + + + + + + +