diff --git a/account_move_line_drilldown/README.rst b/account_move_line_drilldown/README.rst new file mode 100644 index 000000000..335e62c1b --- /dev/null +++ b/account_move_line_drilldown/README.rst @@ -0,0 +1,112 @@ +====================== +Journal Item Drilldown +====================== + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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--financial--tools-lightgray.png?logo=github + :target: https://github.com/OCA/account-financial-tools/tree/12.0/account_move_line_drilldown + :alt: OCA/account-financial-tools +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/account-financial-tools-12-0/account-financial-tools-12-0-account_move_line_drilldown + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/92/12.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module allows the Billing Manager to navigate the amounts in the chart +of accounts across the first two levels of the account group hierarchy plus +the account level. + +**Table of contents** + +.. contents:: + :local: + +Installation +============ + +To allow the user to browse through the first two levels of the chart of account +codes, this module adds two dedicated columns to the journal item table to +store top level, and the top - 1 level of the account group hierarchy that the +journal item belongs to. The columns are populated automatically during the +installation of the module. The installation will take about 2 minutes for every +million move lines in your database. + +Configuration +============= + +In order to enable the pseudohierachy that this module exposes in its move +line pivot view, you need to configure the account group on all accounts in +your chart of accounts. + +Usage +===== + +Go to Invoicing -> Reporting -> Management -> Journal Item Drilldown to browse +journal items across the first two levels of the account group hierarchy plus +the account level. + +By default, you will get a pivot view with the three levels expanded: + + .. figure:: https://raw.githubusercontent.com/OCA/account-financial-tools/12.0/account_move_line_drilldown/static/description/drilldown_pivot.png + :scale: 80 % + :alt: journal Item Drilldown pivot view + +The three levels are: the top level of the account.group hierarchy, +the top - 1 level of the account.group hierarchy, and the account +itself. You can easily collapse a level by deselecting them in the `Group By` +dropdown in the search bar. + +You can also browse the journal items by switching to the tree view and click +through the grouping levels in that view. + + .. figure:: https://raw.githubusercontent.com/OCA/account-financial-tools/12.0/account_move_line_drilldown/static/description/drilldown_tree.png + :scale: 80 % + :alt: journal Item Drilldown tree view + +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 smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Opener B.V. + +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-financial-tools `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/account_move_line_drilldown/__init__.py b/account_move_line_drilldown/__init__.py new file mode 100644 index 000000000..d6f861de9 --- /dev/null +++ b/account_move_line_drilldown/__init__.py @@ -0,0 +1,2 @@ +from .hooks import post_init_hook, pre_init_hook +from . import models diff --git a/account_move_line_drilldown/__manifest__.py b/account_move_line_drilldown/__manifest__.py new file mode 100644 index 000000000..d3b45b5b5 --- /dev/null +++ b/account_move_line_drilldown/__manifest__.py @@ -0,0 +1,21 @@ +# Copyright 2021 Opener B.V. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +{ + "name": "Journal Item Drilldown", + "version": "12.0.1.0.0", + "category": "Accounting", + "license": "AGPL-3", + "summary": "Group journal items by the first 2 account group levels", + "author": "Opener B.V., Odoo Community Association (OCA)", + "website": "https://github.com/OCA/account-financial-tools", + "depends": [ + "account", + ], + "data": [ + "views/account_move_line_view.xml", + ], + "post_init_hook": "post_init_hook", + "pre_init_hook": "pre_init_hook", + "installable": True, +} diff --git a/account_move_line_drilldown/hooks.py b/account_move_line_drilldown/hooks.py new file mode 100644 index 000000000..cd6050e65 --- /dev/null +++ b/account_move_line_drilldown/hooks.py @@ -0,0 +1,26 @@ +# Copyright 2021 Opener B.V. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from odoo import api, SUPERUSER_ID + + +def pre_init_hook(cr): + """Prevent the compute method from kicking in. + + Population of the columns is triggered in the post_init_hook + """ + cr.execute( + """ + alter table account_account + add column if not exists root_group_id INTEGER, + add column if not exists sub_group_id INTEGER; + alter table account_move_line + add column if not exists account_root_group_id INTEGER, + add column if not exists account_sub_group_id INTEGER; + """) + + +def post_init_hook(cr, registry): + """Populate the columns created in the pre-init-hook + """ + env = api.Environment(cr, SUPERUSER_ID, {}) + env["account.group"]._account_groups_compute() diff --git a/account_move_line_drilldown/models/__init__.py b/account_move_line_drilldown/models/__init__.py new file mode 100644 index 000000000..9c22c4179 --- /dev/null +++ b/account_move_line_drilldown/models/__init__.py @@ -0,0 +1,3 @@ +from . import account_account +from . import account_group +from . import account_move_line diff --git a/account_move_line_drilldown/models/account_account.py b/account_move_line_drilldown/models/account_account.py new file mode 100644 index 000000000..b045841fb --- /dev/null +++ b/account_move_line_drilldown/models/account_account.py @@ -0,0 +1,28 @@ +# Copyright 2021 Opener B.V. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from odoo import api, fields, models + + +class AccountAccount(models.Model): + _inherit = "account.account" + + root_group_id = fields.Many2one( + comodel_name="account.group", string="Root Group", + compute="_compute_account_groups", index=True, store=True) + sub_group_id = fields.Many2one( + comodel_name="account.group", string="Sub Group", + compute="_compute_account_groups", index=True, store=True) + + @api.depends("group_id") + def _compute_account_groups(self): + """Provide the root and sub group for each account""" + if not self.ids: + return + for account in self: + sub_group = self.env["account.group"] + root_group = account.group_id + while root_group.parent_id: + sub_group = root_group + root_group = sub_group.parent_id + account.root_group_id = root_group + account.sub_group_id = sub_group diff --git a/account_move_line_drilldown/models/account_group.py b/account_move_line_drilldown/models/account_group.py new file mode 100644 index 000000000..80c5bc725 --- /dev/null +++ b/account_move_line_drilldown/models/account_group.py @@ -0,0 +1,79 @@ +# Copyright 2021 Opener B.V. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +import logging +from odoo import models + + +class AccountGroup(models.Model): + _inherit = "account.group" + + def _parent_store_update(self): + """Propagated the updated parent structure to accounts and move lines + """ + res = super()._parent_store_update() + if self: + self._account_groups_compute() + return res + + def _account_groups_compute(self): + """Set root and sub groups on accounts and move lines. + + Can be called on a recordset of account.group or with an empty `self` + to apply on all accounts with a group_id set. + + Only rewrite the move lines of the updated accounts, and take care + not to select accounts that already have the current values set. + """ + self.env.cr.execute( + """ + WITH vals AS ( + SELECT aa.id, + CAST(split_part(ag.parent_path, '/', 1) AS INTEGER) + as root_group_id, + CASE + WHEN length(split_part(parent_path, '/', 2)) > 0 + THEN CAST(split_part(parent_path, '/', 2) AS INTEGER) + ELSE NULL END AS sub_group_id + FROM account_account aa + JOIN account_group ag ON ag.id = aa.group_id + """ + (" WHERE ag.id IN %s " if self.ids else "") + + """ + ) + UPDATE account_account aa + SET root_group_id = vals.root_group_id, + sub_group_id = vals.sub_group_id + FROM vals + WHERE aa.id = vals.id + AND ( + COALESCE(aa.root_group_id, 0) != + COALESCE(vals.root_group_id, 0) + OR + COALESCE(aa.sub_group_id, 0) != + COALESCE(vals.sub_group_id, 0) + ) + RETURNING aa.id; + """, + (tuple(self.ids),) if self.ids else ()) + account_ids = [account_id for account_id, in self.env.cr.fetchall()] + if not account_ids: + return + logging.getLogger(__name__).debug( + "Recomputing the root and sub groups of all move lines of %s " + "account(s).", len(account_ids)) + self.env.cr.execute( + """ + UPDATE account_move_line aml + SET account_root_group_id = aa.root_group_id, + account_sub_group_id = aa.sub_group_id + FROM account_account aa + WHERE aml.account_id = aa.id + AND aa.id IN %s + """, (tuple(account_ids),)) + self.env.cache.invalidate([ + (self.env["account.account"]._fields['root_group_id'], None), + (self.env["account.account"]._fields['sub_group_id'], None), + (self.env["account.move.line"]._fields['account_root_group_id'], + None), + (self.env["account.move.line"]._fields['account_sub_group_id'], + None), + ]) diff --git a/account_move_line_drilldown/models/account_move_line.py b/account_move_line_drilldown/models/account_move_line.py new file mode 100644 index 000000000..b8d37ca38 --- /dev/null +++ b/account_move_line_drilldown/models/account_move_line.py @@ -0,0 +1,16 @@ +# Copyright 2021 Opener B.V. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from odoo import fields, models + + +class AccountMoveLine(models.Model): + _inherit = "account.move.line" + + account_root_group_id = fields.Many2one( + comodel_name="account.group", string="Account Root Group", + related="account_id.root_group_id", + index=True, readonly=True, store=True) + account_sub_group_id = fields.Many2one( + comodel_name="account.group", string="Account Sub Group", + related="account_id.sub_group_id", + index=True, readonly=True, store=True) diff --git a/account_move_line_drilldown/readme/CONFIGURE.rst b/account_move_line_drilldown/readme/CONFIGURE.rst new file mode 100644 index 000000000..18c8272b9 --- /dev/null +++ b/account_move_line_drilldown/readme/CONFIGURE.rst @@ -0,0 +1,3 @@ +In order to enable the pseudohierachy that this module exposes in its move +line pivot view, you need to configure the account group on all accounts in +your chart of accounts. diff --git a/account_move_line_drilldown/readme/CONTRIBUTORS.readme b/account_move_line_drilldown/readme/CONTRIBUTORS.readme new file mode 100644 index 000000000..3a29acd03 --- /dev/null +++ b/account_move_line_drilldown/readme/CONTRIBUTORS.readme @@ -0,0 +1 @@ +* Stefan Rijnhart diff --git a/account_move_line_drilldown/readme/DESCRIPTION.rst b/account_move_line_drilldown/readme/DESCRIPTION.rst new file mode 100644 index 000000000..da24b97e9 --- /dev/null +++ b/account_move_line_drilldown/readme/DESCRIPTION.rst @@ -0,0 +1,3 @@ +This module allows the Billing Manager to navigate the amounts in the chart +of accounts across the first two levels of the account group hierarchy plus +the account level. diff --git a/account_move_line_drilldown/readme/INSTALL.rst b/account_move_line_drilldown/readme/INSTALL.rst new file mode 100644 index 000000000..ef3d62e7b --- /dev/null +++ b/account_move_line_drilldown/readme/INSTALL.rst @@ -0,0 +1,6 @@ +To allow the user to browse through the first two levels of the chart of account +codes, this module adds two dedicated columns to the journal item table to +store top level, and the top - 1 level of the account group hierarchy that the +journal item belongs to. The columns are populated automatically during the +installation of the module. The installation will take about 2 minutes for every +million move lines in your database. diff --git a/account_move_line_drilldown/readme/USAGE.rst b/account_move_line_drilldown/readme/USAGE.rst new file mode 100644 index 000000000..8b655654d --- /dev/null +++ b/account_move_line_drilldown/readme/USAGE.rst @@ -0,0 +1,21 @@ +Go to Invoicing -> Reporting -> Management -> Journal Item Drilldown to browse +journal items across the first two levels of the account group hierarchy plus +the account level. + +By default, you will get a pivot view with the three levels expanded: + + .. figure:: https://raw.githubusercontent.com/OCA/account-financial-tools/12.0/account_move_line_drilldown/static/description/drilldown_pivot.png + :scale: 80 % + :alt: journal Item Drilldown pivot view + +The three levels are: the top level of the account.group hierarchy, +the top - 1 level of the account.group hierarchy, and the account +itself. You can easily collapse a level by deselecting them in the `Group By` +dropdown in the search bar. + +You can also browse the journal items by switching to the tree view and click +through the grouping levels in that view. + + .. figure:: https://raw.githubusercontent.com/OCA/account-financial-tools/12.0/account_move_line_drilldown/static/description/drilldown_tree.png + :scale: 80 % + :alt: journal Item Drilldown tree view diff --git a/account_move_line_drilldown/static/description/drilldown_pivot.png b/account_move_line_drilldown/static/description/drilldown_pivot.png new file mode 100644 index 000000000..e47f9e79f Binary files /dev/null and b/account_move_line_drilldown/static/description/drilldown_pivot.png differ diff --git a/account_move_line_drilldown/static/description/drilldown_tree.png b/account_move_line_drilldown/static/description/drilldown_tree.png new file mode 100644 index 000000000..6c88daea6 Binary files /dev/null and b/account_move_line_drilldown/static/description/drilldown_tree.png differ diff --git a/account_move_line_drilldown/static/description/index.html b/account_move_line_drilldown/static/description/index.html new file mode 100644 index 000000000..2e2e77a3a --- /dev/null +++ b/account_move_line_drilldown/static/description/index.html @@ -0,0 +1,455 @@ + + + + + + +Journal Item Drilldown + + + +
+

