From 5430843c63c1615297f354812377fa2b1bed3920 Mon Sep 17 00:00:00 2001 From: Holger Brunn Date: Tue, 10 Feb 2015 14:59:54 +0100 Subject: [PATCH 1/6] [FIX] evaluate filters if necessary --- web_advanced_filters/model/ir_filters.py | 61 ++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 5 deletions(-) diff --git a/web_advanced_filters/model/ir_filters.py b/web_advanced_filters/model/ir_filters.py index fb09d45b..c076a4a9 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,62 @@ 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']: + domain = expression.AND([ + domain, + [ + [ + 'id', 'not in', + self.pool[c['model_id']].search( + cr, uid, eval_n(c['domain']), + context=context) + ] + ]]) + 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 +139,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 = { From 5c731deb8a12097136311882dbd62a8ab1d0dc20 Mon Sep 17 00:00:00 2001 From: Holger Brunn Date: Tue, 10 Feb 2015 15:01:07 +0100 Subject: [PATCH 2/6] [IMP] allow users to inspect records when testing filters --- web_advanced_filters/model/ir_filters.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web_advanced_filters/model/ir_filters.py b/web_advanced_filters/model/ir_filters.py index c076a4a9..d09db3df 100644 --- a/web_advanced_filters/model/ir_filters.py +++ b/web_advanced_filters/model/ir_filters.py @@ -191,7 +191,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, }, From 487f31b9ba6d96bd17d08c8f208da23026908a64 Mon Sep 17 00:00:00 2001 From: Holger Brunn Date: Tue, 10 Feb 2015 15:19:21 +0100 Subject: [PATCH 3/6] [IMP] let users edit domain_this if there's other filters, make domain readonly then --- web_advanced_filters/view/ir_filters.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/web_advanced_filters/view/ir_filters.xml b/web_advanced_filters/view/ir_filters.xml index 057db6b1..32c562e6 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, []]])]} + + + + From b57a28d726d747fda114bcfce249954b31a95710 Mon Sep 17 00:00:00 2001 From: Holger Brunn Date: Tue, 10 Feb 2015 20:30:19 +0100 Subject: [PATCH 4/6] [FIX] coding style --- web_advanced_filters/model/ir_filters.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/web_advanced_filters/model/ir_filters.py b/web_advanced_filters/model/ir_filters.py index d09db3df..6d1aedca 100644 --- a/web_advanced_filters/model/ir_filters.py +++ b/web_advanced_filters/model/ir_filters.py @@ -101,7 +101,8 @@ class IrFilters(Model): context=context): result[this['id']] = False complement_domain = expression.normalize_domain( - safe_eval(this['domain'] or 'False') or [expression.FALSE_LEAF]) + safe_eval(this['domain'] or 'False') + or [expression.FALSE_LEAF]) for arg in complement_domain: if not expression.is_leaf(arg): continue From c9275a881799c77a538aeae1e2f17f3a992bb785 Mon Sep 17 00:00:00 2001 From: Holger Brunn Date: Mon, 2 Mar 2015 10:28:00 +0100 Subject: [PATCH 5/6] [IMP] more readable code --- web_advanced_filters/model/ir_filters.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/web_advanced_filters/model/ir_filters.py b/web_advanced_filters/model/ir_filters.py index d09db3df..72c7a958 100644 --- a/web_advanced_filters/model/ir_filters.py +++ b/web_advanced_filters/model/ir_filters.py @@ -70,16 +70,13 @@ class IrFilters(Model): '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', - self.pool[c['model_id']].search( - cr, uid, eval_n(c['domain']), - context=context) - ] - ]]) + [('id', 'not in', matching_ids)], + ]) else: domain = expression.AND([ domain, @@ -101,7 +98,8 @@ class IrFilters(Model): context=context): result[this['id']] = False complement_domain = expression.normalize_domain( - safe_eval(this['domain'] or 'False') or [expression.FALSE_LEAF]) + safe_eval(this['domain'] or 'False') or + [expression.FALSE_LEAF]) for arg in complement_domain: if not expression.is_leaf(arg): continue From fbbc6e31a1d75ac06c00550f7fa63805d25678da Mon Sep 17 00:00:00 2001 From: Holger Brunn Date: Mon, 2 Mar 2015 13:54:23 +0100 Subject: [PATCH 6/6] [FIX] flake8 --- web_advanced_filters/model/ir_filters.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web_advanced_filters/model/ir_filters.py b/web_advanced_filters/model/ir_filters.py index 1575489d..72c7a958 100644 --- a/web_advanced_filters/model/ir_filters.py +++ b/web_advanced_filters/model/ir_filters.py @@ -98,8 +98,8 @@ class IrFilters(Model): context=context): result[this['id']] = False complement_domain = expression.normalize_domain( - safe_eval(this['domain'] or 'False') - or [expression.FALSE_LEAF]) + safe_eval(this['domain'] or 'False') or + [expression.FALSE_LEAF]) for arg in complement_domain: if not expression.is_leaf(arg): continue