diff --git a/addons/web/static/src/js/views/pivot/pivot_view.js b/addons/web/static/src/js/views/pivot/pivot_view.js
index 5c1562efb8c..d85076f8271 100644
--- a/addons/web/static/src/js/views/pivot/pivot_view.js
+++ b/addons/web/static/src/js/views/pivot/pivot_view.js
@@ -69,6 +69,14 @@ var PivotView = AbstractView.extend({
widgets[name] = field.attrs.widget;
}
+ if (field.attrs.string) {
+ measures[name].string = field.attrs.string;
+ }
+
+ if (field.attrs.invisible && py.eval(field.attrs.invisible)) {
+ delete measures[name];
+ return;
+ }
// add active measures to the measure list. This is very rarely
// necessary, but it can be useful if one is working with a
// functional field non stored, but in a model with an overrided
diff --git a/addons/web/static/tests/views/pivot_tests.js b/addons/web/static/tests/views/pivot_tests.js
index 858edcd55e4..5baafda7800 100644
--- a/addons/web/static/tests/views/pivot_tests.js
+++ b/addons/web/static/tests/views/pivot_tests.js
@@ -130,6 +130,52 @@ QUnit.module('Views', {
pivot.destroy();
});
+ QUnit.test('pivot rendering with string attribute on field', function (assert) {
+ assert.expect(1);
+
+ this.data.partner.fields.foo = {string: "Foo", type: "integer", store: true};
+
+ var pivot = createView({
+ View: PivotView,
+ model: "partner",
+ data: this.data,
+ arch: '' +
+ '' +
+ '',
+ });
+
+ assert.strictEqual(pivot.$('.o_pivot_measure_row').text(), "BAR",
+ "the displayed name should be the one set in the string attribute");
+ pivot.destroy();
+ });
+
+ QUnit.test('pivot rendering with invisible attribute on field', function (assert) {
+ assert.expect(2);
+ // when invisible, a field should neither be an active measure,
+ // nor be a selectable measure.
+ _.extend(this.data.partner.fields, {
+ foo: {string: "Foo", type: "integer", store: true},
+ foo2: {string: "Foo2", type: "integer", store: true}
+ })
+
+ var pivot = createView({
+ View: PivotView,
+ model: "partner",
+ data: this.data,
+ arch: '' +
+ '' +
+ '' +
+ '',
+ });
+
+ // there should be only one displayed measure as the other one is invisible
+ assert.containsOnce(pivot, '.o_pivot_measure_row');
+ // there should be only one measure besides count, as the other one is invisible
+ assert.containsN(document.body, '.dropdown-item', 2);
+
+ pivot.destroy();
+ });
+
QUnit.test('pivot view without "string" attribute', function (assert) {
assert.expect(1);
diff --git a/doc/reference/views.rst b/doc/reference/views.rst
index 52af59ecad4..cd96ae1b4a5 100644
--- a/doc/reference/views.rst
+++ b/doc/reference/views.rst
@@ -935,6 +935,10 @@ following attributes:
the name of a field to use in the view. If used for grouping (rather
than aggregating)
+``string``
+ the name that will be used to display the field in the pivot view,
+ overrides the default python String attribute of the field.
+
``type``
indicates whether the field should be used as a grouping criteria or as an
aggregated value within a group. Possible values are:
@@ -950,6 +954,11 @@ following attributes:
``week``, ``month``, ``quarter`` or ``year``) instead of grouping on the
specific datetime (fixed second resolution) or date (fixed day resolution).
+``invisible``
+ if true, the field will not appear either in the active measures nor in the
+ selectable measures (useful for fields that do not make sense aggregated,
+ such as fields in different units, e.g. € and $).
+
The measures are automatically generated from the model fields; only the
aggregatable fields are used. Those measures are also alphabetically
sorted on the string of the field.