diff --git a/web_advanced_filters/model/ir_filters.py b/web_advanced_filters/model/ir_filters.py
index fb09d45b0..72c7a9586 100644
--- a/web_advanced_filters/model/ir_filters.py
+++ b/web_advanced_filters/model/ir_filters.py
@@ -27,6 +27,7 @@ from openerp.tools.translate import _
class IrFilters(Model):
_inherit = 'ir.filters'
+ _evaluate_before_negate = ['one2many', 'many2many']
def _is_frozen_get(self, cr, uid, ids, field_name, args, context=None):
'''determine if this is fixed list of ids'''
@@ -65,17 +66,60 @@ class IrFilters(Model):
cr, uid, this['union_filter_ids'], ['domain'],
context=context)])
for c in self.read(cr, uid, this['complement_filter_ids'],
- ['domain'], context=context):
- domain = expression.AND([
- domain,
- ['!'] + eval_n(c['domain'])])
- result[this['id']] = str(domain)
+ ['domain', 'evaluate_before_negate',
+ 'model_id'],
+ context=context):
+ if c['evaluate_before_negate']:
+ matching_ids = self.pool[c['model_id']].search(
+ cr, uid, eval_n(c['domain']),
+ context=context)
+ domain = expression.AND([
+ domain,
+ [('id', 'not in', matching_ids)],
+ ])
+ else:
+ domain = expression.AND([
+ domain,
+ ['!'] + eval_n(c['domain'])])
+ result[this['id']] = str(expression.normalize_domain(domain))
return result
def _domain_set(self, cr, uid, ids, field_name, field_value, args,
context=None):
self.write(cr, uid, ids, {'domain_this': field_value})
+ def _evaluate_before_negate_get(self, cr, uid, ids, field_name, args,
+ context=None):
+ """check if this filter contains references to x2many fields. If so,
+ then negation goes wrong in nearly all cases, so we evaluate the
+ filter and remove its resulting ids"""
+ result = {}
+ for this in self.read(cr, uid, ids, ['model_id', 'domain'],
+ context=context):
+ result[this['id']] = False
+ complement_domain = expression.normalize_domain(
+ safe_eval(this['domain'] or 'False') or
+ [expression.FALSE_LEAF])
+ for arg in complement_domain:
+ if not expression.is_leaf(arg):
+ continue
+ current_model = self.pool.get(this['model_id'])
+ if not current_model:
+ continue
+ has_x2many = False
+ for field_name in arg[0].split('.'):
+ field = current_model._all_columns[field_name].column
+ has_x2many |= field._type in self._evaluate_before_negate
+ has_x2many |= isinstance(field, fields.function)
+ if hasattr(field, '_obj'):
+ current_model = self.pool.get(field._obj)
+ if not current_model or has_x2many:
+ break
+ if has_x2many:
+ result[this['id']] = True
+ break
+ return result
+
_columns = {
'is_frozen': fields.function(
_is_frozen_get, type='boolean', string='Frozen'),
@@ -93,6 +137,11 @@ class IrFilters(Model):
fnct_inv=_domain_set),
'domain_this': fields.text(
'This filter\'s own domain', oldname='domain'),
+ 'evaluate_before_negate': fields.function(
+ _evaluate_before_negate_get, type='boolean',
+ string='Evaluate this filter before negating',
+ help='This is necessary if this filter contains positive operators'
+ 'on x2many fields')
}
_defaults = {
@@ -140,7 +189,7 @@ class IrFilters(Model):
'res_model': this.model_id,
'domain': this.domain,
'view_type': 'form',
- 'view_mode': 'tree',
+ 'view_mode': 'tree,form',
'context': {
'default_filter_id': this.id,
},
diff --git a/web_advanced_filters/view/ir_filters.xml b/web_advanced_filters/view/ir_filters.xml
index 057db6b1f..32c562e61 100644
--- a/web_advanced_filters/view/ir_filters.xml
+++ b/web_advanced_filters/view/ir_filters.xml
@@ -21,6 +21,12 @@
+
+ {'readonly': ['|', ('union_filter_ids', '!=', [[6, False, []]]), ('complement_filter_ids', '!=', [[6, False, []]])]}
+
+
+
+