From c1171b16920e0319f5f754d6af792187373725cc Mon Sep 17 00:00:00 2001 From: Cedric Collins Date: Wed, 30 Dec 2020 17:02:15 -0600 Subject: [PATCH 1/5] [ADD] sale_exception_portal: show exceptions on portal H4721 --- sale_exception_portal/__init__.py | 1 + sale_exception_portal/__manifest__.py | 22 ++++++ sale_exception_portal/models/__init__.py | 1 + sale_exception_portal/models/sale.py | 35 +++++++++ .../views/sale_portal_templates.xml | 75 +++++++++++++++++++ sale_exception_portal/views/sale_views.xml | 15 ++++ 6 files changed, 149 insertions(+) create mode 100644 sale_exception_portal/__init__.py create mode 100644 sale_exception_portal/__manifest__.py create mode 100644 sale_exception_portal/models/__init__.py create mode 100644 sale_exception_portal/models/sale.py create mode 100644 sale_exception_portal/views/sale_portal_templates.xml create mode 100644 sale_exception_portal/views/sale_views.xml diff --git a/sale_exception_portal/__init__.py b/sale_exception_portal/__init__.py new file mode 100644 index 00000000..0650744f --- /dev/null +++ b/sale_exception_portal/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/sale_exception_portal/__manifest__.py b/sale_exception_portal/__manifest__.py new file mode 100644 index 00000000..4846e95f --- /dev/null +++ b/sale_exception_portal/__manifest__.py @@ -0,0 +1,22 @@ +{ + 'name': 'Sale Exception Portal', + 'summary': 'Display sale exceptions on customer portal', + 'version': '13.0.1.0.0', + 'author': "Hibou Corp.", + 'category': 'Sale', + 'license': 'AGPL-3', + 'website': "https://hibou.io", + 'description': """ +Display sale exceptions on customer portal and prevent further action +""", + 'depends': [ + 'sale_exception', + ], + 'demo': [], + 'data': [ + 'views/sale_portal_templates.xml', + 'views/sale_views.xml', + ], + 'auto_install': False, + 'installable': True, +} diff --git a/sale_exception_portal/models/__init__.py b/sale_exception_portal/models/__init__.py new file mode 100644 index 00000000..8a0dc04e --- /dev/null +++ b/sale_exception_portal/models/__init__.py @@ -0,0 +1 @@ +from . import sale diff --git a/sale_exception_portal/models/sale.py b/sale_exception_portal/models/sale.py new file mode 100644 index 00000000..ae37d0b8 --- /dev/null +++ b/sale_exception_portal/models/sale.py @@ -0,0 +1,35 @@ +import time +from odoo import fields, models + + +class ExceptionRule(models.Model): + _inherit = 'exception.rule' + + website_description = fields.Text('Description for Website') + + +class SaleOrder(models.Model): + _inherit = 'sale.order' + + def _check_sale_order_exceptions(self): + so_exceptions = self.env['exception.rule'].search([('active', '=', True), + ('model', '=', 'sale.order'), + ('exception_type', '=', 'by_py_code')]) + + reasons = [] + + for ex in so_exceptions: + # Globals won't expose modules used in exception rules python code. + # They will have to be manually passed through params. ex [time] + # Locals() can be used instead of defined params, but can also cause buggy behavior on return + params = {'sale': self, 'exception': ex, 'time': time} + try: + exec(ex.code, globals(), params) + if 'failed' in params: + desc = ex.website_description or ex.description + message = {'title': ex.name, 'description': desc} + reasons.append(message) + except: + pass + + return reasons diff --git a/sale_exception_portal/views/sale_portal_templates.xml b/sale_exception_portal/views/sale_portal_templates.xml new file mode 100644 index 00000000..58d680ec --- /dev/null +++ b/sale_exception_portal/views/sale_portal_templates.xml @@ -0,0 +1,75 @@ + + + + + + diff --git a/sale_exception_portal/views/sale_views.xml b/sale_exception_portal/views/sale_views.xml new file mode 100644 index 00000000..e228739a --- /dev/null +++ b/sale_exception_portal/views/sale_views.xml @@ -0,0 +1,15 @@ + + + + + exception.rule.form.inherit + exception.rule + + + + + + + + + From 0ddff4eba7d18c2691f58f19cda4740312fb3e3d Mon Sep 17 00:00:00 2001 From: Cedric Collins Date: Fri, 26 Mar 2021 15:25:43 -0500 Subject: [PATCH 2/5] [IMP] sale_exception_portal: add tests and use safe_eval H5654 --- sale_exception_portal/models/sale.py | 8 +++- sale_exception_portal/tests/__init__.py | 1 + .../tests/test_check_so_exceptions.py | 43 +++++++++++++++++++ 3 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 sale_exception_portal/tests/__init__.py create mode 100644 sale_exception_portal/tests/test_check_so_exceptions.py diff --git a/sale_exception_portal/models/sale.py b/sale_exception_portal/models/sale.py index ae37d0b8..03c88689 100644 --- a/sale_exception_portal/models/sale.py +++ b/sale_exception_portal/models/sale.py @@ -1,5 +1,6 @@ import time from odoo import fields, models +from odoo.tools.safe_eval import safe_eval class ExceptionRule(models.Model): @@ -24,8 +25,11 @@ class SaleOrder(models.Model): # Locals() can be used instead of defined params, but can also cause buggy behavior on return params = {'sale': self, 'exception': ex, 'time': time} try: - exec(ex.code, globals(), params) - if 'failed' in params: + safe_eval(ex.code, + params, + mode='exec', + nocopy=True) # nocopy allows to return 'result' + if params.get('failed', False): desc = ex.website_description or ex.description message = {'title': ex.name, 'description': desc} reasons.append(message) diff --git a/sale_exception_portal/tests/__init__.py b/sale_exception_portal/tests/__init__.py new file mode 100644 index 00000000..0098975e --- /dev/null +++ b/sale_exception_portal/tests/__init__.py @@ -0,0 +1 @@ +from . import test_check_so_exceptions diff --git a/sale_exception_portal/tests/test_check_so_exceptions.py b/sale_exception_portal/tests/test_check_so_exceptions.py new file mode 100644 index 00000000..870ad1be --- /dev/null +++ b/sale_exception_portal/tests/test_check_so_exceptions.py @@ -0,0 +1,43 @@ +from odoo.tests.common import TransactionCase + + +class TestCheckSOExceptions(TransactionCase): + def setUp(self): + super(TestCheckSOExceptions, self).setUp() + + self.azure_customer = self.browse_ref('base.res_partner_12') + + self.exception_rule = self.env['exception.rule'].create({ + 'name': 'No Azure', + 'description': 'No sales to Azure', + 'active': True, + 'model': 'sale.order', + 'exception_type': 'by_py_code', + 'code': 'failed = sale.partner_id and sale.partner_id.id == %d' % self.azure_customer.id + }) + + self.sale_product = self.browse_ref('product.product_product_5') + self.sale_product.standard_price = 100.0 + + def test_00_check_so_exceptions(self): + sale_order = self.env['sale.order'].create({ + 'partner_id': self.azure_customer.id, + 'order_line': [(0, 0, { + 'product_id': self.sale_product.id, + 'product_uom_qty': 1.0, + 'price_unit': 50.0, # Set lower than 100.0 to trigger the exception + })], + }) + + exceptions = sale_order._check_sale_order_exceptions() + self.assertEqual(len(exceptions), 1) + self.assertEqual(exceptions[0].get('description'), 'No sales to Azure') + + self.exception_rule.website_description = 'Different message for website' + exceptions = sale_order._check_sale_order_exceptions() + self.assertEqual(len(exceptions), 1) + self.assertEqual(exceptions[0].get('description'), 'Different message for website') + + self.exception_rule.active = False + exceptions = sale_order._check_sale_order_exceptions() + self.assertEqual(len(exceptions), 0) From bba5b57fbe1c909a6928381227962d88702e3102 Mon Sep 17 00:00:00 2001 From: Cedric Collins Date: Sun, 28 Mar 2021 18:33:57 -0500 Subject: [PATCH 3/5] [MIG] sale_exception_portal: migrate to 14.0 H5654 --- sale_exception_portal/__manifest__.py | 2 +- sale_exception_portal/models/sale.py | 28 ++----------------- .../tests/test_check_so_exceptions.py | 2 +- 3 files changed, 5 insertions(+), 27 deletions(-) diff --git a/sale_exception_portal/__manifest__.py b/sale_exception_portal/__manifest__.py index 4846e95f..9002214e 100644 --- a/sale_exception_portal/__manifest__.py +++ b/sale_exception_portal/__manifest__.py @@ -1,7 +1,7 @@ { 'name': 'Sale Exception Portal', 'summary': 'Display sale exceptions on customer portal', - 'version': '13.0.1.0.0', + 'version': '14.0.1.0.0', 'author': "Hibou Corp.", 'category': 'Sale', 'license': 'AGPL-3', diff --git a/sale_exception_portal/models/sale.py b/sale_exception_portal/models/sale.py index 03c88689..76874b3c 100644 --- a/sale_exception_portal/models/sale.py +++ b/sale_exception_portal/models/sale.py @@ -1,6 +1,4 @@ -import time from odoo import fields, models -from odoo.tools.safe_eval import safe_eval class ExceptionRule(models.Model): @@ -13,27 +11,7 @@ class SaleOrder(models.Model): _inherit = 'sale.order' def _check_sale_order_exceptions(self): - so_exceptions = self.env['exception.rule'].search([('active', '=', True), - ('model', '=', 'sale.order'), - ('exception_type', '=', 'by_py_code')]) - - reasons = [] - - for ex in so_exceptions: - # Globals won't expose modules used in exception rules python code. - # They will have to be manually passed through params. ex [time] - # Locals() can be used instead of defined params, but can also cause buggy behavior on return - params = {'sale': self, 'exception': ex, 'time': time} - try: - safe_eval(ex.code, - params, - mode='exec', - nocopy=True) # nocopy allows to return 'result' - if params.get('failed', False): - desc = ex.website_description or ex.description - message = {'title': ex.name, 'description': desc} - reasons.append(message) - except: - pass - + exception_ids = self.detect_exceptions() + exceptions = self.env['exception.rule'].browse(exception_ids) + reasons = [{'title': ex.name, 'description': ex.website_description or ex.description} for ex in exceptions] return reasons diff --git a/sale_exception_portal/tests/test_check_so_exceptions.py b/sale_exception_portal/tests/test_check_so_exceptions.py index 870ad1be..daf7d1af 100644 --- a/sale_exception_portal/tests/test_check_so_exceptions.py +++ b/sale_exception_portal/tests/test_check_so_exceptions.py @@ -25,7 +25,7 @@ class TestCheckSOExceptions(TransactionCase): 'order_line': [(0, 0, { 'product_id': self.sale_product.id, 'product_uom_qty': 1.0, - 'price_unit': 50.0, # Set lower than 100.0 to trigger the exception + 'price_unit': 50.0, })], }) From 171da19871525ac48733e848f48650a13a4d06cf Mon Sep 17 00:00:00 2001 From: Cedric Collins Date: Sun, 16 Jan 2022 23:35:16 -0600 Subject: [PATCH 4/5] [MIG] sale_exception_portal: bump version and fix test exception --- sale_exception_portal/__manifest__.py | 2 +- sale_exception_portal/tests/test_check_so_exceptions.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sale_exception_portal/__manifest__.py b/sale_exception_portal/__manifest__.py index 9002214e..b41d9142 100644 --- a/sale_exception_portal/__manifest__.py +++ b/sale_exception_portal/__manifest__.py @@ -1,7 +1,7 @@ { 'name': 'Sale Exception Portal', 'summary': 'Display sale exceptions on customer portal', - 'version': '14.0.1.0.0', + 'version': '15.0.1.0.0', 'author': "Hibou Corp.", 'category': 'Sale', 'license': 'AGPL-3', diff --git a/sale_exception_portal/tests/test_check_so_exceptions.py b/sale_exception_portal/tests/test_check_so_exceptions.py index daf7d1af..7c0c3bae 100644 --- a/sale_exception_portal/tests/test_check_so_exceptions.py +++ b/sale_exception_portal/tests/test_check_so_exceptions.py @@ -13,7 +13,7 @@ class TestCheckSOExceptions(TransactionCase): 'active': True, 'model': 'sale.order', 'exception_type': 'by_py_code', - 'code': 'failed = sale.partner_id and sale.partner_id.id == %d' % self.azure_customer.id + 'code': 'failed = object.partner_id and object.partner_id.id == %d' % self.azure_customer.id }) self.sale_product = self.browse_ref('product.product_product_5') From 49ff1aaed24004a34732657c6d0c188026fb3aee Mon Sep 17 00:00:00 2001 From: Juan Pablo Ticse Date: Wed, 16 Aug 2023 17:48:20 +0000 Subject: [PATCH 5/5] [MIG] sale_exception_portal: Fixed views and updated manifest --- sale_exception_portal/__manifest__.py | 2 +- .../views/sale_portal_templates.xml | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/sale_exception_portal/__manifest__.py b/sale_exception_portal/__manifest__.py index b41d9142..79476897 100644 --- a/sale_exception_portal/__manifest__.py +++ b/sale_exception_portal/__manifest__.py @@ -1,7 +1,7 @@ { 'name': 'Sale Exception Portal', 'summary': 'Display sale exceptions on customer portal', - 'version': '15.0.1.0.0', + 'version': '16.0.1.0.0', 'author': "Hibou Corp.", 'category': 'Sale', 'license': 'AGPL-3', diff --git a/sale_exception_portal/views/sale_portal_templates.xml b/sale_exception_portal/views/sale_portal_templates.xml index 58d680ec..a3f7434b 100644 --- a/sale_exception_portal/views/sale_portal_templates.xml +++ b/sale_exception_portal/views/sale_portal_templates.xml @@ -6,16 +6,16 @@
  • - - Sign & Pay + Sign & Pay Accept & Sign - - -