diff --git a/setup/web_pivot_hide_total/odoo/addons/web_pivot_hide_total b/setup/web_pivot_hide_total/odoo/addons/web_pivot_hide_total
new file mode 120000
index 000000000000..f7517efcf20e
--- /dev/null
+++ b/setup/web_pivot_hide_total/odoo/addons/web_pivot_hide_total
@@ -0,0 +1 @@
+../../../../web_pivot_hide_total
\ No newline at end of file
diff --git a/setup/web_pivot_hide_total/setup.py b/setup/web_pivot_hide_total/setup.py
new file mode 100644
index 000000000000..28c57bb64031
--- /dev/null
+++ b/setup/web_pivot_hide_total/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+ setup_requires=['setuptools-odoo'],
+ odoo_addon=True,
+)
diff --git a/web_pivot_hide_total/README.rst b/web_pivot_hide_total/README.rst
new file mode 100644
index 000000000000..d7f8f00abe2d
--- /dev/null
+++ b/web_pivot_hide_total/README.rst
@@ -0,0 +1 @@
+This file is going to be generated by oca-gen-addon-readme.
diff --git a/web_pivot_hide_total/__init__.py b/web_pivot_hide_total/__init__.py
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/web_pivot_hide_total/__manifest__.py b/web_pivot_hide_total/__manifest__.py
new file mode 100644
index 000000000000..c5ad0f7d443c
--- /dev/null
+++ b/web_pivot_hide_total/__manifest__.py
@@ -0,0 +1,16 @@
+# Copyright 2017 ACSONE SA/NV
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+{
+ "name": "Web Pivot View Hide Total",
+ "summary": """
+ This addon adds a new inherited version of pivot view.
+ It intends to hide the last total column when required.""",
+ "version": "14.0.1.0.0",
+ "license": "AGPL-3",
+ "author": "ACSONE SA/NV,Odoo Community Association (OCA)",
+ "website": "https://github.com/OCA/web",
+ "depends": ["web"],
+ "data": ["views/web_pivot_hide_total_views.xml"],
+ "installable": True,
+}
diff --git a/web_pivot_hide_total/readme/CONFIGURATION.rst b/web_pivot_hide_total/readme/CONFIGURATION.rst
new file mode 100644
index 000000000000..bd9d6b24a0a3
--- /dev/null
+++ b/web_pivot_hide_total/readme/CONFIGURATION.rst
@@ -0,0 +1,18 @@
+Activation of the view is done in xml file, using "js_class" tag.
+
+In your xml file, declare a pivot view with js_class="web_pivot_hide_total".
+
+For example :
+
+.. code-block:: xml
+
+
+ my.model
+
+
+
+
+
+
+
+
diff --git a/web_pivot_hide_total/readme/CONFIGURE.rst b/web_pivot_hide_total/readme/CONFIGURE.rst
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/web_pivot_hide_total/readme/CONTRIBUTORS.rst b/web_pivot_hide_total/readme/CONTRIBUTORS.rst
new file mode 100644
index 000000000000..79b40021f0d8
--- /dev/null
+++ b/web_pivot_hide_total/readme/CONTRIBUTORS.rst
@@ -0,0 +1,2 @@
+* RĂ©gis Pirard
+* Souheil Bejaoui
diff --git a/web_pivot_hide_total/readme/DESCRIPTION.rst b/web_pivot_hide_total/readme/DESCRIPTION.rst
new file mode 100644
index 000000000000..e7851433b4eb
--- /dev/null
+++ b/web_pivot_hide_total/readme/DESCRIPTION.rst
@@ -0,0 +1,13 @@
+In some cases, we want to use the columns of a pivot view
+to compare datas, but the total sum displayed in the last column
+juste makes no sens.
+
+This module intends to hide that last total column when required.
+
+.. image:: ../static/description/before.png
+ :alt: Before
+
+\
+
+.. image:: ../static/description/after.png
+ :alt: After
diff --git a/web_pivot_hide_total/readme/ROADMAP.rst b/web_pivot_hide_total/readme/ROADMAP.rst
new file mode 100644
index 000000000000..8667f3e5259b
--- /dev/null
+++ b/web_pivot_hide_total/readme/ROADMAP.rst
@@ -0,0 +1 @@
+* Allow setting default dialog size per user.
diff --git a/web_pivot_hide_total/static/description/after.png b/web_pivot_hide_total/static/description/after.png
new file mode 100644
index 000000000000..c5923b6e894c
Binary files /dev/null and b/web_pivot_hide_total/static/description/after.png differ
diff --git a/web_pivot_hide_total/static/description/before.png b/web_pivot_hide_total/static/description/before.png
new file mode 100644
index 000000000000..05f42fe3b6e3
Binary files /dev/null and b/web_pivot_hide_total/static/description/before.png differ
diff --git a/web_pivot_hide_total/static/description/icon.png b/web_pivot_hide_total/static/description/icon.png
new file mode 100644
index 000000000000..3a0328b516c4
Binary files /dev/null and b/web_pivot_hide_total/static/description/icon.png differ
diff --git a/web_pivot_hide_total/static/src/js/views/pivot/pivot_model_hide_total.js b/web_pivot_hide_total/static/src/js/views/pivot/pivot_model_hide_total.js
new file mode 100644
index 000000000000..ff92993c0555
--- /dev/null
+++ b/web_pivot_hide_total/static/src/js/views/pivot/pivot_model_hide_total.js
@@ -0,0 +1,86 @@
+odoo.define("web.PivotModelHideTotal", function (require) {
+ "use strict";
+
+ const {_t} = require("web.core");
+
+ const PivotModel = require("web.PivotModel");
+
+ const PivotModelHideTotal = PivotModel.extend({
+ /**
+ * @override
+ */
+ _getTableHeaders: function () {
+ var colGroupBys = this._getGroupBys().colGroupBys;
+ var height = colGroupBys.length + 1;
+ var measureCount = this.data.measures.length;
+ var originCount = this.data.origins.length;
+ var leafCounts = this._getLeafCounts(this.colGroupTree);
+ var headers = [];
+ var measureColumns = [];
+
+ // 1) generate col group rows (total row + one row for each col groupby)
+ var colGroupRows = new Array(height).fill(0).map(function () {
+ return [];
+ });
+ // Blank top left cell
+ colGroupRows[0].push({
+ height: height + 1 + (originCount > 1 ? 1 : 0),
+ title: "",
+ width: 1,
+ });
+
+ // Col groupby cells with group values
+ /**
+ * Recursive function that generates the header cells corresponding to
+ * the groups of a given tree.
+ *
+ * @param {Object} tree
+ * @param {Object} fields
+ */
+ function generateTreeHeaders(tree, fields) {
+ var group = tree.root;
+ var rowIndex = group.values.length;
+ var row = colGroupRows[rowIndex];
+ var groupId = [[], group.values];
+ var isLeaf = !tree.directSubTrees.size;
+ var leafCount = leafCounts[JSON.stringify(tree.root.values)];
+ var cell = {
+ groupId: groupId,
+ height: isLeaf ? colGroupBys.length + 1 - rowIndex : 1,
+ isLeaf: isLeaf,
+ label:
+ rowIndex === 0
+ ? undefined
+ : fields[colGroupBys[rowIndex - 1].split(":")[0]].string,
+ title: group.labels[group.labels.length - 1] || _t("Total"),
+ width: leafCount * measureCount * (2 * originCount - 1),
+ };
+ row.push(cell);
+ if (isLeaf) {
+ measureColumns.push(cell);
+ }
+
+ [...tree.directSubTrees.values()].forEach(function (subTree) {
+ generateTreeHeaders(subTree, fields);
+ });
+ }
+
+ generateTreeHeaders(this.colGroupTree, this.fields);
+
+ headers = headers.concat(colGroupRows);
+
+ // 2) generate measures row
+ var measuresRow = this._getMeasuresRow(measureColumns);
+ headers.push(measuresRow);
+
+ // 3) generate origins row if more than one origin
+ if (originCount > 1) {
+ headers.push(this._getOriginsRow(measuresRow));
+ }
+
+ return headers;
+ },
+ });
+
+ return PivotModelHideTotal;
+});
diff --git a/web_pivot_hide_total/static/src/js/views/pivot/pivot_view_hide_total.js b/web_pivot_hide_total/static/src/js/views/pivot/pivot_view_hide_total.js
new file mode 100644
index 000000000000..6886d0031fb4
--- /dev/null
+++ b/web_pivot_hide_total/static/src/js/views/pivot/pivot_view_hide_total.js
@@ -0,0 +1,17 @@
+odoo.define("web_pivot_hide_total.PivotViewHideTotal", function (require) {
+ "use strict";
+
+ const PivotView = require("web.PivotView");
+ const PivotModelHideTotal = require("web.PivotModelHideTotal");
+ const viewRegistry = require("web.view_registry");
+
+ const PivotViewHideTotal = PivotView.extend({
+ config: _.extend({}, PivotView.prototype.config, {
+ Model: PivotModelHideTotal,
+ }),
+ });
+
+ viewRegistry.add("web_pivot_hide_total", PivotViewHideTotal);
+
+ return PivotViewHideTotal;
+});
diff --git a/web_pivot_hide_total/views/web_pivot_hide_total_views.xml b/web_pivot_hide_total/views/web_pivot_hide_total_views.xml
new file mode 100644
index 000000000000..0d96aff1e944
--- /dev/null
+++ b/web_pivot_hide_total/views/web_pivot_hide_total_views.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+