From be09003c2a3155ab6544e1da025d006261d01705 Mon Sep 17 00:00:00 2001 From: Holger Brunn Date: Wed, 22 Jan 2025 17:03:06 +0100 Subject: [PATCH] [ADD] account_reconcile_model_inclusion --- account_reconcile_model_inclusion/README.rst | 113 +++++ account_reconcile_model_inclusion/__init__.py | 1 + .../__manifest__.py | 23 + .../demo/account_reconcile_model.xml | 51 ++ .../models/__init__.py | 1 + .../models/account_reconcile_model.py | 73 +++ .../readme/CONFIGURE.md | 4 + .../readme/CONTRIBUTORS.md | 1 + .../readme/DESCRIPTION.md | 3 + .../readme/USAGE.md | 4 + .../static/description/icon.png | Bin 0 -> 9455 bytes .../static/description/index.html | 453 ++++++++++++++++++ .../tests/__init__.py | 1 + .../test_account_reconcile_model_inclusion.py | 82 ++++ .../views/account_reconcile_model.xml | 15 + .../addons/account_reconcile_model_inclusion | 1 + .../setup.py | 6 + 17 files changed, 832 insertions(+) create mode 100644 account_reconcile_model_inclusion/README.rst create mode 100644 account_reconcile_model_inclusion/__init__.py create mode 100644 account_reconcile_model_inclusion/__manifest__.py create mode 100644 account_reconcile_model_inclusion/demo/account_reconcile_model.xml create mode 100644 account_reconcile_model_inclusion/models/__init__.py create mode 100644 account_reconcile_model_inclusion/models/account_reconcile_model.py create mode 100644 account_reconcile_model_inclusion/readme/CONFIGURE.md create mode 100644 account_reconcile_model_inclusion/readme/CONTRIBUTORS.md create mode 100644 account_reconcile_model_inclusion/readme/DESCRIPTION.md create mode 100644 account_reconcile_model_inclusion/readme/USAGE.md create mode 100644 account_reconcile_model_inclusion/static/description/icon.png create mode 100644 account_reconcile_model_inclusion/static/description/index.html create mode 100644 account_reconcile_model_inclusion/tests/__init__.py create mode 100644 account_reconcile_model_inclusion/tests/test_account_reconcile_model_inclusion.py create mode 100644 account_reconcile_model_inclusion/views/account_reconcile_model.xml create mode 120000 setup/account_reconcile_model_inclusion/odoo/addons/account_reconcile_model_inclusion create mode 100644 setup/account_reconcile_model_inclusion/setup.py diff --git a/account_reconcile_model_inclusion/README.rst b/account_reconcile_model_inclusion/README.rst new file mode 100644 index 0000000000..2b59a29a5f --- /dev/null +++ b/account_reconcile_model_inclusion/README.rst @@ -0,0 +1,113 @@ +======================================== +Reconciliation model inclusion/exclusion +======================================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:4b34b13c2c66ef191993b5a96c02315d7eb330d531916ab6328f2da05a725033 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png + :target: https://odoo-community.org/page/development-status + :alt: Alpha +.. |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--reconcile-lightgray.png?logo=github + :target: https://github.com/OCA/account-reconcile/tree/16.0/account_reconcile_model_inclusion + :alt: OCA/account-reconcile +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/account-reconcile-16-0/account-reconcile-16-0-account_reconcile_model_inclusion + :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-reconcile&target_branch=16.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module allows to include or exclude other models when matching +reconciliation rules. + +Doing so can simplify models significantly for cases where there's some +overlap between sets of codes to match, like "if it looks like XX XX, +take rule 1, if it looks like XX XXX take rule 2, but if XX XX and XX +XXX are present in any order, take rule 3". + +.. IMPORTANT:: + This is an alpha version, the data model and design can change at any time without warning. + Only for development or testing purpose, do not use in production. + `More details on development status `_ + +**Table of contents** + +.. contents:: + :local: + +Configuration +============= + +To configure this module, you need to: + +1. Go to Accounting / Banks / Reconciliation Models +2. Fill in rules to include/exclude in the conditions tab + +Usage +===== + +To use this module, you need to: + +1. Configure a reconciliation model as outlined above +2. Observe it will be used according to the configuration during + reconciliation + +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 +------- + +* Hunki Enterprises BV + +Contributors +------------ + +- Holger Brunn + (https://hunki-enterprises.com) + +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. + +.. |maintainer-hbrunn| image:: https://github.com/hbrunn.png?size=40px + :target: https://github.com/hbrunn + :alt: hbrunn + +Current `maintainer `__: + +|maintainer-hbrunn| + +This module is part of the `OCA/account-reconcile `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/account_reconcile_model_inclusion/__init__.py b/account_reconcile_model_inclusion/__init__.py new file mode 100644 index 0000000000..0650744f6b --- /dev/null +++ b/account_reconcile_model_inclusion/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/account_reconcile_model_inclusion/__manifest__.py b/account_reconcile_model_inclusion/__manifest__.py new file mode 100644 index 0000000000..79c2d34e88 --- /dev/null +++ b/account_reconcile_model_inclusion/__manifest__.py @@ -0,0 +1,23 @@ +# Copyright 2025 Hunki Enterprises BV +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl-3.0) + +{ + "name": "Reconciliation model inclusion/exclusion", + "summary": "Allows to match only when other models match/don't match", + "version": "16.0.1.0.0", + "development_status": "Alpha", + "category": "Accounting", + "website": "https://github.com/OCA/account-reconcile", + "author": "Hunki Enterprises BV, Odoo Community Association (OCA)", + "maintainers": ["hbrunn"], + "license": "AGPL-3", + "depends": [ + "account", + ], + "data": [ + "views/account_reconcile_model.xml", + ], + "demo": [ + "demo/account_reconcile_model.xml", + ], +} diff --git a/account_reconcile_model_inclusion/demo/account_reconcile_model.xml b/account_reconcile_model_inclusion/demo/account_reconcile_model.xml new file mode 100644 index 0000000000..4ececa8ff1 --- /dev/null +++ b/account_reconcile_model_inclusion/demo/account_reconcile_model.xml @@ -0,0 +1,51 @@ + + + + + Two blocks + writeoff_suggestion + match_regex + .*\bXX\s+\d{2}\s+\d{2}\b.* + + + Three blocks + writeoff_suggestion + match_regex + .*\bXY\s+\d{2}\s+\d{2}\s+\d{2}\b.* + + + Three blocks (includes two blocks) + writeoff_suggestion + match_regex + .*\bXX\s+\d{2}\s+\d{2}\s+\d{2}\b.* + + + Both blocks + writeoff_suggestion + + + + Both XX blocks + writeoff_suggestion + + + + + + + + + diff --git a/account_reconcile_model_inclusion/models/__init__.py b/account_reconcile_model_inclusion/models/__init__.py new file mode 100644 index 0000000000..e27d0c6ca4 --- /dev/null +++ b/account_reconcile_model_inclusion/models/__init__.py @@ -0,0 +1 @@ +from . import account_reconcile_model diff --git a/account_reconcile_model_inclusion/models/account_reconcile_model.py b/account_reconcile_model_inclusion/models/account_reconcile_model.py new file mode 100644 index 0000000000..f610e86c8e --- /dev/null +++ b/account_reconcile_model_inclusion/models/account_reconcile_model.py @@ -0,0 +1,73 @@ +# Copyright 2025 Hunki Enterprises BV +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl-3.0) + +from odoo import fields, models +from odoo.tools.safe_eval import safe_eval + + +class AccountReconcileModel(models.Model): + _inherit = "account.reconcile.model" + + include_reconcile_model_ids = fields.Many2many( + comodel_name="account.reconcile.model", + relation="account_reconcile_model_include_rel", + column1="model_id", + column2="included_model_id", + ) + exclude_reconcile_model_ids = fields.Many2many( + comodel_name="account.reconcile.model", + relation="account_reconcile_model_exclude_rel", + column1="model_id", + column2="excluded_model_id", + ) + + def _account_reconcile_model_inclusion_expression(self, seen=None): + """ + Build an expression with 'm{model.id}' as variables that expresses + the applicability of a model recursively wrt includes/excludes + """ + seen = seen or set() + seen.add(self) + result = ( + f"(m{self.id} and " + + ( + " and ".join( + include._account_reconcile_model_inclusion_expression(seen.copy()) + if include not in seen + else f"m{include.id}" + for include in self.include_reconcile_model_ids + ) + or "True" + ) + + " and " + + ( + " and ".join( + "not " + + exclude._account_reconcile_model_inclusion_expression(seen.copy()) + if exclude not in seen + else f"m{exclude.id}" + for exclude in self.exclude_reconcile_model_ids + ) + or "True" + ) + + ")" + ) + return result + + def _is_applicable_for(self, st_line, partner): + """ + Apply inclusion/exclusion of other models' results + """ + result = super()._is_applicable_for(st_line, partner) + + if not result or self.env.context.get("account_reconcile_model_inclusion"): + return result + + expression = self._account_reconcile_model_inclusion_expression() + eval_context = { + f"m{model.id}": model._is_applicable_for(st_line, partner) + for model in self.search([]).with_context( + account_reconcile_model_inclusion=True + ) + } + return safe_eval(expression, eval_context) diff --git a/account_reconcile_model_inclusion/readme/CONFIGURE.md b/account_reconcile_model_inclusion/readme/CONFIGURE.md new file mode 100644 index 0000000000..e2ec4407fa --- /dev/null +++ b/account_reconcile_model_inclusion/readme/CONFIGURE.md @@ -0,0 +1,4 @@ +To configure this module, you need to: + +1. Go to Accounting / Banks / Reconciliation Models +2. Fill in rules to include/exclude in the conditions tab diff --git a/account_reconcile_model_inclusion/readme/CONTRIBUTORS.md b/account_reconcile_model_inclusion/readme/CONTRIBUTORS.md new file mode 100644 index 0000000000..b28199e1f4 --- /dev/null +++ b/account_reconcile_model_inclusion/readme/CONTRIBUTORS.md @@ -0,0 +1 @@ +- Holger Brunn \ (https://hunki-enterprises.com) diff --git a/account_reconcile_model_inclusion/readme/DESCRIPTION.md b/account_reconcile_model_inclusion/readme/DESCRIPTION.md new file mode 100644 index 0000000000..ed329b5bbd --- /dev/null +++ b/account_reconcile_model_inclusion/readme/DESCRIPTION.md @@ -0,0 +1,3 @@ +This module allows to include or exclude other models when matching reconciliation rules. + +Doing so can simplify models significantly for cases where there's some overlap between sets of codes to match, like "if it looks like XX XX, take rule 1, if it looks like XX XXX take rule 2, but if XX XX and XX XXX are present in any order, take rule 3". diff --git a/account_reconcile_model_inclusion/readme/USAGE.md b/account_reconcile_model_inclusion/readme/USAGE.md new file mode 100644 index 0000000000..0482215ef3 --- /dev/null +++ b/account_reconcile_model_inclusion/readme/USAGE.md @@ -0,0 +1,4 @@ +To use this module, you need to: + +1. Configure a reconciliation model as outlined above +2. Observe it will be used according to the configuration during reconciliation diff --git a/account_reconcile_model_inclusion/static/description/icon.png b/account_reconcile_model_inclusion/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d GIT binary patch literal 9455 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 z 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 Xviia!U7SGha1wx#SCgwmn*{w2TRX*I literal 0 HcmV?d00001 diff --git a/account_reconcile_model_inclusion/static/description/index.html b/account_reconcile_model_inclusion/static/description/index.html new file mode 100644 index 0000000000..50aaf18bb0 --- /dev/null +++ b/account_reconcile_model_inclusion/static/description/index.html @@ -0,0 +1,453 @@ + + + + + +Reconciliation model inclusion/exclusion + + + +
+

