diff --git a/sync_multi_company_bank_account/README.rst b/sync_multi_company_bank_account/README.rst new file mode 100644 index 0000000..e5cca64 --- /dev/null +++ b/sync_multi_company_bank_account/README.rst @@ -0,0 +1,76 @@ +.. image:: https://odoo-community.org/readme-banner-image + :target: https://odoo-community.org/get-involved?utm_source=readme + :alt: Odoo Community Association + +=============================== +Sync Multi Company Bank Account +=============================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:2cb1117e7eeae500370f540a90494e7d195242b9492ae0ffc2f344857e97e33a + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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/license-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-Escodoo%2Faccount--addons-lightgray.png?logo=github + :target: https://github.com/Escodoo/account-addons/tree/16.0/sync_multi_company_bank_account + :alt: Escodoo/account-addons + +|badge1| |badge2| |badge3| + +The Multi-Company Bank Account Synchronization module aims to ensure that all companies within a business group have the same bank accounts registered and updated, so that all of them can carry out financial transactions without data compatibility issues. + +The synchronization is performed automatically, so that the addition, update or deletion of a bank account in one of the companies is reflected in all other companies of the group. To ensure data integrity, the module also checks whether the bank account can be deleted without compromising the integrity of the records in other companies. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +To use the Multi-Company Bank Account Synchronization module, follow these steps: + +Install the module in your Odoo system. + +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 + * Cristiano Mafra Junior + +Maintainers +~~~~~~~~~~~ + +This module is part of the `Escodoo/account-addons `_ project on GitHub. + +You are welcome to contribute. diff --git a/sync_multi_company_bank_account/__init__.py b/sync_multi_company_bank_account/__init__.py new file mode 100644 index 0000000..cc6b635 --- /dev/null +++ b/sync_multi_company_bank_account/__init__.py @@ -0,0 +1,2 @@ +from . import models +from .hooks import post_init_hook diff --git a/sync_multi_company_bank_account/__manifest__.py b/sync_multi_company_bank_account/__manifest__.py new file mode 100644 index 0000000..a4c1cab --- /dev/null +++ b/sync_multi_company_bank_account/__manifest__.py @@ -0,0 +1,16 @@ +# Copyright 2023 - TODAY, Escodoo +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +{ + "name": "Sync Multi Company Bank Account", + "summary": """ + Sync Multi Company Bank Accounts""", + "version": "16.0.1.0.0", + "license": "AGPL-3", + "author": "Escodoo", + "website": "https://github.com/Escodoo/account-addons", + "depends": ["base"], + "data": [], + "demo": [], + "post_init_hook": "post_init_hook", +} diff --git a/sync_multi_company_bank_account/hooks.py b/sync_multi_company_bank_account/hooks.py new file mode 100644 index 0000000..8f040b3 --- /dev/null +++ b/sync_multi_company_bank_account/hooks.py @@ -0,0 +1,25 @@ +# Copyright 2023 - TODAY, Marcel Savegnago +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import SUPERUSER_ID, api + + +def post_init_hook(cr, registry): + env = api.Environment(cr, SUPERUSER_ID, {}) + cr.execute("SELECT * FROM res_partner_bank") + res_partner_bank = [] + res_partner_bank = cr.dictfetchall() + if res_partner_bank: + bank_accounts = env["res.partner.bank"] + companies = env["res.company"].search([]) + for company in companies: + bank_accounts |= company.bank_ids + for bank_account in bank_accounts: + for company in companies: + if company.id != bank_account.company_id.id: + if bank_account.acc_number not in company.bank_ids.mapped( + "acc_number" + ): + bank_account.sudo().with_context( + no_sync_partner_bank=True + ).copy({"company_id": company.id}) diff --git a/sync_multi_company_bank_account/i18n/sync_multi_company_bank_account.pot b/sync_multi_company_bank_account/i18n/sync_multi_company_bank_account.pot new file mode 100644 index 0000000..97eda2f --- /dev/null +++ b/sync_multi_company_bank_account/i18n/sync_multi_company_bank_account.pot @@ -0,0 +1,24 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * sync_multi_company_bank_account +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 15.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: sync_multi_company_bank_account +#: model:ir.model,name:sync_multi_company_bank_account.model_res_partner_bank +msgid "Bank Accounts" +msgstr "" + +#. module: sync_multi_company_bank_account +#: model:ir.model,name:sync_multi_company_bank_account.model_res_company +msgid "Companies" +msgstr "" diff --git a/sync_multi_company_bank_account/models/__init__.py b/sync_multi_company_bank_account/models/__init__.py new file mode 100644 index 0000000..7e68b8a --- /dev/null +++ b/sync_multi_company_bank_account/models/__init__.py @@ -0,0 +1,2 @@ +from . import res_partner_bank +from . import res_company diff --git a/sync_multi_company_bank_account/models/res_company.py b/sync_multi_company_bank_account/models/res_company.py new file mode 100644 index 0000000..d5be731 --- /dev/null +++ b/sync_multi_company_bank_account/models/res_company.py @@ -0,0 +1,45 @@ +# Copyright 2023 - TODAY, Marcel Savegnago +# Copyright 2025 - TODAY, Cristiano Mafra Junior +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import api, models + + +class ResCompany(models.Model): + _inherit = "res.company" + + def copy_bank_accounts(self): + oldest_company = self.search([], order="create_date").filtered( + lambda c: c.id != self.id + )[:1] + if not oldest_company: + return + + bank_accounts = self.env["res.partner.bank"].search( + [ + ("company_id", "=", oldest_company.id), + ] + ) + + for bank_account in bank_accounts: + dst_partner = self.partner_id + existing = self.env["res.partner.bank"].search( + [ + ("partner_id", "=", dst_partner.id), + ("sanitized_acc_number", "=", bank_account.sanitized_acc_number), + ], + limit=1, + ) + if not existing: + bank_account.sudo().with_context(no_sync_partner_bank=True).copy( + default={ + "company_id": self.id, + "partner_id": dst_partner.id, + } + ) + + @api.model + def create(self, vals): + company = super().create(vals) + company.copy_bank_accounts() + return company diff --git a/sync_multi_company_bank_account/models/res_partner_bank.py b/sync_multi_company_bank_account/models/res_partner_bank.py new file mode 100644 index 0000000..70f28f1 --- /dev/null +++ b/sync_multi_company_bank_account/models/res_partner_bank.py @@ -0,0 +1,73 @@ +# Copyright 2023 - TODAY, Marcel Savegnago +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl). + +from odoo import api, models + + +class ResPartnerBank(models.Model): + _inherit = "res.partner.bank" + + @api.model + def create(self, vals): + res = super().create(vals) + if not self.env.context.get("no_sync_partner_bank"): + res.sudo()._sync_partner_bank(vals) + return res + + def write(self, vals): + old_acc_number = self.acc_number + old_partner_id = self.partner_id.id + res = super().write(vals) + if not self.env.context.get("no_sync_partner_bank"): + self.sudo()._sync_partner_bank(vals, old_acc_number, old_partner_id) + return res + + def unlink(self): + if not self.env.context.get("no_sync_partner_bank_check_unlink"): + for bank in self: + for company in self.env["res.company"].search([]): + if company.id != bank.company_id.id: + dst_partner = company.partner_id + partner_bank = self.env["res.partner.bank"].search( + [ + ("partner_id", "=", dst_partner.id), + ( + "sanitized_acc_number", + "=", + bank.sanitized_acc_number, + ), + ], + limit=1, + ) + if partner_bank: + partner_bank.sudo().with_context( + no_sync_partner_bank_check_unlink=True + ).unlink() + return super().unlink() + + def _sync_partner_bank(self, vals, old_acc_number=None, old_partner_id=None): + for rec in self: + for company in self.env["res.company"].search([]): + if company.id != rec.company_id.id: + dst_partner = company.partner_id + + partner_bank = self.env["res.partner.bank"].search( + [ + ("partner_id", "=", dst_partner.id), + ( + "sanitized_acc_number", + "=", + rec.sanitized_acc_number, + ), + ], + limit=1, + ) + if partner_bank: + partner_bank.with_context(no_sync_partner_bank=True).write(vals) + else: + rec.sudo().with_context(no_sync_partner_bank=True).copy( + { + "company_id": company.id, + "partner_id": dst_partner.id, + } + ) diff --git a/sync_multi_company_bank_account/pyproject.toml b/sync_multi_company_bank_account/pyproject.toml new file mode 100644 index 0000000..4231d0c --- /dev/null +++ b/sync_multi_company_bank_account/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/sync_multi_company_bank_account/readme/CONTRIBUTORS.rst b/sync_multi_company_bank_account/readme/CONTRIBUTORS.rst new file mode 100644 index 0000000..d812cd8 --- /dev/null +++ b/sync_multi_company_bank_account/readme/CONTRIBUTORS.rst @@ -0,0 +1,4 @@ +* `Escodoo `_: + + * Marcel Savegnago + * Cristiano Mafra Junior diff --git a/sync_multi_company_bank_account/readme/DESCRIPTION.rst b/sync_multi_company_bank_account/readme/DESCRIPTION.rst new file mode 100644 index 0000000..6d003f6 --- /dev/null +++ b/sync_multi_company_bank_account/readme/DESCRIPTION.rst @@ -0,0 +1,3 @@ +The Multi-Company Bank Account Synchronization module aims to ensure that all companies within a business group have the same bank accounts registered and updated, so that all of them can carry out financial transactions without data compatibility issues. + +The synchronization is performed automatically, so that the addition, update or deletion of a bank account in one of the companies is reflected in all other companies of the group. To ensure data integrity, the module also checks whether the bank account can be deleted without compromising the integrity of the records in other companies. diff --git a/sync_multi_company_bank_account/readme/USAGE.rst b/sync_multi_company_bank_account/readme/USAGE.rst new file mode 100644 index 0000000..2b4d222 --- /dev/null +++ b/sync_multi_company_bank_account/readme/USAGE.rst @@ -0,0 +1,3 @@ +To use the Multi-Company Bank Account Synchronization module, follow these steps: + +Install the module in your Odoo system. diff --git a/sync_multi_company_bank_account/static/description/icon.png b/sync_multi_company_bank_account/static/description/icon.png new file mode 100644 index 0000000..12ab005 Binary files /dev/null and b/sync_multi_company_bank_account/static/description/icon.png differ diff --git a/sync_multi_company_bank_account/static/description/index.html b/sync_multi_company_bank_account/static/description/index.html new file mode 100644 index 0000000..fb4a311 --- /dev/null +++ b/sync_multi_company_bank_account/static/description/index.html @@ -0,0 +1,430 @@ + + + + + +README.rst + + + +
+ + +Odoo Community Association +
+

