mirror of https://github.com/OCA/web.git
Merge pull request #83 from hbrunn/7.0-advanced_filters
7.0 advanced filters: semantics of negative searches on properties of x2manypull/100/head
commit
ce2f3f4156
|
@ -27,6 +27,7 @@ from openerp.tools.translate import _
|
||||||
|
|
||||||
class IrFilters(Model):
|
class IrFilters(Model):
|
||||||
_inherit = 'ir.filters'
|
_inherit = 'ir.filters'
|
||||||
|
_evaluate_before_negate = ['one2many', 'many2many']
|
||||||
|
|
||||||
def _is_frozen_get(self, cr, uid, ids, field_name, args, context=None):
|
def _is_frozen_get(self, cr, uid, ids, field_name, args, context=None):
|
||||||
'''determine if this is fixed list of ids'''
|
'''determine if this is fixed list of ids'''
|
||||||
|
@ -65,17 +66,60 @@ class IrFilters(Model):
|
||||||
cr, uid, this['union_filter_ids'], ['domain'],
|
cr, uid, this['union_filter_ids'], ['domain'],
|
||||||
context=context)])
|
context=context)])
|
||||||
for c in self.read(cr, uid, this['complement_filter_ids'],
|
for c in self.read(cr, uid, this['complement_filter_ids'],
|
||||||
['domain'], context=context):
|
['domain', 'evaluate_before_negate',
|
||||||
domain = expression.AND([
|
'model_id'],
|
||||||
domain,
|
context=context):
|
||||||
['!'] + eval_n(c['domain'])])
|
if c['evaluate_before_negate']:
|
||||||
result[this['id']] = str(domain)
|
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
|
return result
|
||||||
|
|
||||||
def _domain_set(self, cr, uid, ids, field_name, field_value, args,
|
def _domain_set(self, cr, uid, ids, field_name, field_value, args,
|
||||||
context=None):
|
context=None):
|
||||||
self.write(cr, uid, ids, {'domain_this': field_value})
|
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 = {
|
_columns = {
|
||||||
'is_frozen': fields.function(
|
'is_frozen': fields.function(
|
||||||
_is_frozen_get, type='boolean', string='Frozen'),
|
_is_frozen_get, type='boolean', string='Frozen'),
|
||||||
|
@ -93,6 +137,11 @@ class IrFilters(Model):
|
||||||
fnct_inv=_domain_set),
|
fnct_inv=_domain_set),
|
||||||
'domain_this': fields.text(
|
'domain_this': fields.text(
|
||||||
'This filter\'s own domain', oldname='domain'),
|
'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 = {
|
_defaults = {
|
||||||
|
@ -140,7 +189,7 @@ class IrFilters(Model):
|
||||||
'res_model': this.model_id,
|
'res_model': this.model_id,
|
||||||
'domain': this.domain,
|
'domain': this.domain,
|
||||||
'view_type': 'form',
|
'view_type': 'form',
|
||||||
'view_mode': 'tree',
|
'view_mode': 'tree,form',
|
||||||
'context': {
|
'context': {
|
||||||
'default_filter_id': this.id,
|
'default_filter_id': this.id,
|
||||||
},
|
},
|
||||||
|
|
|
@ -21,6 +21,12 @@
|
||||||
<field name="complement_filter_ids" nolabel="1" domain="[('user_id', 'in', [False, uid]),('id', '!=', id), ('model_id', '=', model_id)]" />
|
<field name="complement_filter_ids" nolabel="1" domain="[('user_id', 'in', [False, uid]),('id', '!=', id), ('model_id', '=', model_id)]" />
|
||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
|
<field name="domain" position="attributes">
|
||||||
|
<attribute name="attrs">{'readonly': ['|', ('union_filter_ids', '!=', [[6, False, []]]), ('complement_filter_ids', '!=', [[6, False, []]])]}</attribute>
|
||||||
|
</field>
|
||||||
|
<field name="domain" position="after">
|
||||||
|
<field name="domain_this" attrs="{'invisible': [('union_filter_ids', '=', [[6, False, []]]), ('complement_filter_ids', '=', [[6, False, []]])]}" />
|
||||||
|
</field>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
<record id="form_ir_filters_save_new" model="ir.ui.view">
|
<record id="form_ir_filters_save_new" model="ir.ui.view">
|
||||||
|
|
Loading…
Reference in New Issue