[FIX] web: sort pivot rows in comparison mode

Before this commit, it was not possible to sort
the rows of a pivot view while in comparison
mode. This fix makes it now possible. Note that
in comparison mode, a click on a header of type
"measure" will sort the rows according to the
column values coming from the data of interest.

closes odoo/odoo#28411
This commit is contained in:
Mathieu Duckerts-Antoine
2018-12-18 12:56:06 +00:00
parent c7a307ffd2
commit 7618f84beb
4 changed files with 198 additions and 11 deletions
@@ -336,7 +336,8 @@ var PivotController = AbstractController.extend({
var col_id = $target.data('id');
var measure = $target.data('measure');
var isAscending = $target.hasClass('o_pivot_measure_row_sorted_asc');
this.model.sortRows(col_id, measure, isAscending);
var dataType = $target.data('data_type');
this.model.sortRows(col_id, measure, isAscending, dataType);
this.update({}, {reload: false});
},
/**
@@ -457,16 +457,23 @@ var PivotModel = AbstractModel.extend({
* @param {any} col_id
* @param {any} measure
* @param {any} descending
* @param {'data'|'comparisonData'|'variation'} [dataType]
*/
sortRows: function (col_id, measure, descending) {
sortRows: function (col_id, measure, descending, dataType) {
var cells = this.data.cells;
var comparisonFunction = compare;
if (this.data.compare) {
dataType = dataType || 'data';
comparisonFunction = specialCompare;
}
this._traverseTree(this.data.main_row.root, function (header) {
header.children.sort(compare);
header.children.sort(comparisonFunction);
});
this.data.sorted_column = {
id: col_id,
measure: measure,
order: descending ? 'desc' : 'asc',
dataType: dataType,
};
function _getValue (id1, id2) {
if ((id1 in cells) && (id2 in cells[id1])) {
@@ -476,12 +483,26 @@ var PivotModel = AbstractModel.extend({
}
function compare (row1, row2) {
var values1 = _getValue(row1.id, col_id),
values2 = _getValue(row2.id, col_id),
value1 = values1 ? values1[measure] : 0,
value2 = values2 ? values2[measure] : 0;
var values1 = _getValue(row1.id, col_id);
var values2 = _getValue(row2.id, col_id);
var value1 = values1 ? values1[measure] : 0;
var value2 = values2 ? values2[measure] : 0;
return descending ? value1 - value2 : value2 - value1;
}
function specialCompare (row1, row2) {
var values1 = _getValue(row1.id, col_id);
var values2 = _getValue(row2.id, col_id);
var value1 = values1 ? values1[measure] : {data: 0, comparisonData: 0, variation: {magnitude: 0}};
var value2 = values2 ? values2[measure] : {data: 0, comparisonData: 0, variation: {magnitude: 0}};
if (dataType === 'variation') {
return descending ?
value1[dataType].magnitude - value2[dataType].magnitude:
value2[dataType].magnitude - value1[dataType].magnitude;
}
return descending ?
value1[dataType] - value2[dataType]:
value2[dataType] - value1[dataType];
}
},
/**
* Toggle the active state for a given measure, then reload the data.
@@ -116,6 +116,8 @@ var PivotRenderer = AbstractRenderer.extend({
_renderHeaders: function ($thead, headers, nbrCols) {
var self = this;
var i, j, cell, $row, $cell;
var measure, dataType;
var id, measureCellIds = [];
var groupbyLabels = _.map(this.state.colGroupBys, function (gb) {
return self.state.fields[gb.split(':')[0]].string;
@@ -144,10 +146,13 @@ var PivotRenderer = AbstractRenderer.extend({
$cell.data('id', cell.id);
}
if (cell.measure) {
measure = cell.measure;
measureCellIds.push(cell.id);
$cell.addClass('o_pivot_measure_row text-muted')
.text(this.state.fields[cell.measure].string);
$cell.data('id', cell.id).data('measure', cell.measure);
if (!this.compare && cell.id === this.state.sortedColumn.id && cell.measure === this.state.sortedColumn.measure) {
.text(this.state.fields[measure].string);
$cell.data('id', cell.id).data('measure', measure);
if (cell.id === this.state.sortedColumn.id &&
measure === this.state.sortedColumn.measure) {
$cell.addClass('o_pivot_measure_row_sorted_' + this.state.sortedColumn.order);
if (this.state.sortedColumn.order == 'asc') {
$cell.attr('aria-sorted', 'ascending');
@@ -167,12 +172,30 @@ var PivotRenderer = AbstractRenderer.extend({
}
if (this.compare) {
var colLabels = [this.timeRangeDescription, this.comparisonTimeRangeDescription, 'Variation'];
var dataTypes = ['data', 'comparisonData', 'variation'];
$row = $('<tr>');
for (i = 0; i < 3 * nbrCols; i++) {
id = measureCellIds[~~(i / 3)];
measure = this.state.measures[(~~(i / 3)) % this.state.measures.length];
dataType = dataTypes[i % 3];
$cell = $('<th>')
.addClass('o_pivot_measure_row text-muted')
.data('data_type', dataType)
.data('id', id)
.data('measure', measure)
.text(colLabels[i % 3])
.attr('rowspan', 1)
.attr('colspan', 1);
if (dataType === this.state.sortedColumn.dataType &&
id === this.state.sortedColumn.id &&
measure === this.state.sortedColumn.measure) {
$cell.addClass('o_pivot_measure_row_sorted_' + this.state.sortedColumn.order);
if (this.state.sortedColumn.order === 'asc') {
$cell.attr('aria-sorted', 'ascending');
} else {
$cell.attr('aria-sorted', 'descending');
}
}
$row.append($cell);
}
$thead.append($row);
+143 -1
View File
@@ -1417,7 +1417,7 @@ QUnit.module('Views', {
actionManager.destroy();
});
QUnit.test('export data in excel with comparison', function (assert) {
QUnit.test('export data in excel with comparison', function (assert) {
assert.expect(10);
this.data.partner.records[0].date = '2016-12-15';
@@ -1572,5 +1572,147 @@ QUnit.module('Views', {
unpatchDate();
actionManager.destroy();
});
QUnit.module('Sort in comparison mode', {
beforeEach: function () {
this.data.partner.records[0].date = '2016-12-15';
this.data.partner.records[1].date = '2016-12-17';
this.data.partner.records[2].date = '2016-11-22';
this.data.partner.records[3].date = '2016-11-03';
this.data.partner.fields.company_type = {string: "Company Type", type: "selection", selection: [["company", "Company"], ["individual", "individual"]], searchable: true, store: true, sortable: true};
this.data.partner.records[0].company_type = 'company';
this.data.partner.records[1].company_type = 'individual';
this.data.partner.records[2].company_type = 'company';
this.data.partner.records[3].company_type = 'individual';
this.unpatchDate = patchDate(2016, 11, 20, 1, 0, 0);
this.actualResult = function () {
var actualResult = $('.o_pivot .o_pivot_cell_value div').map(function() {
return $( this ).text();
}).get().join();
return actualResult;
};
// create an action manager to test the interactions with the search view
this.actionManager = createActionManager({
data: this.data,
archs: {
'partner,false,pivot': '<pivot>' +
'<field name="date" interval="day" type="row"/>' +
'<field name="company_type" type="col"/>' +
'<field name="foo" type="measure"/>' +
'</pivot>',
'partner,false,search': '<search></search>',
},
debug: 1,
});
this.actionManager.doAction({
res_model: 'partner',
type: 'ir.actions.act_window',
views: [[false, 'pivot']],
flags: {
pivot: {
additionalMeasures: ['product_id'],
}
}
});
// open time range menu
testUtils.dom.click($('.o_control_panel .o_time_range_menu_button'));
// select 'Today' as range
testUtils.fields.editInput($('.o_control_panel .o_time_range_selector'), 'this_month');
// check checkbox 'Compare To'
testUtils.dom.click($('.o_control_panel .o_time_range_menu .o_comparison_checkbox'));
// Click on 'Apply' button
testUtils.dom.click($('.o_control_panel .o_time_range_menu .o_apply_range'));
// We are in comparison mode
},
afterEach: function () {
this.unpatchDate();
this.actionManager.destroy();
},
}, function () {
QUnit.test('when clicking on measure, sort by "This Month" (period of interest)', function (assert) {
assert.expect(1);
// click on 'Foo' in column Total/Company
testUtils.dom.click($('.o_pivot_measure_row').eq(0));
var results = [
"12", "17", "-29.41%", "1", "2", "-50%", "13", "19", "-31.58%",
"12", "0", "100%", "12", "0" , "100%",
"1", "0", "100%", "1" , "0", "100%",
"0", "17", "-100%", "0", "17", "-100%",
"0", "2", "-100%", "0" , "2" , "-100%"
];
assert.strictEqual(this.actualResult(), results.join());
});
QUnit.test(
'click on a period of interest header sort according to the appropriate column ' +
'first in ascending order then in descending order',
function (assert) {
assert.expect(2);
// click on 'This Month' in column Total/Individual/Foo
testUtils.dom.click($('.o_pivot_measure_row').eq(6));
var results = [
"12", "17", "-29.41%", "1", "2", "-50%", "13", "19", "-31.58%",
"1", "0", "100%", "1" , "0", "100%",
"12", "0", "100%", "12", "0" , "100%",
"0", "17", "-100%", "0", "17", "-100%",
"0", "2", "-100%", "0" , "2" , "-100%"
];
var actualResult = $('.o_pivot .o_pivot_cell_value div').text();
assert.strictEqual(actualResult, results.join(''));
// click once again on 'This Month' in column Total/Individual/Foo
testUtils.dom.click($('.o_pivot_measure_row').eq(6));
results = [
"12", "17", "-29.41%", "1", "2", "-50%", "13", "19", "-31.58%",
"12", "0", "100%", "12", "0" , "100%",
"0", "17", "-100%", "0", "17", "-100%",
"0", "2", "-100%", "0" , "2" , "-100%",
"1", "0", "100%", "1" , "0", "100%"
];
assert.strictEqual(this.actualResult(), results.join());
});
QUnit.test('click on a period of comparison header sort according to appropriate column',
function (assert) {
assert.expect(1);
// click on 'Previous Period' in column Total/Individual/Foo
testUtils.dom.click($('.o_pivot_measure_row').eq(7));
var results = [
"12", "17", "-29.41%", "1", "2", "-50%", "13", "19", "-31.58%",
"0", "2", "-100%", "0" , "2" , "-100%",
"12", "0", "100%", "12", "0" , "100%",
"1", "0", "100%", "1" , "0", "100%",
"0", "17", "-100%", "0", "17", "-100%"
];
assert.strictEqual(this.actualResult(), results.join());
});
QUnit.test('click on a variation header sort according to appropriate column',
function (assert) {
assert.expect(1);
// click on 'Variation' in column Total/Individual/Foo
testUtils.dom.click($('.o_pivot_measure_row').eq(11));
var results = [
"12", "17", "-29.41%", "1", "2", "-50%", "13", "19", "-31.58%",
"12", "0", "100%", "12", "0" , "100%",
"1", "0", "100%", "1" , "0", "100%",
"0", "17", "-100%", "0", "17", "-100%",
"0", "2", "-100%", "0" , "2" , "-100%"
];
assert.strictEqual(this.actualResult(), results.join());
});
});
});
});