From 40ab5ac5619ad1b3e6d625dfdf0f5f93349b3abd Mon Sep 17 00:00:00 2001 From: sbejaoui Date: Thu, 11 Jul 2019 15:36:43 +0200 Subject: [PATCH 01/42] [ADD] - report substitute This addon give the possibility to substitute a report action by another based on some criteria. --- report_substitute/__init__.py | 1 + report_substitute/__manifest__.py | 20 +++++++++ report_substitute/models/__init__.py | 2 + report_substitute/models/ir_actions_report.py | 40 +++++++++++++++++ ...ir_actions_report_substitution_criteria.py | 28 ++++++++++++ ...r_actions_report_substitution_criteria.xml | 25 +++++++++++ report_substitute/views/ir_actions_report.xml | 43 +++++++++++++++++++ 7 files changed, 159 insertions(+) create mode 100644 report_substitute/__init__.py create mode 100644 report_substitute/__manifest__.py create mode 100644 report_substitute/models/__init__.py create mode 100644 report_substitute/models/ir_actions_report.py create mode 100644 report_substitute/models/ir_actions_report_substitution_criteria.py create mode 100644 report_substitute/security/ir_actions_report_substitution_criteria.xml create mode 100644 report_substitute/views/ir_actions_report.xml diff --git a/report_substitute/__init__.py b/report_substitute/__init__.py new file mode 100644 index 0000000000..0650744f6b --- /dev/null +++ b/report_substitute/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/report_substitute/__manifest__.py b/report_substitute/__manifest__.py new file mode 100644 index 0000000000..a9ad3ca7a9 --- /dev/null +++ b/report_substitute/__manifest__.py @@ -0,0 +1,20 @@ +# Copyright 2019 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + 'name': 'Report Substitute', + 'summary': """ + This addon give the possibility to substitute a report action by + another based on some criteria. + """, + 'version': '12.0.1.0.0', + 'license': 'AGPL-3', + 'author': 'ACSONE SA/NV,' + 'Odoo Community Association (OCA)', + 'website': 'https://github.com/acsone/reporting-engine', + 'depends': ['base'], + 'data': [ + 'security/ir_actions_report_substitution_criteria.xml', + 'views/ir_actions_report.xml', + ], +} diff --git a/report_substitute/models/__init__.py b/report_substitute/models/__init__.py new file mode 100644 index 0000000000..d1a25e84ae --- /dev/null +++ b/report_substitute/models/__init__.py @@ -0,0 +1,2 @@ +from . import ir_actions_report +from . import ir_actions_report_substitution_criteria diff --git a/report_substitute/models/ir_actions_report.py b/report_substitute/models/ir_actions_report.py new file mode 100644 index 0000000000..ca2e7ce836 --- /dev/null +++ b/report_substitute/models/ir_actions_report.py @@ -0,0 +1,40 @@ +# Copyright 2019 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models, _ +from odoo.tools.safe_eval import safe_eval + + +class IrActionReport(models.Model): + + _inherit = 'ir.actions.report' + + action_report_substitution_criteria_ids = fields.One2many( + comodel_name="ir.actions.report.substitution.criteria", + inverse_name="action_report_id", + string="Substitution Criteria", + ) + + @api.multi + def _get_substitution_report(self, model, active_ids): + self.ensure_one() + model = self.env[model] + for ( + substitution_report_criteria + ) in self.action_report_substitution_criteria_ids: + domain = safe_eval(substitution_report_criteria.domain) + domain.append(('id', 'in', active_ids)) + if set(model.search(domain).ids) == set(active_ids): + return ( + substitution_report_criteria.substitution_action_report_id + ) + return False + + @api.multi + def render(self, res_ids, data=None): + substitution_report = self._get_substitution_report( + self.model, res_ids + ) + if substitution_report: + return substitution_report.render(res_ids) + return super().render(res_ids, data) diff --git a/report_substitute/models/ir_actions_report_substitution_criteria.py b/report_substitute/models/ir_actions_report_substitution_criteria.py new file mode 100644 index 0000000000..04430aedec --- /dev/null +++ b/report_substitute/models/ir_actions_report_substitution_criteria.py @@ -0,0 +1,28 @@ +# Copyright 2019 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class ActionsReportSubstitutionCriteria(models.Model): + + _name = 'ir.actions.report.substitution.criteria' + _description = 'Action Report Substitution Criteria' + _order = 'sequence ASC' + + sequence = fields.Integer(default=10) + action_report_id = fields.Many2one( + comodel_name="ir.actions.report", + string="Report Action", + required=True, + ondelete="cascade", + ) + model = fields.Char(related="action_report_id.model", store=True) + domain = fields.Char(string="Domain", required=True, default="[]") + substitution_action_report_id = fields.Many2one( + comodel_name="ir.actions.report", + string="Substitution Report Action", + required=True, + ondelete="cascade", + domain="[('model', '=', model)]" + ) diff --git a/report_substitute/security/ir_actions_report_substitution_criteria.xml b/report_substitute/security/ir_actions_report_substitution_criteria.xml new file mode 100644 index 0000000000..b74770b852 --- /dev/null +++ b/report_substitute/security/ir_actions_report_substitution_criteria.xml @@ -0,0 +1,25 @@ + + + + + + + action.report.substitution.criteria user access + + + + + + + + + action.report.substitution.criteria manager access + + + + + + + + diff --git a/report_substitute/views/ir_actions_report.xml b/report_substitute/views/ir_actions_report.xml new file mode 100644 index 0000000000..750aeb7416 --- /dev/null +++ b/report_substitute/views/ir_actions_report.xml @@ -0,0 +1,43 @@ + + + + + + + ir.actions.report.form (in report_dispatch_base) + + ir.actions.report + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+
+ + +
From b15d39d96ae3e7d11d5c52d09cbc662450fb8cbc Mon Sep 17 00:00:00 2001 From: sbejaoui Date: Mon, 22 Jul 2019 14:26:07 +0200 Subject: [PATCH 02/42] [ADD] - Add readme --- report_substitute/README.rst | 100 ++++ report_substitute/__manifest__.py | 3 +- report_substitute/readme/CONTRIBUTORS.rst | 1 + report_substitute/readme/DESCRIPTION.rst | 4 + report_substitute/readme/ROADMAP.rst | 1 + report_substitute/readme/USAGE.rst | 15 + .../static/description/index.html | 443 ++++++++++++++++++ report_substitute/views/ir_actions_report.xml | 2 +- 8 files changed, 566 insertions(+), 3 deletions(-) create mode 100644 report_substitute/README.rst create mode 100644 report_substitute/readme/CONTRIBUTORS.rst create mode 100644 report_substitute/readme/DESCRIPTION.rst create mode 100644 report_substitute/readme/ROADMAP.rst create mode 100644 report_substitute/readme/USAGE.rst create mode 100644 report_substitute/static/description/index.html diff --git a/report_substitute/README.rst b/report_substitute/README.rst new file mode 100644 index 0000000000..7739e6f2f1 --- /dev/null +++ b/report_substitute/README.rst @@ -0,0 +1,100 @@ +================= +Report Substitute +================= + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! 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%2Freporting--engine-lightgray.png?logo=github + :target: https://github.com/OCA/reporting-engine/tree/12.0/report_substitute + :alt: OCA/reporting-engine +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/reporting-engine-12-0/reporting-engine-12-0-report_substitute + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/143/12.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module allows you to create substitution rules for report actions. +A typical use case is to replace a standard report by alternative reports +when some conditions are met. For instance, it allows to configure alternate +reports for different companies. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +To use this module, you need to: + +#. Go to 'Actions' / 'Reports' + +#. Select the desired report you want to substitute + +#. In the substitutions page add a new line + +#. Select the substitution report action + +#. Set a domain to specify when this substitution should happen + + +When a user calls a report action, the system tries to find the first +substitution in with a domain that matches all records. + +Known issues / Roadmap +====================== + +- The document name result should take the name of the substitution report. + +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 +~~~~~~~ + +* ACSONE SA/NV + +Contributors +~~~~~~~~~~~~ + +* Bejaoui Souheil + +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/reporting-engine `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/report_substitute/__manifest__.py b/report_substitute/__manifest__.py index a9ad3ca7a9..db268ee16a 100644 --- a/report_substitute/__manifest__.py +++ b/report_substitute/__manifest__.py @@ -4,8 +4,7 @@ { 'name': 'Report Substitute', 'summary': """ - This addon give the possibility to substitute a report action by - another based on some criteria. + This module allows to create substitution rules for report actions. """, 'version': '12.0.1.0.0', 'license': 'AGPL-3', diff --git a/report_substitute/readme/CONTRIBUTORS.rst b/report_substitute/readme/CONTRIBUTORS.rst new file mode 100644 index 0000000000..35c03ffe0f --- /dev/null +++ b/report_substitute/readme/CONTRIBUTORS.rst @@ -0,0 +1 @@ +* Bejaoui Souheil diff --git a/report_substitute/readme/DESCRIPTION.rst b/report_substitute/readme/DESCRIPTION.rst new file mode 100644 index 0000000000..55ccac5e86 --- /dev/null +++ b/report_substitute/readme/DESCRIPTION.rst @@ -0,0 +1,4 @@ +This module allows you to create substitution rules for report actions. +A typical use case is to replace a standard report by alternative reports +when some conditions are met. For instance, it allows to configure alternate +reports for different companies. diff --git a/report_substitute/readme/ROADMAP.rst b/report_substitute/readme/ROADMAP.rst new file mode 100644 index 0000000000..28e27a3eac --- /dev/null +++ b/report_substitute/readme/ROADMAP.rst @@ -0,0 +1 @@ +- The document name result should take the name of the substitution report. diff --git a/report_substitute/readme/USAGE.rst b/report_substitute/readme/USAGE.rst new file mode 100644 index 0000000000..b91a68d52a --- /dev/null +++ b/report_substitute/readme/USAGE.rst @@ -0,0 +1,15 @@ +To use this module, you need to: + +#. Go to 'Actions' / 'Reports' + +#. Select the desired report you want to substitute + +#. In the substitutions page add a new line + +#. Select the substitution report action + +#. Set a domain to specify when this substitution should happen + + +When a user calls a report action, the system tries to find the first +substitution in with a domain that matches all records. diff --git a/report_substitute/static/description/index.html b/report_substitute/static/description/index.html new file mode 100644 index 0000000000..e2994a632e --- /dev/null +++ b/report_substitute/static/description/index.html @@ -0,0 +1,443 @@ + + + + + + +Report Substitute + + + +
+

