diff --git a/base_exception/__manifest__.py b/base_exception/__manifest__.py
index 35e2c0be2..a7539eef7 100644
--- a/base_exception/__manifest__.py
+++ b/base_exception/__manifest__.py
@@ -18,6 +18,7 @@
'data': [
'security/base_exception_security.xml',
'security/ir.model.access.csv',
+ 'security/tmp_test_model_access_rule.xml',
'wizard/base_exception_confirm_view.xml',
'views/base_exception_view.xml',
],
diff --git a/base_exception/models/base_exception.py b/base_exception/models/base_exception.py
index 0eebb72cf..c62fba6c8 100644
--- a/base_exception/models/base_exception.py
+++ b/base_exception/models/base_exception.py
@@ -5,11 +5,15 @@
import time
from functools import wraps
+import os
+from odoo import api, fields, models, tools, _
+import logging
-from odoo import api, models, fields, _
from odoo.exceptions import UserError, ValidationError
from odoo.tools.safe_eval import safe_eval
+_logger = logging.getLogger(__name__)
+
def implemented_by_base_exception(func):
"""Call a prefixed function based on 'namespace'."""
@@ -45,15 +49,14 @@ class ExceptionRule(models.Model):
active = fields.Boolean('Active')
next_state = fields.Char(
'Next state',
- help="If we detect exception we set de state of object (ex purchase) "
+ help="If we detect exception we set the state of object (ex purchase) "
"to the next_state (ex 'to approve'). If there are more than one "
"exception detected and all have a value for next_state, we use"
"the exception having the smallest sequence value")
code = fields.Text(
'Python Code',
help="Python code executed to check if the exception apply or "
- "not. The code must apply block = True to apply the "
- "exception.",
+ "not. Use failed = True to block the exception",
default="""
# Python code. Use failed = True to block the base.exception.
# You can use the following variables :
@@ -63,7 +66,7 @@ class ExceptionRule(models.Model):
# base.exception line (ex rule_group = sale for sale order)
# - object: same as order or line, browse_record of the base.exception or
# base.exception line
-# - pool: ORM model pool (i.e. self.pool)
+# - env: Odoo Environment (i.e. self.env)
# - time: Python time module
# - cr: database cursor
# - uid: current user id
@@ -79,10 +82,10 @@ class ExceptionRule(models.Model):
select_vals = self.env[
rule.model].fields_get()[
'state']['selection']
- if rule.next_state\
- not in [s[0] for s in select_vals]:
+ select_vals_code = [s[0] for s in select_vals]
+ if rule.next_state not in select_vals_code:
raise ValidationError(
- _('The value "%s" you chose for the "next state" '
+ _('The value "%s" you choose for the "next state" '
'field state of "%s" is wrong.'
' Value must be in this list %s')
% (rule.next_state,
@@ -121,14 +124,14 @@ class BaseException(models.AbstractModel):
@api.multi
def _popup_exceptions(self):
action = self._get_popup_action()
- action = action.read()[0]
- action.update({
+ action_data = action.read()[0]
+ action_data.update({
'context': {
'active_id': self.ids[0],
'active_ids': self.ids
}
})
- return action
+ return action_data
@api.model
def _get_popup_action(self):
@@ -187,18 +190,17 @@ class BaseException(models.AbstractModel):
@api.model
def _exception_rule_eval_context(self, obj_name, rec):
- user = self.env['res.users'].browse(self._uid)
return {obj_name: rec,
- 'self': self.pool.get(rec._name),
+ 'self': self.env[rec._name],
'object': rec,
'obj': rec,
- 'pool': self.pool,
- 'cr': self._cr,
- 'uid': self._uid,
- 'user': user,
+ 'env': self.env,
+ 'cr': self.env.cr,
+ 'uid': self.env.user.id,
+ 'user': self.env.user,
'time': time,
# copy context to prevent side-effects of eval
- 'context': self._context.copy()}
+ 'context': self.env.context.copy()}
@api.model
def _rule_eval(self, rule, obj_name, rec):
@@ -225,10 +227,8 @@ class BaseException(models.AbstractModel):
if self._rule_eval(rule, self.rule_group, self):
exception_ids.append(rule.id)
if rule.next_state:
- if not next_state_rule:
- next_state_rule = rule
- elif next_state_rule and\
- rule.sequence < next_state_rule.sequence:
+ if not next_state_rule or\
+ rule.sequence < next_state_rule.sequence:
next_state_rule = rule
if sub_exceptions:
for obj_line in self._get_lines():
@@ -252,3 +252,28 @@ class BaseException(models.AbstractModel):
def _default_get_lines(self):
return []
+
+ @api.model
+ def _import_acl_for_tmp_test_model(self):
+ # import the access rule of temp test model only if testing
+ testing = tools.config.get('test_enable')\
+ or os.environ.get('ODOO_TEST_ENABLE')
+ if testing:
+ header = ['id', 'name', 'model_id:id', 'group_id:id',
+ 'perm_read', 'perm_write',
+ 'perm_create', 'perm_unlink']
+ IrModelAccess = self.env['ir.model.access']
+ acl_data = [
+ ['access_base_exception_test_purchase',
+ 'access_base_exception_test_purchase',
+ 'base_exception.model_base_exception_test_purchase',
+ 'base.group_system', '1', '1', '1', '1'],
+ ['access_base_exception_test_purchase_line',
+ 'access_base_exception_test_purchase_line',
+ 'base_exception.model_base_exception_test_purchase_line',
+ 'base.group_system', '1', '1', '1', '1']
+ ]
+
+ result = IrModelAccess.load(header, acl_data)
+ if result['messages']:
+ _logger.warning(result['messages'])
diff --git a/base_exception/security/ir.model.access.csv b/base_exception/security/ir.model.access.csv
index ad0cb33f9..38331a4f4 100644
--- a/base_exception/security/ir.model.access.csv
+++ b/base_exception/security/ir.model.access.csv
@@ -3,5 +3,3 @@ access_exception_rule,base.exception,model_exception_rule,base.group_user,1,0,0,
access_exception_rule_manager,base.exception,model_exception_rule,base_exception.group_exception_rule_manager,1,1,1,1
access_base_exception,base.exception,model_base_exception,base.group_user,1,0,0,0
access_base_exception_manager,base.exception,model_base_exception,base_exception.group_exception_rule_manager,1,1,1,1
-access_base_exception_test_purchase,access_base_exception_test_purchase,model_base_exception_test_purchase,base.group_system,1,1,1,1
-access_base_exception_test_model_line,access_base_exception_test_model_line,model_base_exception_test_model_line,base.group_system,1,1,1,1
\ No newline at end of file
diff --git a/base_exception/security/tmp_test_model_access_rule.xml b/base_exception/security/tmp_test_model_access_rule.xml
new file mode 100644
index 000000000..d104ea432
--- /dev/null
+++ b/base_exception/security/tmp_test_model_access_rule.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/base_exception/tests/test_tmp_model.py b/base_exception/tests/test_tmp_model.py
index a07367878..8612b6d05 100644
--- a/base_exception/tests/test_tmp_model.py
+++ b/base_exception/tests/test_tmp_model.py
@@ -1,71 +1,77 @@
# Copyright 2017 Akretion (http://www.akretion.com)
# Mourad EL HADJ MIMOUNE
+import os
+from odoo import api, fields, models, tools
+import logging
-from odoo import fields, models, api
+_logger = logging.getLogger(__name__)
+testing = tools.config.get('test_enable') or os.environ.get('ODOO_TEST_ENABLE')
+if testing:
+ class PurchaseTest(models.Model):
+ _inherit = 'base.exception'
+ _name = "base.exception.test.purchase"
+ _description = "Base Ecxeption Test Model"
-class PurchaseTest(models.Model):
- _inherit = 'base.exception'
- _name = "base.exception.test.purchase"
- _description = "Base Ecxeption Test Model"
+ rule_group = fields.Selection(
+ selection_add=[('test_base', 'test')],
+ default='test_base',
+ )
+ name = fields.Char(required=True)
+ user_id = fields.Many2one('res.users', string='Responsible')
+ state = fields.Selection(
+ [('draft', 'New'), ('cancel', 'Cancelled'),
+ ('purchase', 'Purchase'),
+ ('to approve', 'To approve'), ('done', 'Done')],
+ string="Status", readonly=True, default='draft')
+ active = fields.Boolean(default=True)
+ partner_id = fields.Many2one('res.partner', string='Partner')
+ line_ids = fields.One2many(
+ 'base.exception.test.purchase.line', 'lead_id')
+ amount_total = fields.Float(
+ compute='_compute_amount_total', store=True)
- rule_group = fields.Selection(
- selection_add=[('test_base', 'test')],
- default='test_base',
- )
- name = fields.Char(required=True)
- user_id = fields.Many2one('res.users', string='Responsible')
- state = fields.Selection(
- [('draft', 'New'), ('cancel', 'Cancelled'),
- ('purchase', 'Purchase'),
- ('to approve', 'To approve'), ('done', 'Done')],
- string="Status", readonly=True, default='draft')
- active = fields.Boolean(default=True)
- partner_id = fields.Many2one('res.partner', string='Partner')
- line_ids = fields.One2many('base.exception.test.model.line', 'lead_id')
- amount_total = fields.Float(compute='_compute_amount_total', store=True)
+ @api.depends('line_ids')
+ def _compute_amount_total(self):
+ for record in self:
+ for line in record.line_ids:
+ record.amount_total += line.amount * line.qty
- @api.depends('line_ids')
- def _compute_amount_total(self):
- for record in self:
- for line in record.line_ids:
- record.amount_total += line.amount * line.qty
+ @api.constrains('ignore_exception', 'line_ids', 'state')
+ def test_purchase_check_exception(self):
+ orders = self.filtered(lambda s: s.state == 'purchase')
+ if orders:
+ orders._check_exception()
- @api.constrains('ignore_exception', 'line_ids', 'state')
- def test_purchase_check_exception(self):
- orders = self.filtered(lambda s: s.state == 'purchase')
- if orders:
- orders._check_exception()
+ @api.multi
+ def button_approve(self, force=False):
+ self.write({'state': 'to approve'})
+ return {}
- @api.multi
- def button_approve(self, force=False):
- self.write({'state': 'to approve'})
- return {}
+ @api.multi
+ def button_draft(self):
+ self.write({'state': 'draft'})
+ return {}
- @api.multi
- def button_draft(self):
- self.write({'state': 'draft'})
- return {}
+ @api.multi
+ def button_confirm(self):
+ self.write({'state': 'purchase'})
+ return True
- @api.multi
- def button_confirm(self):
- self.write({'state': 'purchase'})
- return True
+ @api.multi
+ def button_cancel(self):
+ self.write({'state': 'cancel'})
- @api.multi
- def button_cancel(self):
- self.write({'state': 'cancel'})
+ def test_base_get_lines(self):
+ self.ensure_one()
+ return self.line_ids
- def test_base_get_lines(self):
- self.ensure_one()
- return self.line_ids
+ class LineTest(models.Model):
+ _name = "base.exception.test.purchase.line"
+ _description = "Base Ecxeption Test Model Line"
-
-class LineTest(models.Model):
- _name = "base.exception.test.model.line"
- _description = "Base Ecxeption Test Model Line"
-
- name = fields.Char()
- lead_id = fields.Many2one('base.exception.test.model', ondelete='cascade')
- qty = fields.Float()
- amount = fields.Float()
+ name = fields.Char()
+ lead_id = fields.Many2one('base.exception.test.purchase',
+ ondelete='cascade')
+ qty = fields.Float()
+ amount = fields.Float()
diff --git a/base_exception/wizard/base_exception_confirm.py b/base_exception/wizard/base_exception_confirm.py
index 9cb207f62..4ab485b8f 100644
--- a/base_exception/wizard/base_exception_confirm.py
+++ b/base_exception/wizard/base_exception_confirm.py
@@ -3,7 +3,8 @@
# Mourad EL HADJ MIMOUNE
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
-from odoo import api, fields, models
+from odoo import api, fields, models, _
+from odoo.exceptions import ValidationError
class ExceptionRuleConfirm(models.AbstractModel):
@@ -19,13 +20,15 @@ class ExceptionRuleConfirm(models.AbstractModel):
@api.model
def default_get(self, field_list):
res = super(ExceptionRuleConfirm, self).default_get(field_list)
- current_model = self._context.get('active_model')
+ current_model = self.env.context.get('active_model')
model_except_obj = self.env[current_model]
- active_ids = self._context.get('active_ids')
- assert len(active_ids) == 1, "Only 1 ID accepted, got %r" % active_ids
+ active_ids = self.env.context.get('active_ids')
+ if len(active_ids) > 1:
+ raise ValidationError(
+ _('Only 1 ID accepted, got %r.') % active_ids)
active_id = active_ids[0]
related_model_except = model_except_obj.browse(active_id)
- exception_ids = [e.id for e in related_model_except.exception_ids]
+ exception_ids = related_model_except.exception_ids.ids
res.update({'exception_ids': [(6, 0, exception_ids)]})
res.update({'related_model_id': active_id})
return res
diff --git a/base_exception/wizard/base_exception_confirm_view.xml b/base_exception/wizard/base_exception_confirm_view.xml
index e100c7ac6..a8ece8e33 100644
--- a/base_exception/wizard/base_exception_confirm_view.xml
+++ b/base_exception/wizard/base_exception_confirm_view.xml
@@ -33,5 +33,5 @@
form
new
-
+