Browse Source

[MIG] base_exception: Migration to 12.0

pull/1557/head
Iván Todorovich 5 years ago
parent
commit
1088f5c3ae
  1. 78
      base_exception/README.rst
  2. 1
      base_exception/__init__.py
  3. 9
      base_exception/__manifest__.py
  4. 129
      base_exception/models/base_exception.py
  5. 8
      base_exception/readme/CONTRIBUTORS.rst
  6. 6
      base_exception/readme/DESCRIPTION.rst
  7. 1
      base_exception/readme/ROADMAP.rst
  8. 437
      base_exception/static/description/index.html
  9. 35
      base_exception/tests/test_base_exception.py
  10. 34
      base_exception/views/base_exception_view.xml
  11. 11
      base_exception/wizard/base_exception_confirm.py
  12. 2
      base_exception/wizard/base_exception_confirm_view.xml

78
base_exception/README.rst

@ -1,11 +1,30 @@
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
:target: https://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
==============
Base Exception
Exception Rule
==============
.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! 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%2Fserver--tools-lightgray.png?logo=github
:target: https://github.com/OCA/server-tools/tree/12.0/base_exception
:alt: OCA/server-tools
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/server-tools-12-0/server-tools-12-0-base_exception
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
:target: https://runbot.odoo-community.org/runbot/149/12.0
:alt: Try me on Runbot
|badge1| |badge2| |badge3| |badge4| |badge5|
This module provide an abstract model to manage customizable
exceptions to be applied on different models (sale order, invoice, ...).
@ -13,34 +32,38 @@ It is not useful for itself. You can see an example of implementation
in the 'sale_exception' module. (sale-workflow repository) or
'purchase_exception' module (purchase-workflow repository).
Usage
=====
**Table of contents**
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
:alt: Try me on Runbot
:target: https://runbot.odoo-community.org/runbot/149/11.0
.. contents::
:local:
Known issues / Roadmap
======================
Terms used in old api like `pool`, `cr`, `uid` must be removed porting this module in version 12.
Bug Tracker
===========
Bugs are tracked on `GitHub Issues
<https://github.com/OCA/server-tools/issues>`_. In case of trouble, please
check there if your issue has already been reported. If you spotted it first,
help us smash it by providing detailed and welcomed feedback.
Bugs are tracked on `GitHub Issues <https://github.com/OCA/server-tools/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 <https://github.com/OCA/server-tools/issues/new?body=module:%20base_exception%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Roadmap
-------
Terms used in old api like `pool`, `cr`, `uid` must be removed porting this module in version 12.
Do not contact contributors directly about support or help with technical issues.
Credits
=======
Images
------
Authors
~~~~~~~
* Odoo Community Association: `Icon <https://github.com/OCA/maintainer-tools/blob/master/template/module/static/description/icon.svg>`_.
* Akretion
* Sodexis
* Camptocamp
Contributors
------------
~~~~~~~~~~~~
* Raphaël Valyi <raphael.valyi@akretion.com>
* Renato Lima <renato.lima@akretion.com>
@ -49,18 +72,21 @@ Contributors
* Yannick Vaucher <yannick.vaucher@camptocamp.com>
* SodexisTeam <dev@sodexis.com>
* Mourad EL HADJ MIMOUNE <mourad.elhadj.mimoune@akretion.com>
* Iván Todorovich <ivan.todorovich@gmail.com>
Maintainer
----------
Maintainers
~~~~~~~~~~~
This module is maintained by the OCA.
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org
This module is maintained by the OCA.
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.
To contribute to this module, please visit https://odoo-community.org.
This module is part of the `OCA/server-tools <https://github.com/OCA/server-tools/tree/12.0/base_exception>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

1
base_exception/__init__.py

@ -1,2 +1 @@
from . import wizard, models

9
base_exception/__manifest__.py

@ -2,18 +2,19 @@
# Copyright 2017 Akretion (http://www.akretion.com)
# Mourad EL HADJ MIMOUNE <mourad.elhadj.mimoune@akretion.com>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
{
'name': 'Exception Rule',
'version': '11.0.1.1.0',
'version': '12.0.1.0.0',
'category': 'Generic Modules',
'summary': """
This module provide an abstract model to manage customizable
exceptions to be applied on different models (sale order, invoice, ...)""",
'author':
"Akretion, Sodexis, Camptocamp, Odoo Community Association (OCA)",
'website': 'http://www.akretion.com',
'depends': ['base_setup'],
'website': 'https://github.com/OCA/server-tools',
'depends': [
'base_setup',
],
'license': 'AGPL-3',
'data': [
'security/base_exception_security.xml',

129
base_exception/models/base_exception.py

@ -6,13 +6,9 @@
import time
from functools import wraps
from odoo import api, fields, models, _
import logging
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'."""
@ -28,50 +24,36 @@ def implemented_by_base_exception(func):
class ExceptionRule(models.Model):
_name = 'exception.rule'
_description = "Exception Rules"
_description = 'Exception Rule'
_order = 'active desc, sequence asc'
name = fields.Char('Exception Name', required=True, translate=True)
description = fields.Text('Description', translate=True)
sequence = fields.Integer(
string='Sequence',
help="Gives the sequence order when applying the test")
help="Gives the sequence order when applying the test",
)
rule_group = fields.Selection(
selection=[],
help="Rule group is used to group the rules that must validated "
"at same time for a target object. Ex: "
"validate sale.order.line rules with sale order rules.",
required=True)
model = fields.Selection(
selection=[],
string='Apply on', required=True)
required=True,
)
model = fields.Selection(selection=[], string='Apply on', required=True)
active = fields.Boolean('Active')
next_state = fields.Char(
'Next state',
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")
"the exception having the smallest sequence value",
)
code = fields.Text(
'Python Code',
help="Python code executed to check if the exception apply or "
"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 :
# - self: ORM model of the record which is checked
# - "rule_group" or "rule_group_"line:
# browse_record of the base.exception or
# 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
# - obj: same as object
# - env: Odoo Environment (i.e. self.env)
# - time: Python time module
# - cr: database cursor
# - uid: current user id
# - context: current context
""")
)
@api.constrains('next_state')
def _check_next_state_value(self):
@ -84,60 +66,55 @@ class ExceptionRule(models.Model):
'state']['selection']
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 choose for the "next state" '
'field state of "%s" is wrong.'
' Value must be in this list %s')
% (rule.next_state,
rule.model,
select_vals)
)
raise ValidationError(_(
'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,
rule.model,
select_vals
))
class BaseException(models.AbstractModel):
_name = 'base.exception'
_order = 'main_exception_id asc'
_description = 'Exception'
main_exception_id = fields.Many2one(
'exception.rule',
compute='_compute_main_error',
string='Main Exception',
store=True)
rule_group = fields.Selection(
[],
readonly=True,
store=True,
)
exception_ids = fields.Many2many(
'exception.rule',
string='Exceptions')
rule_group = fields.Selection([], readonly=True)
exception_ids = fields.Many2many('exception.rule', string='Exceptions')
ignore_exception = fields.Boolean('Ignore Exceptions', copy=False)
@api.depends('exception_ids', 'ignore_exception')
def _compute_main_error(self):
for obj in self:
if not obj.ignore_exception and obj.exception_ids:
obj.main_exception_id = obj.exception_ids[0]
for rec in self:
if not rec.ignore_exception and rec.exception_ids:
rec.main_exception_id = rec.exception_ids[0]
else:
obj.main_exception_id = False
rec.main_exception_id = False
@api.multi
def _popup_exceptions(self):
action = self._get_popup_action()
action_data = action.read()[0]
action_data.update({
action = self._get_popup_action().read()[0]
action.update({
'context': {
'active_id': self.ids[0],
'active_ids': self.ids,
'active_model': self._name,
}
})
return action_data
return action
@api.model
def _get_popup_action(self):
action = self.env.ref('base_exception.action_exception_rule_confirm')
return action
return self.env.ref('base_exception.action_exception_rule_confirm')
@api.multi
def _check_exception(self):
@ -191,36 +168,32 @@ class BaseException(models.AbstractModel):
@api.model
def _exception_rule_eval_context(self, obj_name, rec):
return {obj_name: rec,
'self': self.env[rec._name],
'object': rec,
'obj': rec,
'env': self.env,
'cr': self.env.cr,
'uid': self.env.uid,
'user': self.env.user,
'time': time,
# copy context to prevent side-effects of eval
'context': self.env.context.copy()}
return {
'time': time,
'self': rec,
# obj_name, object, obj: deprecated.
# should be removed in future migrations
obj_name: rec,
'object': rec,
'obj': rec,
# copy context to prevent side-effects of eval
# should be deprecated too, accesible through self.
'context': self.env.context.copy()
}
@api.model
def _rule_eval(self, rule, obj_name, rec):
expr = rule.code
space = self._exception_rule_eval_context(obj_name, rec)
eval_ctx = self._exception_rule_eval_context(obj_name, rec)
try:
safe_eval(expr,
space,
mode='exec',
nocopy=True) # nocopy allows to return 'result'
safe_eval(rule.code, eval_ctx, mode='exec', nocopy=True)
except Exception as e:
raise UserError(
_('Error when evaluating the exception.rule '
'rule:\n %s \n(%s)') % (rule.name, e))
return space.get('failed', False)
raise UserError(_(
'Error when evaluating the exception.rule: '
'%s\n(%s)') % (rule.name, e))
return eval_ctx.get('failed', False)
@api.multi
def _detect_exceptions(self, model_exceptions,
sub_exceptions):
def _detect_exceptions(self, model_exceptions, sub_exceptions):
self.ensure_one()
exception_ids = []
next_state_rule = False
@ -228,8 +201,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 or\
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():

8
base_exception/readme/CONTRIBUTORS.rst

@ -0,0 +1,8 @@
* Raphaël Valyi <raphael.valyi@akretion.com>
* Renato Lima <renato.lima@akretion.com>
* Sébastien BEAU <sebastien.beau@akretion.com>
* Guewen Baconnier <guewen.baconnier@camptocamp.com>
* Yannick Vaucher <yannick.vaucher@camptocamp.com>
* SodexisTeam <dev@sodexis.com>
* Mourad EL HADJ MIMOUNE <mourad.elhadj.mimoune@akretion.com>
* Iván Todorovich <ivan.todorovich@gmail.com>

6
base_exception/readme/DESCRIPTION.rst

@ -0,0 +1,6 @@
This module provide an abstract model to manage customizable
exceptions to be applied on different models (sale order, invoice, ...).
It is not useful for itself. You can see an example of implementation
in the 'sale_exception' module. (sale-workflow repository) or
'purchase_exception' module (purchase-workflow repository).

1
base_exception/readme/ROADMAP.rst

@ -0,0 +1 @@
Terms used in old api like `pool`, `cr`, `uid` must be removed porting this module in version 12.

437
base_exception/static/description/index.html

@ -0,0 +1,437 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.14: http://docutils.sourceforge.net/" />
<title>Exception Rule</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 7952 2016-07-26 18:15:59Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
.subscript {
vertical-align: sub;
font-size: smaller }
.superscript {
vertical-align: super;
font-size: smaller }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
overflow: hidden;
}
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left, .figure.align-left, object.align-left, table.align-left {
clear: left ;
float: left ;
margin-right: 1em }
img.align-right, .figure.align-right, object.align-right, table.align-right {
clear: right ;
float: right ;
margin-left: 1em }
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left }
.align-center {
clear: both ;
text-align: center }
.align-right {
text-align: right }
/* reset inner alignment in figures */
div.align-right {
text-align: inherit }
/* div.align-center * { */
/* text-align: left } */
.align-top {
vertical-align: top }
.align-middle {
vertical-align: middle }
.align-bottom {
vertical-align: bottom }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font: inherit }
pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: grey; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document" id="exception-rule">
<h1 class="title">Exception Rule</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/server-tools/tree/12.0/base_exception"><img alt="OCA/server-tools" src="https://img.shields.io/badge/github-OCA%2Fserver--tools-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/server-tools-12-0/server-tools-12-0-base_exception"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/149/12.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
<p>This module provide an abstract model to manage customizable
exceptions to be applied on different models (sale order, invoice, …).</p>
<p>It is not useful for itself. You can see an example of implementation
in the ‘sale_exception’ module. (sale-workflow repository) or
‘purchase_exception’ module (purchase-workflow repository).</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#known-issues-roadmap" id="id1">Known issues / Roadmap</a></li>
<li><a class="reference internal" href="#bug-tracker" id="id2">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="id3">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="id4">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="id5">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="id6">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="known-issues-roadmap">
<h1><a class="toc-backref" href="#id1">Known issues / Roadmap</a></h1>
<p>Terms used in old api like <cite>pool</cite>, <cite>cr</cite>, <cite>uid</cite> must be removed porting this module in version 12.</p>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#id2">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/server-tools/issues">GitHub Issues</a>.
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
<a class="reference external" href="https://github.com/OCA/server-tools/issues/new?body=module:%20base_exception%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h1><a class="toc-backref" href="#id3">Credits</a></h1>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#id4">Authors</a></h2>
<ul class="simple">
<li>Akretion</li>
<li>Sodexis</li>
<li>Camptocamp</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#id5">Contributors</a></h2>
<ul class="simple">
<li>Raphaël Valyi &lt;<a class="reference external" href="mailto:raphael.valyi&#64;akretion.com">raphael.valyi&#64;akretion.com</a>&gt;</li>
<li>Renato Lima &lt;<a class="reference external" href="mailto:renato.lima&#64;akretion.com">renato.lima&#64;akretion.com</a>&gt;</li>
<li>Sébastien BEAU &lt;<a class="reference external" href="mailto:sebastien.beau&#64;akretion.com">sebastien.beau&#64;akretion.com</a>&gt;</li>
<li>Guewen Baconnier &lt;<a class="reference external" href="mailto:guewen.baconnier&#64;camptocamp.com">guewen.baconnier&#64;camptocamp.com</a>&gt;</li>
<li>Yannick Vaucher &lt;<a class="reference external" href="mailto:yannick.vaucher&#64;camptocamp.com">yannick.vaucher&#64;camptocamp.com</a>&gt;</li>
<li>SodexisTeam &lt;<a class="reference external" href="mailto:dev&#64;sodexis.com">dev&#64;sodexis.com</a>&gt;</li>
<li>Mourad EL HADJ MIMOUNE &lt;<a class="reference external" href="mailto:mourad.elhadj.mimoune&#64;akretion.com">mourad.elhadj.mimoune&#64;akretion.com</a>&gt;</li>
<li>Iván Todorovich &lt;<a class="reference external" href="mailto:ivan.todorovich&#64;gmail.com">ivan.todorovich&#64;gmail.com</a>&gt;</li>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#id6">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
<p>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.</p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/server-tools/tree/12.0/base_exception">OCA/server-tools</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div>
</div>
</div>
</body>
</html>

35
base_exception/tests/test_base_exception.py

@ -13,8 +13,6 @@ _logger = logging.getLogger(__name__)
@common.post_install(True)
class TestBaseException(common.SavepointCase):
# pylint: disable=missing-return
@classmethod
def setUpClass(cls):
super(TestBaseException, cls).setUpClass()
@ -25,31 +23,28 @@ class TestBaseException(common.SavepointCase):
cls.exception_confirm = cls.env['exception.rule.confirm']
cls.exception_rule._fields['rule_group'].selection.append(
('test_base', 'test base exception')
)
('test_base', 'Test Base Exception'))
cls.exception_rule._fields['model'].selection.append(
('base.exception.test.purchase',
'base.exception.test.purchase')
)
('base.exception.test.purchase', 'Purchase Order'))
cls.exception_rule._fields['model'].selection.append(
('base.exception.test.purchase.line',
'base.exception.test.purchase.line')
)
('base.exception.test.purchase.line', 'Purchase Order Line'))
cls.exceptionnozip = cls.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""",
'code': "if not test_base.partner_id.zip: failed=True",
})
cls.exceptionno_minorder = cls.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""",
'code': "if test_base.amount_total <= 200.0: failed=True",
})
cls.exceptionno_lineqty = cls.env['exception.rule'].create({
@ -57,8 +52,8 @@ class TestBaseException(common.SavepointCase):
'sequence': 10,
'rule_group': "test_base",
'model': "base.exception.test.purchase.line",
'code': """if test_base_line.qty <= 0:
failed=True"""})
'code': "if test_base_line.qty <= 0: failed=True"
})
def test_purchase_order_exception(self):
partner = self.env.ref('base.res_partner_1')
@ -66,9 +61,11 @@ class TestBaseException(common.SavepointCase):
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})],
'line_ids': [(0, 0, {
'name': "line test",
'amount': 120.0,
'qty': 1.5,
})],
})
potest1.button_confirm()

34
base_exception/views/base_exception_view.xml

@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<odoo>
<record id="view_exception_rule_tree" model="ir.ui.view">
<field name="name">exception.rule.tree</field>
<field name="model">exception.rule</field>
@ -20,24 +21,45 @@
<field name="arch" type="xml">
<form string="Exception Rule Setup" name="exception_rule">
<sheet>
<div class="oe_button_box" name="button_box">
<button name="toggle_active" type="object" class="oe_stat_button" icon="fa-archive">
<field name="active" widget="boolean_button"/>
</button>
</div>
<div class="oe_title">
<label for="name" class="oe_edit_only"/>
<h1><field name="name"/></h1>
</div>
<group>
<group>
<field name="name"/>
<field name="description"/>
</group>
<group>
<field name="active"/>
<field name="sequence"/>
</group>
</group>
<group>
<group colspan="4" groups="base.group_system">
<field name="rule_group"/>
<field name="model"/>
<field name="next_state"/>
<field name="code"/>
</group>
</group>
<notebook>
<page name="code" string="Python Code">
<field name="code" widget="ace" options="{'mode': 'python'}" placeholder="Enter Python code here. Help about Python expression is available in the help tab of this document."/>
</page>
<page name="help" string="Help">
<group>
<div style="margin-top: 4px;">
<h3>Help with Python expressions</h3>
<p>Various fields may use Python code or Python expressions. The following variables can be used:</p>
<ul>
<li><code>self</code>: Record on which the rule is evaluated.</li>
<li><code>time</code>: useful Python libraries</li>
<li>To block the exception use: <code>failed = True</code></li>
</ul>
</div>
</group>
</page>
</notebook>
</sheet>
</form>
</field>

11
base_exception/wizard/base_exception_confirm.py

@ -2,19 +2,20 @@
# Copyright 2017 Akretion (http://www.akretion.com)
# Mourad EL HADJ MIMOUNE <mourad.elhadj.mimoune@akretion.com>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo import api, fields, models, _
from odoo.exceptions import ValidationError
class ExceptionRuleConfirm(models.AbstractModel):
_name = 'exception.rule.confirm'
_description = 'Exception Rule Confirm Wizard'
related_model_id = fields.Many2one('base.exception',)
exception_ids = fields.Many2many('exception.rule',
string='Exceptions to resolve',
readonly=True)
exception_ids = fields.Many2many(
'exception.rule',
string='Exceptions to resolve',
readonly=True,
)
ignore = fields.Boolean('Ignore Exceptions')
@api.model

2
base_exception/wizard/base_exception_confirm_view.xml

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