Report Substitute

+ + +

Beta License: AGPL-3 OCA/reporting-engine Translate me on Weblate Try me on Runbot

+

This module allows you to create substitution rules for report actions. +A typical use case is to replace a standard report by alternative reports +when some conditions are met. For instance, it allows to configure alternate +reports for different companies.

+

Table of contents

+ +
+

Usage

+

To use this module, you need to:

+
    +
  1. Go to ‘Actions’ / ‘Reports’
  2. +
  3. Select the desired report you want to substitute
  4. +
  5. In the substitutions page add a new line
  6. +
  7. Select the substitution report action
  8. +
  9. Set a domain to specify when this substitution should happen
  10. +
+

When a user calls a report action, the system tries to find the first +substitution in with a domain that matches all records.

+
+
+

Known issues / Roadmap

+
    +
  • The document name result should take the name of the substitution report.
  • +
+
+
+

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

+
    +
  • ACSONE SA/NV
  • +
+
+
+

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/reporting-engine project on GitHub.

+

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

+
+
+
+ + diff --git a/report_substitute/views/ir_actions_report.xml b/report_substitute/views/ir_actions_report.xml index 750aeb7416..6d9f4a45d6 100644 --- a/report_substitute/views/ir_actions_report.xml +++ b/report_substitute/views/ir_actions_report.xml @@ -11,7 +11,7 @@ - + From 006b0341651f4d09bf1dfa502f533dcea95271a3 Mon Sep 17 00:00:00 2001 From: sbejaoui Date: Mon, 22 Jul 2019 15:43:57 +0200 Subject: [PATCH 03/42] [ADD] - Add unit tests --- report_substitute/README.rst | 2 +- report_substitute/__init__.py | 1 + report_substitute/__manifest__.py | 3 +- report_substitute/demo/action_report.xml | 29 +++++++++++ report_substitute/models/__init__.py | 2 +- report_substitute/models/ir_actions_report.py | 16 +++---- ...=> ir_actions_report_substitution_rule.py} | 6 +-- report_substitute/readme/USAGE.rst | 2 +- ...> ir_actions_report_substitution_rule.xml} | 12 ++--- .../static/description/index.html | 2 +- report_substitute/tests/__init__.py | 1 + .../tests/test_report_substitute.py | 48 +++++++++++++++++++ report_substitute/views/ir_actions_report.xml | 4 +- 13 files changed, 104 insertions(+), 24 deletions(-) create mode 100644 report_substitute/demo/action_report.xml rename report_substitute/models/{ir_actions_report_substitution_criteria.py => ir_actions_report_substitution_rule.py} (81%) rename report_substitute/security/{ir_actions_report_substitution_criteria.xml => ir_actions_report_substitution_rule.xml} (76%) create mode 100644 report_substitute/tests/__init__.py create mode 100644 report_substitute/tests/test_report_substitute.py diff --git a/report_substitute/README.rst b/report_substitute/README.rst index 7739e6f2f1..20762b8355 100644 --- a/report_substitute/README.rst +++ b/report_substitute/README.rst @@ -42,7 +42,7 @@ To use this module, you need to: #. Go to 'Actions' / 'Reports' -#. Select the desired report you want to substitute +#. Select the desired report you want to 'Substitution Rules' #. In the substitutions page add a new line diff --git a/report_substitute/__init__.py b/report_substitute/__init__.py index 0650744f6b..0ee8b5073e 100644 --- a/report_substitute/__init__.py +++ b/report_substitute/__init__.py @@ -1 +1,2 @@ from . import models +from . import tests diff --git a/report_substitute/__manifest__.py b/report_substitute/__manifest__.py index db268ee16a..f65a6a02be 100644 --- a/report_substitute/__manifest__.py +++ b/report_substitute/__manifest__.py @@ -13,7 +13,8 @@ 'website': 'https://github.com/acsone/reporting-engine', 'depends': ['base'], 'data': [ - 'security/ir_actions_report_substitution_criteria.xml', + 'security/ir_actions_report_substitution_rule.xml', 'views/ir_actions_report.xml', ], + 'demo': ['demo/action_report.xml'], } diff --git a/report_substitute/demo/action_report.xml b/report_substitute/demo/action_report.xml new file mode 100644 index 0000000000..e3b85ba22b --- /dev/null +++ b/report_substitute/demo/action_report.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + diff --git a/report_substitute/models/__init__.py b/report_substitute/models/__init__.py index d1a25e84ae..27b9defe6e 100644 --- a/report_substitute/models/__init__.py +++ b/report_substitute/models/__init__.py @@ -1,2 +1,2 @@ from . import ir_actions_report -from . import ir_actions_report_substitution_criteria +from . import ir_actions_report_substitution_rule diff --git a/report_substitute/models/ir_actions_report.py b/report_substitute/models/ir_actions_report.py index ca2e7ce836..32c3181277 100644 --- a/report_substitute/models/ir_actions_report.py +++ b/report_substitute/models/ir_actions_report.py @@ -1,7 +1,7 @@ # Copyright 2019 ACSONE SA/NV # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo import api, fields, models, _ +from odoo import api, fields, models from odoo.tools.safe_eval import safe_eval @@ -9,10 +9,10 @@ class IrActionReport(models.Model): _inherit = 'ir.actions.report' - action_report_substitution_criteria_ids = fields.One2many( - comodel_name="ir.actions.report.substitution.criteria", + action_report_substitution_rule_ids = fields.One2many( + comodel_name="ir.actions.report.substitution.rule", inverse_name="action_report_id", - string="Substitution Criteria", + string="Substitution Rules", ) @api.multi @@ -20,13 +20,13 @@ def _get_substitution_report(self, model, active_ids): self.ensure_one() model = self.env[model] for ( - substitution_report_criteria - ) in self.action_report_substitution_criteria_ids: - domain = safe_eval(substitution_report_criteria.domain) + substitution_report_rule + ) in self.action_report_substitution_rule_ids: + domain = safe_eval(substitution_report_rule.domain) domain.append(('id', 'in', active_ids)) if set(model.search(domain).ids) == set(active_ids): return ( - substitution_report_criteria.substitution_action_report_id + substitution_report_rule.substitution_action_report_id ) return False diff --git a/report_substitute/models/ir_actions_report_substitution_criteria.py b/report_substitute/models/ir_actions_report_substitution_rule.py similarity index 81% rename from report_substitute/models/ir_actions_report_substitution_criteria.py rename to report_substitute/models/ir_actions_report_substitution_rule.py index 04430aedec..4c72507111 100644 --- a/report_substitute/models/ir_actions_report_substitution_criteria.py +++ b/report_substitute/models/ir_actions_report_substitution_rule.py @@ -4,10 +4,10 @@ from odoo import fields, models -class ActionsReportSubstitutionCriteria(models.Model): +class ActionsReportSubstitutionRule(models.Model): - _name = 'ir.actions.report.substitution.criteria' - _description = 'Action Report Substitution Criteria' + _name = 'ir.actions.report.substitution.rule' + _description = 'Action Report Substitution Rule' _order = 'sequence ASC' sequence = fields.Integer(default=10) diff --git a/report_substitute/readme/USAGE.rst b/report_substitute/readme/USAGE.rst index b91a68d52a..b6f6613970 100644 --- a/report_substitute/readme/USAGE.rst +++ b/report_substitute/readme/USAGE.rst @@ -2,7 +2,7 @@ To use this module, you need to: #. Go to 'Actions' / 'Reports' -#. Select the desired report you want to substitute +#. Select the desired report you want to 'Substitution Rules' #. In the substitutions page add a new line diff --git a/report_substitute/security/ir_actions_report_substitution_criteria.xml b/report_substitute/security/ir_actions_report_substitution_rule.xml similarity index 76% rename from report_substitute/security/ir_actions_report_substitution_criteria.xml rename to report_substitute/security/ir_actions_report_substitution_rule.xml index b74770b852..e7af09afd4 100644 --- a/report_substitute/security/ir_actions_report_substitution_criteria.xml +++ b/report_substitute/security/ir_actions_report_substitution_rule.xml @@ -4,18 +4,18 @@ - - action.report.substitution.criteria user access - + + action.report.substitution.rule user access + - - action.report.substitution.criteria manager access - + + action.report.substitution.rule manager access + diff --git a/report_substitute/static/description/index.html b/report_substitute/static/description/index.html index e2994a632e..71e4b31b6f 100644 --- a/report_substitute/static/description/index.html +++ b/report_substitute/static/description/index.html @@ -391,7 +391,7 @@

