Browse Source

[MIG] base_exception: Migration to 11.0

pull/1557/head
Mourad Elhadj Mimoune 7 years ago
committed by Iván Todorovich
parent
commit
90727a5d46
  1. 1
      base_exception/__init__.py
  2. 13
      base_exception/__manifest__.py
  3. 40
      base_exception/models/base_exception.py
  4. 12
      base_exception/security/ir.model.access.csv
  5. 4
      base_exception/tests/__init__.py
  6. 84
      base_exception/tests/test_base_exception.py
  7. 72
      base_exception/tests/test_tmp_model.py
  8. 3
      base_exception/views/base_exception_view.xml
  9. 2
      base_exception/wizard/base_exception_confirm.py
  10. 4
      base_exception/wizard/base_exception_confirm_view.xml

1
base_exception/__init__.py

@ -3,3 +3,4 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from . import wizard, models from . import wizard, models
from .tests import test_tmp_model

13
base_exception/__manifest__.py

@ -1,13 +1,18 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# © 2011 Raphaël Valyi, Renato Lima, Guewen Baconnier, Sodexis # © 2011 Raphaël Valyi, Renato Lima, Guewen Baconnier, Sodexis
# © 2017 Akretion (http://www.akretion.com)
# Mourad EL HADJ MIMOUNE <mourad.elhadj.mimoune@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
{'name': 'Exception Rule',
'version': '10.0.1.0.0',
{
'name': 'Exception Rule',
'version': '11.0.1.0.0',
'category': 'Generic Modules', 'category': 'Generic Modules',
'summary': """This module provide an abstract model to manage customizable
'summary': """
This module provide an abstract model to manage customizable
exceptions to be applied on different models (sale order, invoice, ...)""", exceptions to be applied on different models (sale order, invoice, ...)""",
'author': "Akretion, Sodexis, Camptocamp, Odoo Community Association (OCA)",
'author':
"Akretion, Sodexis, Camptocamp, Odoo Community Association (OCA)",
'website': 'http://www.akretion.com', 'website': 'http://www.akretion.com',
'depends': ['base_setup'], 'depends': ['base_setup'],
'license': 'AGPL-3', 'license': 'AGPL-3',

40
base_exception/models/base_exception.py

@ -1,5 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# © 2011 Raphaël Valyi, Renato Lima, Guewen Baconnier, Sodexis # © 2011 Raphaël Valyi, Renato Lima, Guewen Baconnier, Sodexis
# © 2017 Akretion (http://www.akretion.com)
# Mourad EL HADJ MIMOUNE <mourad.elhadj.mimoune@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import time import time
@ -42,6 +44,12 @@ class ExceptionRule(models.Model):
selection=[], selection=[],
string='Apply on', required=True) string='Apply on', required=True)
active = fields.Boolean('Active') active = fields.Boolean('Active')
next_state = fields.Char(
'Next state',
help="If we detect exception we set de 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( code = fields.Text(
'Python Code', 'Python Code',
help="Python code executed to check if the exception apply or " help="Python code executed to check if the exception apply or "
@ -63,6 +71,26 @@ class ExceptionRule(models.Model):
# - context: current context # - context: current context
""") """)
@api.constrains('next_state')
def _check_next_state_value(self):
""" Ensure that the next_state value is in the state values of
destination model """
for rule in self:
if rule.next_state:
select_vals = self.env[
rule.model].fields_get()[
'state']['selection']
if rule.next_state\
not in [s[0] for s in select_vals]:
raise ValidationError(
_('The value "%s" you chose for the "next state" '
'field state of "%s" is wrong.'
' Value must be in this list %s')
% (rule.next_state,
rule.model,
select_vals)
)
class BaseException(models.AbstractModel): class BaseException(models.AbstractModel):
_name = 'base.exception' _name = 'base.exception'
@ -182,7 +210,7 @@ class BaseException(models.AbstractModel):
space, space,
mode='exec', mode='exec',
nocopy=True) # nocopy allows to return 'result' nocopy=True) # nocopy allows to return 'result'
except Exception, e:
except Exception as e:
raise UserError( raise UserError(
_('Error when evaluating the exception.rule ' _('Error when evaluating the exception.rule '
'rule:\n %s \n(%s)') % (rule.name, e)) 'rule:\n %s \n(%s)') % (rule.name, e))
@ -193,9 +221,16 @@ class BaseException(models.AbstractModel):
sub_exceptions): sub_exceptions):
self.ensure_one() self.ensure_one()
exception_ids = [] exception_ids = []
next_state_rule = False
for rule in model_exceptions: for rule in model_exceptions:
if self._rule_eval(rule, self.rule_group, self): if self._rule_eval(rule, self.rule_group, self):
exception_ids.append(rule.id) 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:
next_state_rule = rule
if sub_exceptions: if sub_exceptions:
for obj_line in self._get_lines(): for obj_line in self._get_lines():
for rule in sub_exceptions: for rule in sub_exceptions:
@ -207,6 +242,9 @@ class BaseException(models.AbstractModel):
group_line = self.rule_group + '_line' group_line = self.rule_group + '_line'
if self._rule_eval(rule, group_line, obj_line): if self._rule_eval(rule, group_line, obj_line):
exception_ids.append(rule.id) exception_ids.append(rule.id)
# set object to next state
if next_state_rule:
self.state = next_state_rule.next_state
return exception_ids return exception_ids
@implemented_by_base_exception @implemented_by_base_exception

12
base_exception/security/ir.model.access.csv

@ -1,5 +1,7 @@
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
"access_exception_rule","base.exception","model_exception_rule","base.group_user",1,0,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
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_exception_rule,base.exception,model_exception_rule,base.group_user,1,0,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

