Browse Source

Merge pull request #19 from hbrunn/7.0-compute_domain_x2many

[ADD] web_compute_domain_x2many
pull/20/head
Pedro M. Baeza 10 years ago
parent
commit
2964726620
  1. 20
      web_compute_domain_x2many/__init__.py
  2. 58
      web_compute_domain_x2many/__openerp__.py
  3. BIN
      web_compute_domain_x2many/static/src/img/icon.png
  4. 167
      web_compute_domain_x2many/static/src/js/web_compute_domain_x2many.js
  5. 106
      web_compute_domain_x2many/static/test/web_compute_domain_x2many.js

20
web_compute_domain_x2many/__init__.py

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# This module copyright (C) 2014 Therp BV (<http://therp.nl>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

58
web_compute_domain_x2many/__openerp__.py

@ -0,0 +1,58 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# This module copyright (C) 2014 Therp BV (<http://therp.nl>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
{
"name": "Compute client-side domains on x2many fields correctly",
"version": "1.0",
"author": "Therp BV",
"license": "AGPL-3",
"complexity": "normal",
"description": """
When using ``attrs="..."``, evaluation of x2many fields nearly always goes
wrong in ways not to be expected when being used to server side domains in
Model.search().
This addon fixes those cases while keeping backwards compatibility for cases
where you might have checks in a somewhat hacky way, ie. ``attrs="{'invisible':
[('category_id', '=', [[6, False, []]])]}"``.
""",
"category": "Dependency",
"depends": [
'web',
],
"data": [
],
"js": [
'static/src/js/web_compute_domain_x2many.js',
],
"css": [
],
"qweb": [
],
"test": [
'static/test/web_compute_domain_x2many.js',
],
"auto_install": False,
"installable": True,
"application": False,
"external_dependencies": {
'python': [],
},
}

BIN
web_compute_domain_x2many/static/src/img/icon.png

After

Width: 80  |  Height: 80  |  Size: 7.8 KiB

167
web_compute_domain_x2many/static/src/js/web_compute_domain_x2many.js

@ -0,0 +1,167 @@
//-*- coding: utf-8 -*-
//############################################################################
//
// OpenERP, Open Source Management Solution
// This module copyright (C) 2014 Therp BV (<http://therp.nl>).
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//############################################################################
openerp.web_compute_domain_x2many = function(instance)
{
var _t = instance.web._t;
function find_in_commands(commands, id)
//check if a list of commands contains an id in a way that it will be
//contained after the command list is evaluated
{
return _.reduce(
_.map(
commands,
function(command)
{
switch(command[0])
{
case 1:
case 4:
return 1;
case 2:
case 3:
case 5:
return -1
case 6:
return _(command[2]).contains(id);
default:
return 0;
}
}
),
function(a, b) {return a + b},
0
) > 0;
}
var comparators = {
scalar: function(field_value, op, val, field)
{
switch (op.toLowerCase()) {
case '=':
case '==':
return _.isEqual(field_value, val);
case '!=':
case '<>':
return !_.isEqual(field_value, val);
case '<':
return field_value < val;
case '>':
return field_value > val;
case '<=':
return field_value <= val;
case '>=':
return field_value >= val;
case 'in':
if (!_.isArray(val)) val = [val];
return _(val).contains(field_value);
case 'not in':
if (!_.isArray(val)) val = [val];
return !_(val).contains(field_value);
default:
console.warn(
_t("Unsupported operator %s in domain %s"),
op, JSON.stringify(expr));
return true;
}
},
one2many: function(field_value, op, val, field)
{
switch(op.toLowerCase())
{
case '=':
case '==':
if(!_.isArray(val))
{
return find_in_commands(field_value, val);
}
else
{
return comparators.scalar(field_value, op, val, field);
}
case '!=':
case '<>':
return !comparators.one2many(field_value, '=', val, field);
case 'in':
var found = false;
_.each(val, function(v)
{
found |= find_in_commands(field_value, v);
});
return found;
case 'not in':
return !comparators.one2many(field_value, 'in', val, field);
default:
return comparators.scalar(field_value, op, val, field);
}
},
many2many: function()
{
return comparators.one2many.apply(this, arguments);;
},
};
//start OpenERP compute_domain from web/static/src/view_form.js
instance.web.form.compute_domain = function(expr, fields) {
if (! (expr instanceof Array))
return !! expr;
var stack = [];
for (var i = expr.length - 1; i >= 0; i--) {
var ex = expr[i];
if (ex.length == 1) {
var top = stack.pop();
switch (ex) {
case '|':
stack.push(stack.pop() || top);
continue;
case '&':
stack.push(stack.pop() && top);
continue;
case '!':
stack.push(!top);
continue;
default:
throw new Error(_.str.sprintf(
_t("Unknown operator %s in domain %s"),
ex, JSON.stringify(expr)));
}
}
var field = fields[ex[0]];
if (!field) {
throw new Error(_.str.sprintf(
_t("Unknown field %s in domain %s"),
ex[0], JSON.stringify(expr)));
}
var field_value = field.get_value ? field.get_value() : field.value;
var op = ex[1];
var val = ex[2];
//begin local changes
var field_type = field.field ? field.field.type : 'scalar';
var comparator = comparators[field_type] ? comparators[field_type] : comparators.scalar;
stack.push(comparator(field_value, op, val, field));
//end local changes
}
return _.all(stack, _.identity);
};
//end OpenERP compute_domain
instance.web_compute_domain_x2many.comparators = comparators;
}