Journal Item Drilldown

+ + +

Beta License: AGPL-3 OCA/account-financial-tools Translate me on Weblate Try me on Runbot

+

This module allows the Billing Manager to navigate the amounts in the chart +of accounts across the first two levels of the account group hierarchy plus +the account level.

+

Table of contents

+ +
+

Installation

+

To allow the user to browse through the first two levels of the chart of account +codes, this module adds two dedicated columns to the journal item table to +store top level, and the top - 1 level of the account group hierarchy that the +journal item belongs to. The columns are populated automatically during the +installation of the module. The installation will take about 2 minutes for every +million move lines in your database.

+
+
+

Configuration

+

In order to enable the pseudohierachy that this module exposes in its move +line pivot view, you need to configure the account group on all accounts in +your chart of accounts.

+
+
+

Usage

+

Go to Invoicing -> Reporting -> Management -> Journal Item Drilldown to browse +journal items across the first two levels of the account group hierarchy plus +the account level.

+

By default, you will get a pivot view with the three levels expanded:

+
+
+journal Item Drilldown pivot view +
+
+

The three levels are: the top level of the account.group hierarchy, +the top - 1 level of the account.group hierarchy, and the account +itself. You can easily collapse a level by deselecting them in the Group By +dropdown in the search bar.

+