Usage

To use this module, you need to:

  1. Go to ‘Actions’ / ‘Reports’
  2. -
  3. Select the desired report you want to substitute
  4. +
  5. Select the desired report you want to ‘Substitution Rules’
  6. In the substitutions page add a new line
  7. Select the substitution report action
  8. Set a domain to specify when this substitution should happen
  9. diff --git a/report_substitute/tests/__init__.py b/report_substitute/tests/__init__.py new file mode 100644 index 0000000000..8c5a3f248f --- /dev/null +++ b/report_substitute/tests/__init__.py @@ -0,0 +1 @@ +from . import test_report_substitute diff --git a/report_substitute/tests/test_report_substitute.py b/report_substitute/tests/test_report_substitute.py new file mode 100644 index 0000000000..fecb4be6c0 --- /dev/null +++ b/report_substitute/tests/test_report_substitute.py @@ -0,0 +1,48 @@ +# Copyright 2019 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo.tests.common import TransactionCase + + +class TestReportSubstitute(TransactionCase): + def setUp(self): + # In the demo file we create a new report for ir.module.module model + # with a substation rule from the original report action + super(TestReportSubstitute, self).setUp() + self.action_report = self.env.ref('base.ir_module_reference_print') + self.res_ids = self.env.ref('base.module_base').ids + self.substitution_rule = self.env.ref( + 'report_substitute.substitution_rule_demo_1' + ) + + def test_substitution(self): + res = str(self.action_report.render(res_ids=self.res_ids)[0]) + self.assertIn('
    Substitution Report
    ', res) + # remove the substation rule + self.substitution_rule.unlink() + res = str(self.action_report.render(res_ids=self.res_ids)[0]) + self.assertNotIn('
    Substitution Report
    ', res) + + def test_recursive_substitution(self): + res = str(self.action_report.render(res_ids=self.res_ids)[0]) + self.assertNotIn('
    Substitution Report 2
    ', res) + self.env['ir.actions.report.substitution.rule'].create( + { + 'substitution_action_report_id': self.env.ref( + 'report_substitute.substitution_report_print_2' + ).id, + 'action_report_id': self.env.ref( + 'report_substitute.substitution_report_print' + ).id, + } + ) + res = str(self.action_report.render(res_ids=self.res_ids)[0]) + self.assertIn('
    Substitution Report 2
    ', res) + + def test_substitution_with_domain(self): + self.substitution_rule.write({'domain': "[('name', '=', 'base')]"}) + res = str(self.action_report.render(res_ids=self.res_ids)[0]) + self.assertIn('
    Substitution Report
    ', res) + self.substitution_rule.write({'domain': "[('name', '!=', 'base')]"}) + res = str(self.action_report.render(res_ids=self.res_ids)[0]) + self.assertNotIn('
    Substitution Report
    ', res) diff --git a/report_substitute/views/ir_actions_report.xml b/report_substitute/views/ir_actions_report.xml index 6d9f4a45d6..bda45ba780 100644 --- a/report_substitute/views/ir_actions_report.xml +++ b/report_substitute/views/ir_actions_report.xml @@ -11,8 +11,8 @@ - - + + From 24991f07c2d35c469a4c2d3836ee7f01749a409a Mon Sep 17 00:00:00 2001 From: sbejaoui Date: Tue, 23 Jul 2019 15:33:01 +0200 Subject: [PATCH 04/42] [FIX] - missing method param --- report_substitute/models/ir_actions_report.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/report_substitute/models/ir_actions_report.py b/report_substitute/models/ir_actions_report.py index 32c3181277..3cf091d112 100644 --- a/report_substitute/models/ir_actions_report.py +++ b/report_substitute/models/ir_actions_report.py @@ -36,5 +36,5 @@ def render(self, res_ids, data=None): self.model, res_ids ) if substitution_report: - return substitution_report.render(res_ids) + return substitution_report.render(res_ids, data) return super().render(res_ids, data) From fa31c9d399544669f49a4e65297b9fc18dbc3ef6 Mon Sep 17 00:00:00 2001 From: sbejaoui Date: Tue, 23 Jul 2019 16:24:13 +0200 Subject: [PATCH 05/42] [FIX] - prevent substitution loop --- report_substitute/views/ir_actions_report.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/report_substitute/views/ir_actions_report.xml b/report_substitute/views/ir_actions_report.xml index bda45ba780..0c2c265c8e 100644 --- a/report_substitute/views/ir_actions_report.xml +++ b/report_substitute/views/ir_actions_report.xml @@ -16,7 +16,8 @@ - + />
    From 6f8b341cc91a87d12b9ac4b5c36becb8bc9faa08 Mon Sep 17 00:00:00 2001 From: sbejaoui Date: Thu, 25 Jul 2019 11:07:01 +0200 Subject: [PATCH 06/42] [IMP] - manage subtitute report for multi-action --- report_substitute/__manifest__.py | 1 + report_substitute/models/ir_actions_report.py | 17 +++++++-- .../static/src/js/action_manager.js | 35 +++++++++++++++++++ report_substitute/views/assets_backend.xml | 8 +++++ 4 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 report_substitute/static/src/js/action_manager.js create mode 100644 report_substitute/views/assets_backend.xml diff --git a/report_substitute/__manifest__.py b/report_substitute/__manifest__.py index f65a6a02be..f6061a75e5 100644 --- a/report_substitute/__manifest__.py +++ b/report_substitute/__manifest__.py @@ -14,6 +14,7 @@ 'depends': ['base'], 'data': [ 'security/ir_actions_report_substitution_rule.xml', + 'views/assets_backend.xml', 'views/ir_actions_report.xml', ], 'demo': ['demo/action_report.xml'], diff --git a/report_substitute/models/ir_actions_report.py b/report_substitute/models/ir_actions_report.py index 3cf091d112..88d7b50b69 100644 --- a/report_substitute/models/ir_actions_report.py +++ b/report_substitute/models/ir_actions_report.py @@ -25,11 +25,22 @@ def _get_substitution_report(self, model, active_ids): domain = safe_eval(substitution_report_rule.domain) domain.append(('id', 'in', active_ids)) if set(model.search(domain).ids) == set(active_ids): - return ( - substitution_report_rule.substitution_action_report_id - ) + return substitution_report_rule.substitution_action_report_id return False + @api.model + def get_substitution_report_dict(self, action_report_dict, active_ids): + if action_report_dict.get('id'): + action_report = self.browse(action_report_dict['id']) + substitution_report = action_report + while substitution_report: + action_report = substitution_report + substitution_report = action_report._get_substitution_report( + action_report.model, active_ids + ) + action_report_dict.update(action_report.read()[0]) + return action_report_dict + @api.multi def render(self, res_ids, data=None): substitution_report = self._get_substitution_report( diff --git a/report_substitute/static/src/js/action_manager.js b/report_substitute/static/src/js/action_manager.js new file mode 100644 index 0000000000..754dd70d49 --- /dev/null +++ b/report_substitute/static/src/js/action_manager.js @@ -0,0 +1,35 @@ +// Copyright 2019 ACSONE SA/NV +// License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +odoo.define('report_substitute.action_report_substitute', function(require) { + "use strict"; + + var ActionManager = require('web.ActionManager'); + + ActionManager.include({ + /** + * Intercept action handling substitute the report action + * @override + */ + _handleAction: function(action, options) { + if (action.type === 'ir.actions.report' && + action.context.active_ids) { + var active_ids = action.context.active_ids; + var self = this; + var _super = this._super; + var callersArguments = arguments; + return this._rpc({ + model: 'ir.actions.report', + method: 'get_substitution_report_dict', + args: [action, active_ids] + }).then(function(action_id) { + callersArguments[0] = action_id + return _super.apply(self, callersArguments); + }); + + } + return this._super.apply(this, arguments); + }, + + }); + +}); diff --git a/report_substitute/views/assets_backend.xml b/report_substitute/views/assets_backend.xml new file mode 100644 index 0000000000..4120d85f1d --- /dev/null +++ b/report_substitute/views/assets_backend.xml @@ -0,0 +1,8 @@ + + + + From 5f4c8925fe4ceac772fc7d4e81dbdc25965e3f0b Mon Sep 17 00:00:00 2001 From: sbejaoui Date: Thu, 25 Jul 2019 13:02:07 +0200 Subject: [PATCH 07/42] [IMP] - manage substitution for mail.thread message_post_with_template --- report_substitute/__init__.py | 1 + report_substitute/__manifest__.py | 2 +- report_substitute/models/__init__.py | 1 + report_substitute/models/ir_actions_report.py | 35 +++++++++++++++---- report_substitute/models/mail_thread.py | 24 +++++++++++++ .../static/src/js/action_manager.js | 16 +++++---- report_substitute/views/ir_actions_report.xml | 6 ++-- report_substitute/wizards/__init__.py | 1 + .../wizards/mail_compose_message.py | 28 +++++++++++++++ 9 files changed, 97 insertions(+), 17 deletions(-) create mode 100644 report_substitute/models/mail_thread.py create mode 100644 report_substitute/wizards/__init__.py create mode 100644 report_substitute/wizards/mail_compose_message.py diff --git a/report_substitute/__init__.py b/report_substitute/__init__.py index 0ee8b5073e..1c15bc7eee 100644 --- a/report_substitute/__init__.py +++ b/report_substitute/__init__.py @@ -1,2 +1,3 @@ from . import models +from . import wizards from . import tests diff --git a/report_substitute/__manifest__.py b/report_substitute/__manifest__.py index f6061a75e5..82cac363a2 100644 --- a/report_substitute/__manifest__.py +++ b/report_substitute/__manifest__.py @@ -11,7 +11,7 @@ 'author': 'ACSONE SA/NV,' 'Odoo Community Association (OCA)', 'website': 'https://github.com/acsone/reporting-engine', - 'depends': ['base'], + 'depends': ['base', 'mail'], 'data': [ 'security/ir_actions_report_substitution_rule.xml', 'views/assets_backend.xml', diff --git a/report_substitute/models/__init__.py b/report_substitute/models/__init__.py index 27b9defe6e..a93fca4b48 100644 --- a/report_substitute/models/__init__.py +++ b/report_substitute/models/__init__.py @@ -1,2 +1,3 @@ from . import ir_actions_report from . import ir_actions_report_substitution_rule +from . import mail_thread diff --git a/report_substitute/models/ir_actions_report.py b/report_substitute/models/ir_actions_report.py index 88d7b50b69..e8c45b43a6 100644 --- a/report_substitute/models/ir_actions_report.py +++ b/report_substitute/models/ir_actions_report.py @@ -28,6 +28,18 @@ def _get_substitution_report(self, model, active_ids): return substitution_report_rule.substitution_action_report_id return False + @api.multi + def get_substitution_report(self, active_ids): + self.ensure_one() + action_report = self + substitution_report = action_report + while substitution_report: + action_report = substitution_report + substitution_report = action_report._get_substitution_report( + action_report.model, active_ids + ) + return action_report + @api.model def get_substitution_report_dict(self, action_report_dict, active_ids): if action_report_dict.get('id'): @@ -43,9 +55,20 @@ def get_substitution_report_dict(self, action_report_dict, active_ids): @api.multi def render(self, res_ids, data=None): - substitution_report = self._get_substitution_report( - self.model, res_ids - ) - if substitution_report: - return substitution_report.render(res_ids, data) - return super().render(res_ids, data) + substitution_report = self.get_substitution_report(res_ids) + return super(IrActionReport, substitution_report).render(res_ids, data) + + @api.noguess + def report_action(self, docids, data=None, config=True): + if docids: + if isinstance(docids, models.Model): + active_ids = docids.ids + elif isinstance(docids, int): + active_ids = [docids] + elif isinstance(docids, list): + active_ids = docids + substitution_report = self.get_substitution_report(active_ids) + return super(IrActionReport, substitution_report).report_action( + docids, data, config + ) + return super().report_action(docids, data, config) diff --git a/report_substitute/models/mail_thread.py b/report_substitute/models/mail_thread.py new file mode 100644 index 0000000000..7f1a236fdc --- /dev/null +++ b/report_substitute/models/mail_thread.py @@ -0,0 +1,24 @@ +# Copyright 2019 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, models + + +class MailThread(models.AbstractModel): + + _inherit = 'mail.thread' + + @api.multi + def message_post_with_template(self, template_id, **kwargs): + template = self.env['mail.template'].browse(template_id) + old_report = False + if template and template.report_template and self.ids: + active_ids = self.ids + old_report = template.report_template + template.report_template = old_report.get_substitution_report( + active_ids + ) + res = super().message_post_with_template(template_id, **kwargs) + if old_report: + template.report_template = old_report + return res diff --git a/report_substitute/static/src/js/action_manager.js b/report_substitute/static/src/js/action_manager.js index 754dd70d49..3f7bc14fc2 100644 --- a/report_substitute/static/src/js/action_manager.js +++ b/report_substitute/static/src/js/action_manager.js @@ -1,27 +1,29 @@ // Copyright 2019 ACSONE SA/NV // License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -odoo.define('report_substitute.action_report_substitute', function(require) { +odoo.define("report_substitute.action_report_substitute", function (require) { "use strict"; - var ActionManager = require('web.ActionManager'); + var ActionManager = require("web.ActionManager"); ActionManager.include({ + /** * Intercept action handling substitute the report action * @override */ - _handleAction: function(action, options) { - if (action.type === 'ir.actions.report' && + + _handleAction: function (action, options) { + if (action.type === "ir.actions.report" && action.context.active_ids) { var active_ids = action.context.active_ids; var self = this; var _super = this._super; var callersArguments = arguments; return this._rpc({ - model: 'ir.actions.report', - method: 'get_substitution_report_dict', + model: "ir.actions.report", + method: "get_substitution_report_dict", args: [action, active_ids] - }).then(function(action_id) { + }).then(function (action_id) { callersArguments[0] = action_id return _super.apply(self, callersArguments); }); diff --git a/report_substitute/views/ir_actions_report.xml b/report_substitute/views/ir_actions_report.xml index 0c2c265c8e..c5f9cb142b 100644 --- a/report_substitute/views/ir_actions_report.xml +++ b/report_substitute/views/ir_actions_report.xml @@ -16,8 +16,7 @@ - /> + @@ -26,7 +25,8 @@ invisible="1" readonly="1" required="0"/> - + Date: Fri, 26 Jul 2019 16:15:31 +0200 Subject: [PATCH 08/42] [IMP] - add unit tests --- report_substitute/models/ir_actions_report.py | 10 +++--- .../static/src/js/action_manager.js | 12 ++++--- .../tests/test_report_substitute.py | 18 ++++++++++ .../wizards/mail_compose_message.py | 33 ++++++++++--------- 4 files changed, 48 insertions(+), 25 deletions(-) diff --git a/report_substitute/models/ir_actions_report.py b/report_substitute/models/ir_actions_report.py index e8c45b43a6..a987b24f1d 100644 --- a/report_substitute/models/ir_actions_report.py +++ b/report_substitute/models/ir_actions_report.py @@ -41,17 +41,17 @@ def get_substitution_report(self, active_ids): return action_report @api.model - def get_substitution_report_dict(self, action_report_dict, active_ids): - if action_report_dict.get('id'): - action_report = self.browse(action_report_dict['id']) + def get_substitution_report_action(self, action, active_ids): + if action.get('id'): + action_report = self.browse(action['id']) substitution_report = action_report while substitution_report: action_report = substitution_report substitution_report = action_report._get_substitution_report( action_report.model, active_ids ) - action_report_dict.update(action_report.read()[0]) - return action_report_dict + action.update(action_report.read()[0]) + return action @api.multi def render(self, res_ids, data=None): diff --git a/report_substitute/static/src/js/action_manager.js b/report_substitute/static/src/js/action_manager.js index 3f7bc14fc2..6e4e8f8dee 100644 --- a/report_substitute/static/src/js/action_manager.js +++ b/report_substitute/static/src/js/action_manager.js @@ -14,17 +14,19 @@ odoo.define("report_substitute.action_report_substitute", function (require) { _handleAction: function (action, options) { if (action.type === "ir.actions.report" && - action.context.active_ids) { + action.context.active_ids && + action.action_report_substitution_rule_ids && + action.action_report_substitution_rule_ids != 0) { var active_ids = action.context.active_ids; var self = this; var _super = this._super; var callersArguments = arguments; return this._rpc({ model: "ir.actions.report", - method: "get_substitution_report_dict", + method: "get_substitution_report_action", args: [action, active_ids] - }).then(function (action_id) { - callersArguments[0] = action_id + }).then(function (substitution_action) { + callersArguments[0] = substitution_action return _super.apply(self, callersArguments); }); @@ -34,4 +36,4 @@ odoo.define("report_substitute.action_report_substitute", function (require) { }); -}); +}); \ No newline at end of file diff --git a/report_substitute/tests/test_report_substitute.py b/report_substitute/tests/test_report_substitute.py index fecb4be6c0..75065bd03f 100644 --- a/report_substitute/tests/test_report_substitute.py +++ b/report_substitute/tests/test_report_substitute.py @@ -46,3 +46,21 @@ def test_substitution_with_domain(self): self.substitution_rule.write({'domain': "[('name', '!=', 'base')]"}) res = str(self.action_report.render(res_ids=self.res_ids)[0]) self.assertNotIn('
    Substitution Report
    ', res) + + def test_substitution_with_action_dict(self): + substitution_report_action = self.env[ + 'ir.actions.report' + ].get_substitution_report_action( + self.action_report.read()[0], self.res_ids + ) + self.assertEqual( + substitution_report_action['id'], + self.substitution_rule.substitution_action_report_id.id, + ) + + def test_substitution_with_report_action(self): + res = self.action_report.report_action(self.res_ids) + self.assertEqual( + res['report_name'], + self.substitution_rule.substitution_action_report_id.report_name, + ) diff --git a/report_substitute/wizards/mail_compose_message.py b/report_substitute/wizards/mail_compose_message.py index c0d37a7049..bdb6f844ad 100644 --- a/report_substitute/wizards/mail_compose_message.py +++ b/report_substitute/wizards/mail_compose_message.py @@ -11,18 +11,21 @@ class MailComposeMessage(models.TransientModel): @api.multi @api.onchange('template_id') def onchange_template_id_wrapper(self): - old_report_template = False - if ( - self.template_id - and self.template_id.report_template - and self.env.context.get('active_ids') - ): - active_ids = self.env.context.get('active_ids') - old_report_template = self.template_id.report_template - self.template_id.report_template = ( - old_report_template.get_substitution_report(active_ids) - ) - res = super().onchange_template_id_wrapper() - if old_report_template: - self.template_id.report_template = old_report_template - return res + if self.template_id: + report_template = self.template_id.report_template + if ( + report_template + and report_template.action_report_substitution_rule_ids + and self.env.context.get('active_ids') + ): + active_ids = self.env.context.get('active_ids') + old_report_template = report_template + self.template_id.report_template = ( + old_report_template.get_substitution_report(active_ids) + ) + onchange_result_with_substituted_report = ( + super().onchange_template_id_wrapper() + ) + self.template_id.report_template = old_report_template + return onchange_result_with_substituted_report + return super().onchange_template_id_wrapper() From c1e11ac4ebca9db27b7a8597b6f14e91da7feac7 Mon Sep 17 00:00:00 2001 From: sbejaoui Date: Fri, 2 Aug 2019 11:02:35 +0200 Subject: [PATCH 09/42] [FIX] - manage the case where mail.compose.message is triggered from the chatter --- report_substitute/wizards/mail_compose_message.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/report_substitute/wizards/mail_compose_message.py b/report_substitute/wizards/mail_compose_message.py index bdb6f844ad..d5ab37ff11 100644 --- a/report_substitute/wizards/mail_compose_message.py +++ b/report_substitute/wizards/mail_compose_message.py @@ -13,12 +13,16 @@ class MailComposeMessage(models.TransientModel): def onchange_template_id_wrapper(self): if self.template_id: report_template = self.template_id.report_template + active_ids = [] + if self.env.context.get('active_ids'): + active_ids = self.env.context.get('active_ids') + elif self.env.context.get('default_res_id'): + active_ids = [self.env.context.get('default_res_id')] if ( report_template and report_template.action_report_substitution_rule_ids - and self.env.context.get('active_ids') + and active_ids ): - active_ids = self.env.context.get('active_ids') old_report_template = report_template self.template_id.report_template = ( old_report_template.get_substitution_report(active_ids) From c184e2bc7a3797d1274fff68af52629e066f3b0c Mon Sep 17 00:00:00 2001 From: sbejaoui Date: Tue, 1 Oct 2019 15:42:23 +0200 Subject: [PATCH 10/42] [FIX] - Fix typo --- report_substitute/views/ir_actions_report.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/report_substitute/views/ir_actions_report.xml b/report_substitute/views/ir_actions_report.xml index c5f9cb142b..e8ab9991f9 100644 --- a/report_substitute/views/ir_actions_report.xml +++ b/report_substitute/views/ir_actions_report.xml @@ -5,8 +5,7 @@ - ir.actions.report.form (in report_dispatch_base) - + ir.actions.report.form (in report_substitute) ir.actions.report From e23f5f11a379e7a4bf4c5de2637164d259823fe8 Mon Sep 17 00:00:00 2001 From: sbejaoui Date: Tue, 1 Oct 2019 23:35:11 +0200 Subject: [PATCH 11/42] [12.0][IMP] - Add check for substitution infinite loop --- report_substitute/__manifest__.py | 2 +- .../ir_actions_report_substitution_rule.py | 23 +++++++++++++++++-- .../tests/test_report_substitute.py | 14 +++++++++++ 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/report_substitute/__manifest__.py b/report_substitute/__manifest__.py index 82cac363a2..1dab69dc81 100644 --- a/report_substitute/__manifest__.py +++ b/report_substitute/__manifest__.py @@ -10,7 +10,7 @@ 'license': 'AGPL-3', 'author': 'ACSONE SA/NV,' 'Odoo Community Association (OCA)', - 'website': 'https://github.com/acsone/reporting-engine', + 'website': 'https://github.com/OCA/reporting-engine', 'depends': ['base', 'mail'], 'data': [ 'security/ir_actions_report_substitution_rule.xml', diff --git a/report_substitute/models/ir_actions_report_substitution_rule.py b/report_substitute/models/ir_actions_report_substitution_rule.py index 4c72507111..1f5d936fd7 100644 --- a/report_substitute/models/ir_actions_report_substitution_rule.py +++ b/report_substitute/models/ir_actions_report_substitution_rule.py @@ -1,7 +1,8 @@ # Copyright 2019 ACSONE SA/NV # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo import fields, models +from odoo import fields, models, api, _ +from odoo.exceptions import ValidationError class ActionsReportSubstitutionRule(models.Model): @@ -24,5 +25,23 @@ class ActionsReportSubstitutionRule(models.Model): string="Substitution Report Action", required=True, ondelete="cascade", - domain="[('model', '=', model)]" + domain="[('model', '=', model)]", ) + + @api.constrains('substitution_action_report_id', 'action_report_id') + def _check_substitution_infinite_loop(self): + def _check_infinite_loop(original_report, substitution_report): + if original_report == substitution_report: + raise ValidationError(_("Substitution infinite loop detected")) + for ( + substitution_rule + ) in substitution_report.action_report_substitution_rule_ids: + _check_infinite_loop( + original_report, + substitution_rule.substitution_action_report_id, + ) + + for rec in self: + _check_infinite_loop( + rec.action_report_id, rec.substitution_action_report_id + ) diff --git a/report_substitute/tests/test_report_substitute.py b/report_substitute/tests/test_report_substitute.py index 75065bd03f..3a3d2fbd3c 100644 --- a/report_substitute/tests/test_report_substitute.py +++ b/report_substitute/tests/test_report_substitute.py @@ -2,6 +2,7 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from odoo.tests.common import TransactionCase +from odoo.exceptions import ValidationError class TestReportSubstitute(TransactionCase): @@ -64,3 +65,16 @@ def test_substitution_with_report_action(self): res['report_name'], self.substitution_rule.substitution_action_report_id.report_name, ) + + def test_substitution_infinite_loop(self): + with self.assertRaises(ValidationError): + self.env['ir.actions.report.substitution.rule'].create( + { + 'action_report_id': self.env.ref( + 'report_substitute.substitution_report_print' + ).id, + 'substitution_action_report_id': self.env.ref( + 'base.ir_module_reference_print' + ).id, + } + ) From 5a60e34b1edd54638e5e67a9a6af58b261b24a32 Mon Sep 17 00:00:00 2001 From: oca-travis Date: Mon, 21 Oct 2019 15:02:35 +0000 Subject: [PATCH 12/42] [UPD] Update report_substitute.pot --- report_substitute/i18n/report_substitute.pot | 123 +++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 report_substitute/i18n/report_substitute.pot diff --git a/report_substitute/i18n/report_substitute.pot b/report_substitute/i18n/report_substitute.pot new file mode 100644 index 0000000000..a2852a637a --- /dev/null +++ b/report_substitute/i18n/report_substitute.pot @@ -0,0 +1,123 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * report_substitute +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.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: report_substitute +#: model:ir.model,name:report_substitute.model_ir_actions_report_substitution_rule +msgid "Action Report Substitution Rule" +msgstr "" + +#. module: report_substitute +#: model:ir.model.fields,field_description:report_substitute.field_ir_actions_report_substitution_rule__create_uid +msgid "Created by" +msgstr "" + +#. module: report_substitute +#: model:ir.model.fields,field_description:report_substitute.field_ir_actions_report_substitution_rule__create_date +msgid "Created on" +msgstr "" + +#. module: report_substitute +#: model:ir.model.fields,field_description:report_substitute.field_ir_actions_report_substitution_rule__display_name +msgid "Display Name" +msgstr "" + +#. module: report_substitute +#: model:ir.model.fields,field_description:report_substitute.field_ir_actions_report_substitution_rule__domain +msgid "Domain" +msgstr "" + +#. module: report_substitute +#: model:ir.model,name:report_substitute.model_mail_thread +msgid "Email Thread" +msgstr "" + +#. module: report_substitute +#: model:ir.model,name:report_substitute.model_mail_compose_message +msgid "Email composition wizard" +msgstr "" + +#. module: report_substitute +#: model:ir.model.fields,field_description:report_substitute.field_ir_actions_report_substitution_rule__id +msgid "ID" +msgstr "" + +#. module: report_substitute +#: model:ir.model.fields,field_description:report_substitute.field_ir_actions_report_substitution_rule____last_update +msgid "Last Modified on" +msgstr "" + +#. module: report_substitute +#: model:ir.model.fields,field_description:report_substitute.field_ir_actions_report_substitution_rule__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: report_substitute +#: model:ir.model.fields,field_description:report_substitute.field_ir_actions_report_substitution_rule__write_date +msgid "Last Updated on" +msgstr "" + +#. module: report_substitute +#: model:ir.model.fields,field_description:report_substitute.field_ir_actions_report_substitution_rule__model +msgid "Model Name" +msgstr "" + +#. module: report_substitute +#: model:ir.model,name:report_substitute.model_ir_actions_report +#: model:ir.model.fields,field_description:report_substitute.field_ir_actions_report_substitution_rule__action_report_id +msgid "Report Action" +msgstr "" + +#. module: report_substitute +#: model:ir.model.fields,field_description:report_substitute.field_ir_actions_report_substitution_rule__sequence +msgid "Sequence" +msgstr "" + +#. module: report_substitute +#: model:ir.actions.report,name:report_substitute.substitution_report_print_2 +msgid "Substitution 2 For Technical guide" +msgstr "" + +#. module: report_substitute +#: model:ir.actions.report,name:report_substitute.substitution_report_print +msgid "Substitution For Technical guide" +msgstr "" + +#. module: report_substitute +#: model_terms:ir.ui.view,arch_db:report_substitute.substitution_report +msgid "Substitution Report" +msgstr "" + +#. module: report_substitute +#: model_terms:ir.ui.view,arch_db:report_substitute.substitution_report_2 +msgid "Substitution Report 2" +msgstr "" + +#. module: report_substitute +#: model:ir.model.fields,field_description:report_substitute.field_ir_actions_report_substitution_rule__substitution_action_report_id +msgid "Substitution Report Action" +msgstr "" + +#. module: report_substitute +#: model:ir.model.fields,field_description:report_substitute.field_ir_actions_report__action_report_substitution_rule_ids +#: model_terms:ir.ui.view,arch_db:report_substitute.ir_actions_report_form_view +msgid "Substitution Rules" +msgstr "" + +#. module: report_substitute +#: code:addons/report_substitute/models/ir_actions_report_substitution_rule.py:35 +#, python-format +msgid "Substitution infinite loop detected" +msgstr "" + From b3f5a97b9efa871642116329384e084d6762fd45 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Mon, 21 Oct 2019 15:27:21 +0000 Subject: [PATCH 13/42] [UPD] README.rst --- report_substitute/static/description/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/report_substitute/static/description/index.html b/report_substitute/static/description/index.html index 71e4b31b6f..8bc8afce0b 100644 --- a/report_substitute/static/description/index.html +++ b/report_substitute/static/description/index.html @@ -3,7 +3,7 @@ - + Report Substitute -
    -

    Report Substitute

    +
    + + +Odoo Community Association + +
    +

    Report Substitute

    -

    Beta License: AGPL-3 OCA/reporting-engine Translate me on Weblate Try me on Runboat

    +

    Beta License: AGPL-3 OCA/reporting-engine Translate me on Weblate Try me on Runboat

    This module allows you to create substitution rules for report actions. A typical use case is to replace a standard report by alternative reports when some conditions are met. For instance, it allows to @@ -388,7 +394,7 @@

    Report Substitute

    -

    Usage

    +

    Usage

    To use this module, you need to:

    1. Go to ‘Actions’ / ‘Reports’
    2. @@ -401,14 +407,14 @@

      Usage

      substitution in with a domain that matches all records.

    -

    Known issues / Roadmap

    +

    Known issues / Roadmap

    • The document name result should take the name of the substitution report.
    -

    Bug Tracker

    +

    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 @@ -416,23 +422,25 @@

    Bug Tracker

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

    -

    Credits

    +

    Credits

    -

    Authors

    +

    Authors

    • ACSONE SA/NV
    -

    Maintainers

    +

    Maintainers

    This module is maintained by the OCA.

    -Odoo Community Association + +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.

    @@ -443,5 +451,6 @@

    Maintainers

    +
    From d7ce58bbea0ce9bc8e01becbb6f3b0da2c796992 Mon Sep 17 00:00:00 2001 From: oca-ci Date: Tue, 16 Dec 2025 20:00:43 +0000 Subject: [PATCH 39/42] [UPD] Update report_substitute.pot --- report_substitute/i18n/report_substitute.pot | 1 + 1 file changed, 1 insertion(+) diff --git a/report_substitute/i18n/report_substitute.pot b/report_substitute/i18n/report_substitute.pot index 8de9403202..c46afb589a 100644 --- a/report_substitute/i18n/report_substitute.pot +++ b/report_substitute/i18n/report_substitute.pot @@ -101,6 +101,7 @@ msgstr "" #. module: report_substitute #: model:ir.model.fields,field_description:report_substitute.field_ir_actions_report__action_report_substitution_rule_ids +#: model:ir.model.fields,field_description:report_substitute.field_report_pdf_form__action_report_substitution_rule_ids #: model_terms:ir.ui.view,arch_db:report_substitute.ir_actions_report_form_view msgid "Substitution Rules" msgstr "" From f4d789c1c0c8047a1377d78fbef45ab90f8f206c Mon Sep 17 00:00:00 2001 From: Weblate Date: Tue, 16 Dec 2025 20:04:28 +0000 Subject: [PATCH 40/42] Update translation files Updated by "Update PO files to match POT (msgmerge)" hook in Weblate. Translation: reporting-engine-18.0/reporting-engine-18.0-report_substitute Translate-URL: https://translation.odoo-community.org/projects/reporting-engine-18-0/reporting-engine-18-0-report_substitute/ --- report_substitute/i18n/es.po | 2 +- report_substitute/i18n/it.po | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/report_substitute/i18n/es.po b/report_substitute/i18n/es.po index d4140205fa..97d57aee24 100644 --- a/report_substitute/i18n/es.po +++ b/report_substitute/i18n/es.po @@ -104,6 +104,7 @@ msgstr "Acción del informe de sustitución" #. module: report_substitute #: model:ir.model.fields,field_description:report_substitute.field_ir_actions_report__action_report_substitution_rule_ids +#: model:ir.model.fields,field_description:report_substitute.field_report_pdf_form__action_report_substitution_rule_ids #: model_terms:ir.ui.view,arch_db:report_substitute.ir_actions_report_form_view msgid "Substitution Rules" msgstr "Reglas de sustitución" @@ -111,7 +112,6 @@ msgstr "Reglas de sustitución" #. module: report_substitute #. odoo-python #: code:addons/report_substitute/models/ir_actions_report_substitution_rule.py:0 -#, python-format msgid "Substitution infinite loop detected" msgstr "Detectado bucle infinito de sustitución" diff --git a/report_substitute/i18n/it.po b/report_substitute/i18n/it.po index ef9d4a61aa..7badc71d77 100644 --- a/report_substitute/i18n/it.po +++ b/report_substitute/i18n/it.po @@ -104,6 +104,7 @@ msgstr "Azione resoconto sostituzione" #. module: report_substitute #: model:ir.model.fields,field_description:report_substitute.field_ir_actions_report__action_report_substitution_rule_ids +#: model:ir.model.fields,field_description:report_substitute.field_report_pdf_form__action_report_substitution_rule_ids #: model_terms:ir.ui.view,arch_db:report_substitute.ir_actions_report_form_view msgid "Substitution Rules" msgstr "Regole sostituzione" @@ -111,6 +112,5 @@ msgstr "Regole sostituzione" #. module: report_substitute #. odoo-python #: code:addons/report_substitute/models/ir_actions_report_substitution_rule.py:0 -#, python-format msgid "Substitution infinite loop detected" msgstr "Rilevato ciclo infinito sostituzione" From 5f44e124e69220b4bb846d43210cf98338e30641 Mon Sep 17 00:00:00 2001 From: Domenico Stragapede Date: Wed, 5 Aug 2026 11:52:34 +0200 Subject: [PATCH 41/42] [IMP] report_substitute: pre-commit auto fixes --- report_substitute/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/report_substitute/__manifest__.py b/report_substitute/__manifest__.py index 2fc579a461..9e342301fc 100644 --- a/report_substitute/__manifest__.py +++ b/report_substitute/__manifest__.py @@ -8,7 +8,7 @@ """, "version": "18.0.1.0.0", "license": "AGPL-3", - "author": "ACSONE SA/NV," "Odoo Community Association (OCA)", + "author": "ACSONE SA/NV,Odoo Community Association (OCA)", "website": "https://github.com/OCA/reporting-engine", "depends": ["base", "mail"], "data": [ From 86f382bed833ba9478b9b97e374299de9e5cfa55 Mon Sep 17 00:00:00 2001 From: Domenico Stragapede Date: Wed, 5 Aug 2026 15:51:28 +0200 Subject: [PATCH 42/42] [19.0][MIG] report_substitute: Migration to 19.0 --- report_substitute/README.rst | 10 +- report_substitute/__manifest__.py | 2 +- report_substitute/models/mail_thread.py | 16 +-- .../static/description/index.html | 6 +- .../static/src/js/action_manager.esm.js | 2 +- .../tests/test_report_substitute.py | 100 ++++++++++++++---- 6 files changed, 95 insertions(+), 41 deletions(-) diff --git a/report_substitute/README.rst b/report_substitute/README.rst index 5607564f5b..120fcc1376 100644 --- a/report_substitute/README.rst +++ b/report_substitute/README.rst @@ -21,13 +21,13 @@ Report Substitute :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Freporting--engine-lightgray.png?logo=github - :target: https://github.com/OCA/reporting-engine/tree/18.0/report_substitute + :target: https://github.com/OCA/reporting-engine/tree/19.0/report_substitute :alt: OCA/reporting-engine .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/reporting-engine-18-0/reporting-engine-18-0-report_substitute + :target: https://translation.odoo-community.org/projects/reporting-engine-19-0/reporting-engine-19-0-report_substitute :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/reporting-engine&target_branch=18.0 + :target: https://runboat.odoo-community.org/builds?repo=OCA/reporting-engine&target_branch=19.0 :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| @@ -68,7 +68,7 @@ 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 `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -106,6 +106,6 @@ Current `maintainer `__: |maintainer-sbejaoui| -This module is part of the `OCA/reporting-engine `_ project on GitHub. +This module is part of the `OCA/reporting-engine `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/report_substitute/__manifest__.py b/report_substitute/__manifest__.py index 9e342301fc..010a88bb0e 100644 --- a/report_substitute/__manifest__.py +++ b/report_substitute/__manifest__.py @@ -6,7 +6,7 @@ "summary": """ This module allows to create substitution rules for report actions. """, - "version": "18.0.1.0.0", + "version": "19.0.1.0.0", "license": "AGPL-3", "author": "ACSONE SA/NV,Odoo Community Association (OCA)", "website": "https://github.com/OCA/reporting-engine", diff --git a/report_substitute/models/mail_thread.py b/report_substitute/models/mail_thread.py index f468903c3a..c83b38bf1b 100644 --- a/report_substitute/models/mail_thread.py +++ b/report_substitute/models/mail_thread.py @@ -27,17 +27,17 @@ def message_post_with_source( self.with_context(default_report_template_ids=new_report_template_ids), ).message_post_with_source( source_ref, - render_values, - message_type, - subtype_xmlid, - subtype_id, + render_values=render_values, + message_type=message_type, + subtype_xmlid=subtype_xmlid, + subtype_id=subtype_id, **kwargs, ) return super().message_post_with_source( source_ref, - render_values, - message_type, - subtype_xmlid, - subtype_id, + render_values=render_values, + message_type=message_type, + subtype_xmlid=subtype_xmlid, + subtype_id=subtype_id, **kwargs, ) diff --git a/report_substitute/static/description/index.html b/report_substitute/static/description/index.html index e2aca6dd3f..8410c8a017 100644 --- a/report_substitute/static/description/index.html +++ b/report_substitute/static/description/index.html @@ -374,7 +374,7 @@

    Report Substitute

    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! source digest: sha256:b2a85461ade5dd5f30d8cdec1f353002db6baf217f8d0584c7708046843b8076 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

    Beta License: AGPL-3 OCA/reporting-engine Translate me on Weblate Try me on Runboat

    +

    Beta License: AGPL-3 OCA/reporting-engine Translate me on Weblate Try me on Runboat

    This module allows you to create substitution rules for report actions. A typical use case is to replace a standard report by alternative reports when some conditions are met. For instance, it allows to @@ -418,7 +418,7 @@

    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.

    +feedback.

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

    @@ -446,7 +446,7 @@

    Maintainers

    promote its widespread use.

    Current maintainer:

    sbejaoui

    -

    This module is part of the OCA/reporting-engine project on GitHub.

    +

    This module is part of the OCA/reporting-engine project on GitHub.

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

    diff --git a/report_substitute/static/src/js/action_manager.esm.js b/report_substitute/static/src/js/action_manager.esm.js index 352b89b706..89402db7e2 100644 --- a/report_substitute/static/src/js/action_manager.esm.js +++ b/report_substitute/static/src/js/action_manager.esm.js @@ -15,7 +15,7 @@ registry action_report_substitution_rule_ids && action_report_substitution_rule_ids.length !== 0 ) { - var active_ids = action.context.active_ids; + const active_ids = action.context.active_ids; const substitution = await orm.call( "ir.actions.report", "get_substitution_report_action", diff --git a/report_substitute/tests/test_report_substitute.py b/report_substitute/tests/test_report_substitute.py index 6772b976c7..2c47463f8c 100644 --- a/report_substitute/tests/test_report_substitute.py +++ b/report_substitute/tests/test_report_substitute.py @@ -2,23 +2,85 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from odoo.exceptions import ValidationError -from odoo.tests.common import TransactionCase +from odoo.tests.common import TransactionCase, tagged +@tagged("post_install", "-at_install") class TestReportSubstitute(TransactionCase): - def setUp(self): - # In the demo file we create a new report for ir.module.module model - # with a substation rule from the original report action - super().setUp() - self.action_report = self.env.ref("base.ir_module_reference_print") - self.res_ids = self.env.ref("base.module_base").ids - self.substitution_rule = self.env.ref( - "report_substitute.substitution_rule_demo_1" - ) - self.env.company.external_report_layout_id = self.env.ref( + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.action_report = cls.env.ref("base.ir_module_reference_print") + cls.res_ids = cls.env.ref("base.module_base").ids + cls.env.company.external_report_layout_id = cls.env.ref( "web.external_layout_standard" ).id + cls.substitution_report_test_view = cls.env["ir.ui.view"].create( + { + "name": "substitution_report_test", + "key": "substitution_report_test", + "type": "qweb", + "arch": '' + '
    Substitution Report
    ' + "
    ", + } + ) + cls.env["ir.model.data"].create( + { + "model": "ir.ui.view", + "module": "report_substitute", + "name": "substitution_report_test", + "res_id": cls.substitution_report_test_view.id, + } + ) + + cls.substitution_report_2_test_view = cls.env["ir.ui.view"].create( + { + "key": "substitution_report_2_test", + "name": "substitution_report_2_test", + "type": "qweb", + "arch": '' + '
    Substitution Report 2
    ' + "
    ", + } + ) + cls.env["ir.model.data"].create( + { + "model": "ir.ui.view", + "module": "report_substitute", + "name": "substitution_report_2_test", + "res_id": cls.substitution_report_2_test_view.id, + } + ) + + cls.substitution_report = cls.env["ir.actions.report"].create( + { + "name": "Substitution For Technical guide", + "model": "ir.module.module", + "report_type": "qweb-pdf", + "report_name": "report_substitute.substitution_report_test", + "report_file": "report_substitute.substitution_report_test", + "binding_type": "report", + } + ) + cls.substitution_report_2 = cls.env["ir.actions.report"].create( + { + "name": "Substitution 2 For Technical guide", + "model": "ir.module.module", + "report_type": "qweb-pdf", + "report_name": "report_substitute.substitution_report_2_test", + "report_file": "report_substitute.substitution_report_2_test", + "binding_type": "report", + } + ) + cls.substitution_rule = cls.env["ir.actions.report.substitution.rule"].create( + { + "action_report_id": cls.action_report.id, + "substitution_action_report_id": cls.substitution_report.id, + } + ) + def test_substitution(self): res = str( self.action_report._render( @@ -44,12 +106,8 @@ def test_recursive_substitution(self): self.assertNotIn('
    Substitution Report 2
    ', res) self.env["ir.actions.report.substitution.rule"].create( { - "substitution_action_report_id": self.env.ref( - "report_substitute.substitution_report_print_2" - ).id, - "action_report_id": self.env.ref( - "report_substitute.substitution_report_print" - ).id, + "substitution_action_report_id": self.substitution_report_2.id, + "action_report_id": self.substitution_report.id, } ) res = str( @@ -95,11 +153,7 @@ def test_substitution_infinite_loop(self): with self.assertRaises(ValidationError): self.env["ir.actions.report.substitution.rule"].create( { - "action_report_id": self.env.ref( - "report_substitute.substitution_report_print" - ).id, - "substitution_action_report_id": self.env.ref( - "base.ir_module_reference_print" - ).id, + "action_report_id": self.substitution_report.id, + "substitution_action_report_id": self.action_report.id, } )