106
web_compute_domain_x2many/static/test/web_compute_domain_x2many.js

@ -0,0 +1,106 @@
//-*- coding: utf-8 -*-
//############################################################################
//
// OpenERP, Open Source Management Solution
// This module copyright (C) 2014 Therp BV (<http://therp.nl>).
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//############################################################################
openerp.testing.section(
'web_compute_domain_x2many',
function(test)
{
//start OpenERP core tests from web/static/test/form.js
test("basic", function (instance) {
var fields = {
'a': {value: 3},
'group_method': {value: 'line'},
'select1': {value: 'day'},
'rrule_type': {value: 'monthly'}
};
ok(instance.web.form.compute_domain(
[['a', '=', 3]], fields));
ok(instance.web.form.compute_domain(
[['group_method','!=','count']], fields));
ok(instance.web.form.compute_domain(
[['select1','=','day'], ['rrule_type','=','monthly']], fields));
});
test("or", function (instance) {
var web = {
'section_id': {value: null},
'user_id': {value: null},
'member_ids': {value: null}
};
var domain = ['|', ['section_id', '=', 42],
'|', ['user_id','=',3],
['member_ids', 'in', [3]]];
ok(instance.web.form.compute_domain(domain, _.extend(
{}, web, {'section_id': {value: 42}})));
ok(instance.web.form.compute_domain(domain, _.extend(
{}, web, {'user_id': {value: 3}})));
ok(instance.web.form.compute_domain(domain, _.extend(
{}, web, {'member_ids': {value: 3}})));
});
test("not", function (instance) {
var fields = {
'a': {value: 5},
'group_method': {value: 'line'}
};
ok(instance.web.form.compute_domain(
['!', ['a', '=', 3]], fields));
ok(instance.web.form.compute_domain(
['!', ['group_method','=','count']], fields));
});
//end OpenERP core tests
var fields = {
one2many_empty: {value: [], field: {type: 'one2many'}},
one2many_one_entry: {value: [[4, 42, false]], field: {type: 'one2many'}},
one2many_multiple_entries: {value: [[4, 42, false], [4, 43, false]], field: {type: 'one2many'}},
many2many_empty: {value: [[6, false, []]], field: {type: 'many2many'}},
many2many_one_entry: {value: [[6, false, [42]]], field: {type: 'many2many'}},
many2many_multiple_entries: {value: [[6, false, [42, 43]]], field: {type: 'many2many'}},
};
test('legacy behavior', function(instance)
{
var eval = function(expression, fields)
{
expression = instance.web.pyeval.eval('domain', expression, {}, {});
return instance.web.form.compute_domain(expression, fields)
}
ok(eval("[('one2many_empty', '=', [])]", fields), 'empty one2many');
ok(eval("[('many2many_empty', '=', [[6, False, []]])]", fields), 'empty many2many');
});
test('x2many tests', function(instance)
{
var eval = function(expression, fields)
{
expression = instance.web.pyeval.eval('domain', expression, {}, {});
return instance.web.form.compute_domain(expression, fields)
}
ok(!eval("[('one2many_empty', '=', 42)]", fields), 'empty one2many == value');
ok(eval("[('one2many_one_entry', '=', 42)]", fields), 'one2many with one entry == value');
ok(eval("[('one2many_multiple_entries', '=', 42)]", fields), 'one2many with multiple entries == value');
ok(eval("[('one2many_multiple_entries', 'in', [42])]", fields), 'one2many with multiple entries in [value]');
ok(!eval("[('many2many_empty', '=', 42)]", fields), 'empty many2many == value');
ok(eval("[('many2many_one_entry', '=', 42)]", fields), 'many2many with one entry == value');
ok(eval("[('many2many_multiple_entries', '=', 42)]", fields), 'many2many with multiple entries == value');
ok(eval("[('many2many_multiple_entries', 'in', [42])]", fields), 'many2many with multiple entries in [value]');
ok(eval("[('many2many_multiple_entries', 'not in', [44])]", fields), 'many2many with multiple entries not in [value]');
});
});
Loading…
Cancel
Save