You can also browse the journal items by switching to the tree view and click +through the grouping levels in that view.

+
+
+journal Item Drilldown tree view +
+
+
+
+

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 smashing it by providing a detailed and welcomed +feedback.

+

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

+
+
+

Credits

+
+

Authors

+
    +
  • Opener B.V.
  • +
+
+
+

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-financial-tools project on GitHub.

+

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

+
+
+
+ + diff --git a/account_move_line_drilldown/tests/__init__.py b/account_move_line_drilldown/tests/__init__.py new file mode 100644 index 000000000..0800cbe8d --- /dev/null +++ b/account_move_line_drilldown/tests/__init__.py @@ -0,0 +1 @@ +from . import test_account_move_line_drilldown diff --git a/account_move_line_drilldown/tests/test_account_move_line_drilldown.py b/account_move_line_drilldown/tests/test_account_move_line_drilldown.py new file mode 100644 index 000000000..72e6bd2c1 --- /dev/null +++ b/account_move_line_drilldown/tests/test_account_move_line_drilldown.py @@ -0,0 +1,78 @@ +# Copyright 2021 Opener B.V. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from odoo.tests.common import SavepointCase, tagged + + +@tagged('post_install', '-at_install') +class TestAccountMoveLineDrilldown(SavepointCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.journal = cls.env["account.journal"].search( + [("company_id", "=", cls.env.user.company_id.id)], limit=1) + cls.accounts = cls.env["account.account"].search( + [("company_id", "=", cls.env.user.company_id.id)], limit=3) + cls.group1 = cls.env["account.group"].create({ + "name": "1", + "code_prefix": "1", + }) + cls.group12 = cls.env["account.group"].create({ + "name": "12", + "code_prefix": "12", + "parent_id": cls.group1.id, + }) + cls.group123 = cls.env["account.group"].create({ + "name": "123", + "code_prefix": "123", + "parent_id": cls.group12.id, + }) + cls.group124 = cls.env["account.group"].create({ + "name": "124", + "code_prefix": "124", + "parent_id": cls.group12.id, + }) + cls.group15 = cls.env["account.group"].create({ + "name": "15", + "code_prefix": "15", + "parent_id": cls.group1.id, + }) + cls.group156 = cls.env["account.group"].create({ + "name": "156", + "code_prefix": "156", + "parent_id": cls.group15.id, + }) + + def test_account_move_line_drilldown(self): + """Fields from this module are computed as expected""" + move = self.env['account.move'].create({ + 'journal_id': self.journal.id, + 'line_ids': [ + (0, 0, {'debit': 100.0, 'account_id': self.accounts[0].id}), + (0, 0, {'credit': 100.0, 'account_id': self.accounts[1].id}), + ], + }) + move_line = move.line_ids[0] + account = move_line.account_id + account.group_id = self.group123 + self.assertEqual(move_line.account_root_group_id, self.group1) + self.assertEqual(move_line.account_sub_group_id, self.group12) + + account.group_id = self.group12 + self.assertEqual(move_line.account_root_group_id, self.group1) + self.assertEqual(move_line.account_sub_group_id, self.group12) + + account.group_id = self.group1 + self.assertEqual(move_line.account_root_group_id, self.group1) + self.assertFalse(move_line.account_sub_group_id) + + account.group_id = self.group156 + self.assertEqual(move_line.account_root_group_id, self.group1) + self.assertEqual(move_line.account_sub_group_id, self.group15) + + self.group156.parent_id = self.group123 + self.assertEqual(move_line.account_root_group_id, self.group1) + self.assertEqual(move_line.account_sub_group_id, self.group12) + + self.group156.parent_id = False + self.assertEqual(move_line.account_root_group_id, self.group156) + self.assertFalse(move_line.account_sub_group_id) diff --git a/account_move_line_drilldown/views/account_move_line_view.xml b/account_move_line_drilldown/views/account_move_line_view.xml new file mode 100644 index 000000000..b0f70039e --- /dev/null +++ b/account_move_line_drilldown/views/account_move_line_view.xml @@ -0,0 +1,30 @@ + + + + + account.move.line + + + + + + + + + Journal Item Drilldown + account.move.line + pivot,tree,form + { + "search_default_group_by_account_root_group_id": 1, + "search_default_group_by_account_sub_group_id": 1, + "search_default_account": 1, + } + + +