Reconciliation model inclusion/exclusion

+ + +

Alpha License: AGPL-3 OCA/account-reconcile Translate me on Weblate Try me on Runboat

+

This module allows to include or exclude other models when matching +reconciliation rules.

+

Doing so can simplify models significantly for cases where there’s some +overlap between sets of codes to match, like “if it looks like XX XX, +take rule 1, if it looks like XX XXX take rule 2, but if XX XX and XX +XXX are present in any order, take rule 3”.

+
+

Important

+

This is an alpha version, the data model and design can change at any time without warning. +Only for development or testing purpose, do not use in production. +More details on development status

+
+

Table of contents

+ +
+

Configuration

+

To configure this module, you need to:

+
    +
  1. Go to Accounting / Banks / Reconciliation Models
  2. +
  3. Fill in rules to include/exclude in the conditions tab
  4. +
+
+
+

Usage

+

To use this module, you need to:

+
    +
  1. Configure a reconciliation model as outlined above
  2. +
  3. Observe it will be used according to the configuration during +reconciliation
  4. +
+
+
+

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

+
    +
  • Hunki Enterprises BV
  • +
+
+ +
+

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.

+

Current maintainer:

+

hbrunn

+

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

+

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

+
+
+
+ + diff --git a/account_reconcile_model_inclusion/tests/__init__.py b/account_reconcile_model_inclusion/tests/__init__.py new file mode 100644 index 0000000000..807c1429f8 --- /dev/null +++ b/account_reconcile_model_inclusion/tests/__init__.py @@ -0,0 +1 @@ +from . import test_account_reconcile_model_inclusion diff --git a/account_reconcile_model_inclusion/tests/test_account_reconcile_model_inclusion.py b/account_reconcile_model_inclusion/tests/test_account_reconcile_model_inclusion.py new file mode 100644 index 0000000000..f3bbb33bbb --- /dev/null +++ b/account_reconcile_model_inclusion/tests/test_account_reconcile_model_inclusion.py @@ -0,0 +1,82 @@ +# Copyright 2025 Hunki Enterprises BV +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl-3.0) + +from odoo.tests.common import TransactionCase + + +class SomethingAccountReconcileModelInclusion(TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.rule_two_blocks = cls.env.ref( + "account_reconcile_model_inclusion.model_rule_two_blocks" + ) + cls.rule_three_blocks = cls.env.ref( + "account_reconcile_model_inclusion.model_rule_three_blocks" + ) + cls.rule_three_blocks_xx = cls.env.ref( + "account_reconcile_model_inclusion.model_rule_three_blocks_xx" + ) + cls.rule_both = cls.env.ref("account_reconcile_model_inclusion.model_rule_both") + cls.rule_both_xx = cls.env.ref( + "account_reconcile_model_inclusion.model_rule_both_xx" + ) + + def test_account_reconcile_model_inclusion(self): + """Test that inclusion/exclusion works""" + StatementLine = self.env["account.bank.statement.line"] + Partner = self.env["res.partner"] + + line = StatementLine.new({}) + + def assertApplicable(rule): + nonlocal line + self.assertTrue(rule._is_applicable_for(line, Partner)) + + def assertNotApplicable(rule): + nonlocal line + self.assertFalse(rule._is_applicable_for(line, Partner)) + + line.payment_ref = "XX 42 42" + assertApplicable(self.rule_two_blocks) + assertNotApplicable(self.rule_three_blocks) + assertNotApplicable(self.rule_three_blocks_xx) + assertNotApplicable(self.rule_both) + + line.payment_ref = "hello XX 42 42 world" + assertApplicable(self.rule_two_blocks) + assertNotApplicable(self.rule_three_blocks) + assertNotApplicable(self.rule_three_blocks_xx) + assertNotApplicable(self.rule_both) + + line.payment_ref = "hello XY 42 42 42 world" + assertNotApplicable(self.rule_two_blocks) + assertApplicable(self.rule_three_blocks) + assertNotApplicable(self.rule_three_blocks_xx) + assertNotApplicable(self.rule_both) + + line.payment_ref = "hello XY 42 42 42/XX 42 42 world" + assertNotApplicable(self.rule_two_blocks) + assertNotApplicable(self.rule_three_blocks) + assertNotApplicable(self.rule_three_blocks_xx) + assertApplicable(self.rule_both) + + line.payment_ref = "hello XX 42 42 42/XX 42 42 world" + assertNotApplicable(self.rule_two_blocks) + assertNotApplicable(self.rule_three_blocks) + assertApplicable(self.rule_three_blocks_xx) + assertNotApplicable(self.rule_both) + assertApplicable(self.rule_both_xx) + + line.payment_ref = "hello XX 42 42 42 world" + assertNotApplicable(self.rule_two_blocks) + assertNotApplicable(self.rule_three_blocks) + assertApplicable(self.rule_three_blocks_xx) + assertNotApplicable(self.rule_both) + + self.rule_three_blocks_xx.exclude_reconcile_model_ids = self.rule_two_blocks + self.rule_two_blocks.exclude_reconcile_model_ids = self.rule_three_blocks_xx + line.payment_ref = "hello XX 42 42 42/XX 42 42 world" + assertNotApplicable(self.rule_two_blocks) + assertNotApplicable(self.rule_three_blocks_xx) + assertNotApplicable(self.rule_both_xx) diff --git a/account_reconcile_model_inclusion/views/account_reconcile_model.xml b/account_reconcile_model_inclusion/views/account_reconcile_model.xml new file mode 100644 index 0000000000..e5b3ec50c5 --- /dev/null +++ b/account_reconcile_model_inclusion/views/account_reconcile_model.xml @@ -0,0 +1,15 @@ + + + + + account.reconcile.model + + + + + + + + + diff --git a/setup/account_reconcile_model_inclusion/odoo/addons/account_reconcile_model_inclusion b/setup/account_reconcile_model_inclusion/odoo/addons/account_reconcile_model_inclusion new file mode 120000 index 0000000000..f5a96cdeef --- /dev/null +++ b/setup/account_reconcile_model_inclusion/odoo/addons/account_reconcile_model_inclusion @@ -0,0 +1 @@ +../../../../account_reconcile_model_inclusion \ No newline at end of file diff --git a/setup/account_reconcile_model_inclusion/setup.py b/setup/account_reconcile_model_inclusion/setup.py new file mode 100644 index 0000000000..28c57bb640 --- /dev/null +++ b/setup/account_reconcile_model_inclusion/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)