[FIX] correctly handle group_by_no_leaf when no grouping applied
authorXavier Morel <xmo@openerp.com>
Tue, 16 Apr 2013 09:23:44 +0000 (11:23 +0200)
committerXavier Morel <xmo@openerp.com>
Tue, 16 Apr 2013 09:23:44 +0000 (11:23 +0200)
If there are no grouping field specified *but* group_by_no_leaf is
specified, should call read_group with no grouping fields: will
generate a single group (which can not be opened) for all of the
model.

Necessary for analysis views since individual "records" make no sense.

bzr revid: xmo@openerp.com-20130416092344-2pqog8f7xprn6hsh

addons/web/__openerp__.py
addons/web/static/src/js/data.js
addons/web/static/test/data.js [new file with mode: 0644]

index 937442d..f335c52 100644 (file)
@@ -77,6 +77,7 @@ This module provides the core of the OpenERP Web Client.
         "static/test/class.js",
         "static/test/registry.js",
         "static/test/form.js",
+        "static/test/data.js",
         "static/test/list-utils.js",
         "static/test/formats.js",
         "static/test/rpc.js",
index cfcd863..a36441a 100644 (file)
@@ -112,24 +112,27 @@ instance.web.Query = instance.web.Class.extend({
      * @returns {jQuery.Deferred<Array<openerp.web.QueryGroup>> | null}
      */
     group_by: function (grouping) {
-        if (grouping === undefined) {
-            return null;
+        var ctx = instance.web.pyeval.eval(
+            'context', this._model.context(this._context));
+
+        // undefined passed in explicitly (!)
+        if (_.isUndefined(grouping)) {
+            grouping = [];
         }
 
         if (!(grouping instanceof Array)) {
             grouping = _.toArray(arguments);
         }
-        if (_.isEmpty(grouping)) { return null; }
+        if (_.isEmpty(grouping) && !ctx['group_by_no_leaf']) {
+            return null;
+        }
 
         var self = this;
-
-        var ctx = instance.web.pyeval.eval(
-            'context', this._model.context(this._context));
         return this._model.call('read_group', {
             groupby: grouping,
             fields: _.uniq(grouping.concat(this._fields || [])),
             domain: this._model.domain(this._filter),
-            context: this._model.context(this._context),
+            context: ctx,
             offset: this._offset,
             limit: this._limit,
             orderby: instance.web.serialize_sort(this._order_by) || false
@@ -325,7 +328,7 @@ instance.web.Model = instance.web.Class.extend({
      * Fetches the model's domain, combined with the provided domain if any
      *
      * @param {Array} [domain] to combine with the model's internal domain
-     * @returns The model's internal domain, or the AND-ed union of the model's internal domain and the provided domain
+     * @returns {instance.web.CompoundDomain} The model's internal domain, or the AND-ed union of the model's internal domain and the provided domain
      */
     domain: function (domain) {
         if (!domain) { return this._domain; }
@@ -337,7 +340,7 @@ instance.web.Model = instance.web.Class.extend({
      * combined with the provided context if any
      *
      * @param {Object} [context] to combine with the model's internal context
-     * @returns The union of the user's context and the model's internal context, as well as the provided context if any. In that order.
+     * @returns {instance.web.CompoundContext} The union of the user's context and the model's internal context, as well as the provided context if any. In that order.
      */
     context: function (context) {
         return new instance.web.CompoundContext(
diff --git a/addons/web/static/test/data.js b/addons/web/static/test/data.js
new file mode 100644 (file)
index 0000000..6f1e518
--- /dev/null
@@ -0,0 +1,76 @@
+openerp.testing.section('data.model.group_by', {
+    rpc: 'mock',
+    dependencies: ['web.data'],
+}, function (test) {
+    var group_result = [{
+        bar: 3, bar_count: 5, __context: {}, __domain: [['bar', '=', 3]],
+    }, {
+        bar: 5, bar_count: 3, __context: {}, __domain: [['bar', '=', 5]],
+    }, {
+        bar: 8, bar_count: 0, __context: {}, __domain: [['bar', '=', 8]],
+    }];
+    test('basic', {asserts: 7}, function (instance, $fix, mock) {
+        var m = new instance.web.Model('foo');
+        mock('foo:read_group', function (args, kwargs) {
+            deepEqual(kwargs.fields, ['bar'],
+                      "should read grouping field");
+            deepEqual(kwargs.groupby, ['bar'],
+                      "should have single grouping field");
+            return group_result;
+        });
+        mock('/web/dataset/search_read', function (args) {
+            deepEqual(args.params.domain, [['bar', '=', 3]],
+                      "should have domain matching that of group_by result");
+            return {records: [
+                {bar: 3, id: 1},
+                {bar: 3, id: 2},
+                {bar: 3, id: 4},
+                {bar: 3, id: 8},
+                {bar: 3, id: 16}
+            ], length: 5};
+        });
+
+        return m.query().group_by('bar')
+        .then(function (groups) {
+            ok(groups, "should have data");
+            equal(groups.length, 3, "should have three results");
+            var first = groups[0];
+            ok(first.attributes.has_children, "should have children");
+            return  first.query().all();
+        }).done(function (first) {
+            equal(first.length, 5, "should have 5 records")
+        });
+    });
+    test('noleaf', {asserts: 5}, function (instance, $fix, mock) {
+        var m = new instance.web.Model('foo', {group_by_no_leaf: true});
+        mock('foo:read_group', function (args, kwargs) {
+            deepEqual(kwargs.fields, ['bar'],
+                      "should read grouping field");
+            deepEqual(kwargs.groupby, ['bar'],
+                      "should have single grouping field");
+
+            return  group_result;
+        });
+        return m.query().group_by('bar')
+        .then(function (groups) {
+            ok(groups, "should have data");
+            equal(groups.length, 3, "should have three results");
+            ok(!groups[0].attributes.has_children,
+                "should not have children because no_leaf");
+        })
+    });
+    test('nogroup', {rpc: false}, function (instance, $f, mock) {
+        var m = new instance.web.Model('foo');
+        strictEqual(m.query().group_by(), null, "should not group");
+    });
+    test('empty.noleaf', {asserts: 1}, function (instance, $f, mock) {
+        var m = new instance.web.Model('foo',  {group_by_no_leaf: true});
+        mock('foo:read_group', function (args, kwargs) {
+            return [{__context: [], __domain: []}];
+        });
+        return m.query().group_by().done(function (groups) {
+            strictEqual(groups.length, 1,
+                        "should generate a single fake-ish group");
+        });
+    });
+});