diff --git a/account_journal_display_type/__init__.py b/account_journal_display_type/__init__.py new file mode 100644 index 00000000..493e5c15 --- /dev/null +++ b/account_journal_display_type/__init__.py @@ -0,0 +1,4 @@ +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl). + +from . import models +from .hook import post_init_hook diff --git a/account_journal_display_type/__manifest__.py b/account_journal_display_type/__manifest__.py new file mode 100644 index 00000000..05b66309 --- /dev/null +++ b/account_journal_display_type/__manifest__.py @@ -0,0 +1,17 @@ +# Copyright 2024 Akretion (https://www.akretion.com). +# @author Matthieu SAISON +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +{ + "name": "Account Journal Display Type", + "summary": "Account Journal type for payment", + "version": "14.0.1.0.0", + "development_status": "Beta", + "category": "Accounting", + "website": "https://github.com/OCA/account-financial-tools", + "author": "Akretion, " "Odoo Community Association (OCA)", + "maintainers": ["matthieu_saison"], + "license": "AGPL-3", + "depends": ["account", "account_statement_completion_label_simple"], + "data": ["views/account_journal_view.xml"], + "post_init_hook": "post_init_hook", +} diff --git a/account_journal_display_type/hook.py b/account_journal_display_type/hook.py new file mode 100644 index 00000000..ec474072 --- /dev/null +++ b/account_journal_display_type/hook.py @@ -0,0 +1,8 @@ +from odoo import SUPERUSER_ID, api + + +def post_init_hook(cr, registry): + env = api.Environment(cr, SUPERUSER_ID, {}) + journal_ids = env["account.journal"].search([]) + for journal in journal_ids: + journal.display_type = journal.type diff --git a/account_journal_display_type/models/__init__.py b/account_journal_display_type/models/__init__.py new file mode 100644 index 00000000..2388e119 --- /dev/null +++ b/account_journal_display_type/models/__init__.py @@ -0,0 +1 @@ +from . import account_journal diff --git a/account_journal_display_type/models/account_journal.py b/account_journal_display_type/models/account_journal.py new file mode 100644 index 00000000..677ff2ba --- /dev/null +++ b/account_journal_display_type/models/account_journal.py @@ -0,0 +1,80 @@ +from odoo import api, fields, models + + +class AccountJournal(models.Model): + _inherit = "account.journal" + + display_type = fields.Selection( + [ + ("sale", "Sales"), + ("purchase", "Purchase"), + ("cash", "Cash"), + ("bank", "Bank"), + ("payment", "Payment"), + ("general", "Miscellaneous"), + ], + required=True, + help="Select 'Sale' for customer invoices journals.\n" + "Select 'Purchase' for vendor bills journals.\n" + "Select 'Cash' or 'Bank' for journals that are used in customer or vendor payments.\n" + "Select 'General' for miscellaneous operations journals.", + ) + type = fields.Selection(compute="_compute_type", store=True) + default_account_id = fields.Many2one( + comodel_name="account.account", + compute="_compute_default_account_id", + readonly=False, + store=True, + ) + payment_debit_account_id = fields.Many2one( + comodel_name="account.account", + compute="_compute_payment_account_id", + readonly=False, + store=True, + ) + payment_credit_account_id = fields.Many2one( + comodel_name="account.account", + compute="_compute_payment_account_id", + readonly=False, + store=True, + ) + + @api.depends("display_type") + def _compute_type(self): + for record in self: + if record.display_type == "payment": + record.type = "bank" + else: + record.type = record.display_type + + @api.depends("display_type", "payment_debit_account_id") + def _compute_default_account_id(self): + for record in self: + if record.display_type == "payment": + record.default_account_id = record.payment_debit_account_id + + @api.depends("display_type", "default_account_id") + def _compute_payment_account_id(self): + for record in self: + if record.type == "cash": + record.payment_debit_account_id = record.default_account_id + record.payment_credit_account_id = record.default_account_id + + @api.model + def _fill_missing_values(self, vals): + # _fill_missing_values automaticly create a account if not set, + # this code bypass this behavior + if vals.get("display_type") == "payment": + vals["default_account_id"] = True + elif vals.get("display_type") == "cash": + vals["payment_debit_account_id"] = True + vals["payment_credit_account_id"] = True + super()._fill_missing_values(vals) + if vals.get("display_type") == "payment": + vals.pop("default_account_id") + # allow journal creation if display_type not define + if not vals.get("display_type"): + vals["display_type"] = vals["type"] + elif vals.get("display_type") == "cash": + vals.pop("payment_debit_account_id") + vals.pop("payment_credit_account_id") diff --git a/account_journal_display_type/models/readme/CONTRIBUTOR.rst b/account_journal_display_type/models/readme/CONTRIBUTOR.rst new file mode 100644 index 00000000..812f8b2e --- /dev/null +++ b/account_journal_display_type/models/readme/CONTRIBUTOR.rst @@ -0,0 +1 @@ +* Matthieu Saison \ No newline at end of file diff --git a/account_journal_display_type/models/readme/DESCSRIPTION.rst b/account_journal_display_type/models/readme/DESCSRIPTION.rst new file mode 100644 index 00000000..521e44ef --- /dev/null +++ b/account_journal_display_type/models/readme/DESCSRIPTION.rst @@ -0,0 +1,8 @@ +This module introduce improvement on journal type to simplify configuration of Payment and Cash Journal. + + +The payment journal does not exist in odoo, it's associate to a bank journal but in payment case, +the default_account_id will have the same value as payment_debit_account_id. +This module introduce a new field type called display_type who hide the default type from UI, and make possible to had new journal type. Payment display_type is hadded here, and the associated legacy journal type is bank. The default_account_id is hided and will have the same value as payment_debit_account_id + +For Cash type, the only field we kept is default_account_id. The payment config tab is useless for a cash journal and was remove from UI. (in this case payment_debit_account_id and payment_credit_account_id are set with value of default_account_id) diff --git a/account_journal_display_type/tests/__init__.py b/account_journal_display_type/tests/__init__.py new file mode 100644 index 00000000..e18170d9 --- /dev/null +++ b/account_journal_display_type/tests/__init__.py @@ -0,0 +1 @@ +from . import test_journal_display_type diff --git a/account_journal_display_type/tests/test_journal_display_type.py b/account_journal_display_type/tests/test_journal_display_type.py new file mode 100644 index 00000000..cc120bf3 --- /dev/null +++ b/account_journal_display_type/tests/test_journal_display_type.py @@ -0,0 +1,81 @@ +from odoo.tests import SavepointCase +from odoo.tests.common import new_test_user, users + + +class TestJournalDisplayType(SavepointCase): + def setUp(self): + super().setUp() + + self.account = self.env["account.account"].create( + { + "name": "Test account", + "code": "TAC", + "user_type_id": self.env.ref("account.data_account_type_payable").id, + "reconcile": True, + } + ) + self.manager = new_test_user( + self.env, "test_manager", "account.group_account_manager" + ) + + @users("test_manager") + def test_journal_payment_with_account(self): + + journal = self.env["account.journal"].create( + { + "name": "Bank with account", + "display_type": "cash", + "type": "cash", + "code": "BK100", + "payment_debit_account_id": self.account.id, + "payment_credit_account_id": self.account.id, + } + ) + journal.display_type = "payment" + self.assertEqual(journal.type, "bank") + self.assertEqual(journal.default_account_id, journal.payment_debit_account_id) + + @users("test_manager") + def test_journal_payment_without_account(self): + + journal = self.env["account.journal"].create( + { + "name": "Bank without account", + "display_type": "payment", + "type": "bank", + "code": "BK101", + } + ) + self.assertTrue(journal.payment_debit_account_id) + self.assertTrue(journal.payment_credit_account_id) + self.assertEqual(journal.type, "bank") + self.assertEqual(journal.default_account_id, journal.payment_debit_account_id) + + @users("test_manager") + def test_journal_cash_with_account(self): + + journal = self.env["account.journal"].create( + { + "name": "Cash with account", + "display_type": "cash", + "type": "cash", + "code": "BK102", + "default_account_id": self.account.id, + } + ) + self.assertEqual(journal.type, "cash") + self.assertEqual(journal.default_account_id, self.account) + self.assertEqual(journal.default_account_id, journal.payment_debit_account_id) + self.assertEqual(journal.default_account_id, journal.payment_credit_account_id) + + @users("test_manager") + def test_journal_bank_without_account(self): + + journal = self.env["account.journal"].create( + { + "name": "Bank without account", + "type": "bank", + "code": "BK103", + } + ) + self.assertTrue(journal.payment_debit_account_id) diff --git a/account_journal_display_type/views/account_journal_view.xml b/account_journal_display_type/views/account_journal_view.xml new file mode 100644 index 00000000..8f45f650 --- /dev/null +++ b/account_journal_display_type/views/account_journal_view.xml @@ -0,0 +1,74 @@ + + + + + account.journal + + 1 + + + {'invisible': True} + + + + + + + + {'required': [ ('type', '=', 'bank'), ('display_type', '=', 'bank')], 'invisible': [('display_type', '!=', 'bank')]} + + + + + {'required': [('type', '=', 'cash')], 'invisible': [('type', '!=', 'cash')]} + + + + + + {'required': [('display_type', 'in', ('bank', 'cash'))], 'invisible': [('display_type', 'not in', ('bank', 'cash'))]} + + + + + {'invisible': ['|', ('type', '!=', 'bank'), ('display_type', '=', 'payment') ]} + + + + + {'required': [('type', 'in', ('bank', 'cash'))], 'invisible': [('type', 'not in', ('bank', 'cash'))]} + + + + + {'required': [('type', 'in', ('bank', 'cash'))], 'invisible': [('type', 'not in', ('bank', 'cash'))]} + + + + + {'invisible': [('type', 'in', ['sale', 'purchase', 'general','cash'])]} + + + + + + +