Sync Multi Company Bank Account

+ +

Beta License: AGPL-3 Escodoo/account-addons

+

The Multi-Company Bank Account Synchronization module aims to ensure that all companies within a business group have the same bank accounts registered and updated, so that all of them can carry out financial transactions without data compatibility issues.

+

The synchronization is performed automatically, so that the addition, update or deletion of a bank account in one of the companies is reflected in all other companies of the group. To ensure data integrity, the module also checks whether the bank account can be deleted without compromising the integrity of the records in other companies.

+

Table of contents

+ +
+

Usage

+

To use the Multi-Company Bank Account Synchronization module, follow these steps:

+

Install the module in your Odoo system.

+
+
+

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 part of the Escodoo/account-addons project on GitHub.

+

You are welcome to contribute.

+
+
+
+
+ + diff --git a/sync_multi_company_bank_account/tests/__init__.py b/sync_multi_company_bank_account/tests/__init__.py new file mode 100644 index 0000000..9a23be1 --- /dev/null +++ b/sync_multi_company_bank_account/tests/__init__.py @@ -0,0 +1 @@ +from . import test_res_partner_bank diff --git a/sync_multi_company_bank_account/tests/test_res_partner_bank.py b/sync_multi_company_bank_account/tests/test_res_partner_bank.py new file mode 100644 index 0000000..0f75584 --- /dev/null +++ b/sync_multi_company_bank_account/tests/test_res_partner_bank.py @@ -0,0 +1,90 @@ +# Copyright 2023 - TODAY, Marcel Savegnago +# Copyright 2025 - TODAY, Cristiano Mafra Junior +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo.tests.common import TransactionCase + + +class TestResPartnerBank(TransactionCase): + @classmethod + def setUpClass(cls, *args, **kwargs): + super().setUpClass(*args, **kwargs) + cls.partner = cls.env["res.partner"].create( + { + "name": "Test Partner", + } + ) + cls.company1 = cls.env["res.company"].create( + { + "name": "Test Company 1", + } + ) + cls.company2 = cls.env["res.company"].create( + { + "name": "Test Company 2", + } + ) + + def test_copy_bank_accounts(self): + self.env["res.partner.bank"].create( + { + "acc_number": "123456789", + "partner_id": self.company1.partner_id.id, + "company_id": self.company1.id, + } + ) + + company1_bank = self.env["res.partner.bank"].search( + [ + ("partner_id", "=", self.company1.partner_id.id), + ("acc_number", "=", "123456789"), + ] + ) + company2_bank = self.env["res.partner.bank"].search( + [ + ("partner_id", "=", self.company2.partner_id.id), + ("acc_number", "=", "123456789"), + ] + ) + + self.assertEqual(len(company1_bank), 1) + self.assertEqual(len(company2_bank), 1) + + def test_create_no_sync_partner_bank(self): + bank = self.env["res.partner.bank"].create( + { + "acc_number": "987654321", + "partner_id": self.company1.partner_id.id, + "company_id": self.company1.id, + } + ) + + company2_bank = self.env["res.partner.bank"].search( + [ + ("partner_id", "=", self.company2.partner_id.id), + ("acc_number", "=", bank.acc_number), + ], + limit=1, + ) + + self.assertEqual(company2_bank.acc_number, "987654321") + + def test_write_sync_partner_bank(self): + bank = self.env["res.partner.bank"].create( + { + "acc_number": "433322244", + "partner_id": self.company1.partner_id.id, + "company_id": self.company1.id, + } + ) + bank.write({"acc_number": "888444333"}) + + company2_bank = self.env["res.partner.bank"].search( + [ + ("partner_id", "=", self.company2.partner_id.id), + ("acc_number", "=", "888444333"), + ], + limit=1, + ) + + self.assertEqual(company2_bank.acc_number, "888444333")