4
base_exception/tests/__init__.py

@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
from . import test_tmp_model
from . import test_base_exception

84
base_exception/tests/test_base_exception.py

@ -0,0 +1,84 @@
# -*- coding: utf-8 -*-
# © 2016 Akretion Mourad EL HADJ MIMOUNE
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo.tests import common
import logging
_logger = logging.getLogger(__name__)
# @common.at_install(False)
# @common.post_install(True)
class TestBaseException(common.TransactionCase):
def setUp(self):
super(TestBaseException, self).setUp()
self.base_exception = self.env['base.exception']
self.exception_rule = self.env['exception.rule']
self.exception_confirm = self.env['exception.rule.confirm']
self.exception_rule._fields['rule_group'].selection.append(
('test_base', 'test base exception')
)
self.exception_rule._fields['model'].selection.append(
('base.exception.test.purchase',
'base.exception.test.purchase')
)
self.exception_rule._fields['model'].selection.append(
('base.exception.test.purchase.line',
'base.exception.test.purchase.line')
)
self.exceptionnozip = self.env['exception.rule'].create({
'name': "No ZIP code on destination",
'sequence': 10,
'rule_group': "test_base",
'model': "base.exception.test.purchase",
'code': """if not test_base.partner_id.zip:
failed=True""",
})
self.exceptionno_minorder = self.env['exception.rule'].create({
'name': "Min order except",
'sequence': 10,
'rule_group': "test_base",
'model': "base.exception.test.purchase",
'code': """if test_base.amount_total <= 200.0:
failed=True""",
})
self.exceptionno_lineqty = self.env['exception.rule'].create({
'name': "Qty > 0",
'sequence': 10,
'rule_group': "test_base",
'model': "base.exception.test.purchase.line",
'code': """if test_base_line.qty <= 0:
failed=True"""})
def test_sale_order_exception(self):
partner = self.env.ref('base.res_partner_1')
partner.zip = False
potest1 = self.env['base.exception.test.purchase'].create({
'name': 'Test base exception to basic purchase',
'partner_id': partner.id,
'line_ids': [(0, 0, {'name': "line test",
'amount': 120.0,
'qty': 1.5})],
})
potest1.button_confirm()
# Set ignore_exception flag (Done after ignore is selected at wizard)
potest1.ignore_exception = True
potest1.button_confirm()
self.assertTrue(potest1.state == 'purchase')
# Simulation the opening of the wizard exception_confirm and
# set ignore_exception to True
except_confirm = self.exception_confirm.with_context(
{
'active_id': potest1.id,
'active_ids': [potest1.id],
'active_model': potest1._name
}).new({'ignore': True})
except_confirm.action_confirm()
self.assertTrue(potest1.ignore_exception)

72
base_exception/tests/test_tmp_model.py

@ -0,0 +1,72 @@
# -*- coding: utf-8 -*-
# © 2017 Akretion (http://www.akretion.com)
# Mourad EL HADJ MIMOUNE <mourad.elhadj.mimoune@akretion.com>
from odoo import fields, models, api
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.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.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_draft(self):
self.write({'state': 'draft'})
return {}
@api.multi
def button_confirm(self):
self.write({'state': 'purchase'})
return True
@api.multi
def button_cancel(self):
self.write({'state': 'cancel'})
def test_base_get_lines(self):
self.ensure_one()
return self.line_ids
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()

3
base_exception/views/base_exception_view.xml

@ -1,6 +1,5 @@
<?xml version="1.0" ?> <?xml version="1.0" ?>
<odoo> <odoo>
<record id="view_exception_rule_tree" model="ir.ui.view"> <record id="view_exception_rule_tree" model="ir.ui.view">
<field name="name">exception.rule.tree</field> <field name="name">exception.rule.tree</field>
<field name="model">exception.rule</field> <field name="model">exception.rule</field>
@ -31,6 +30,7 @@
<group colspan="4" col="2" groups="base.group_system"> <group colspan="4" col="2" groups="base.group_system">
<field name="rule_group"/> <field name="rule_group"/>
<field name="model"/> <field name="model"/>
<field name="next_state"/>
<field name="code"/> <field name="code"/>
</group> </group>
</form> </form>
@ -47,5 +47,4 @@
</record> </record>
<menuitem action="action_exception_rule_tree" id="menu_action_exception" parent="base.menu_custom" sequence="90" /> <menuitem action="action_exception_rule_tree" id="menu_action_exception" parent="base.menu_custom" sequence="90" />
</odoo> </odoo>

2
base_exception/wizard/base_exception_confirm.py

@ -1,5 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# © 2011 Raphaël Valyi, Renato Lima, Guewen Baconnier, Sodexis # © 2011 Raphaël Valyi, Renato Lima, Guewen Baconnier, Sodexis
# © 2017 Akretion (http://www.akretion.com)
# Mourad EL HADJ MIMOUNE <mourad.elhadj.mimoune@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import api, fields, models from odoo import api, fields, models

4
base_exception/wizard/base_exception_confirm_view.xml

@ -1,7 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<odoo> <odoo>
<data>
<record id="view_exception_rule_confirm" model="ir.ui.view"> <record id="view_exception_rule_confirm" model="ir.ui.view">
<field name="name">Exceptions Rules</field> <field name="name">Exceptions Rules</field>
<field name="model">exception.rule.confirm</field> <field name="model">exception.rule.confirm</field>
@ -34,6 +32,4 @@
<field name="view_id" ref="view_exception_rule_confirm"/> <field name="view_id" ref="view_exception_rule_confirm"/>
<field name="target">new</field> <field name="target">new</field>
</record> </record>
</data>
</odoo> </odoo>
Loading…
Cancel
Save