[REF] moves more code to dataLoader class to simplify pivot class (clean separation between pivot code and loading code) (addon web_graph)
bzr revid: ged@openerp.com-20131217111501-wu0nbid36bncy4wz
This commit is contained in:
parent
65642c8c06
commit
de51e3c35a
|
@ -163,7 +163,7 @@ instance.web_graph.GraphView = instance.web.View.extend({
|
|||
display_data: function () {
|
||||
var pivot = this.pivot_table;
|
||||
if (pivot.stale_data) {
|
||||
pivot.load_data().done(this.proxy('display_data'));
|
||||
pivot.update_data().done(this.proxy('display_data'));
|
||||
} else {
|
||||
this.$('.graph_main_content svg').remove();
|
||||
this.table.empty();
|
||||
|
|
|
@ -117,15 +117,15 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({
|
|||
|
||||
// return all non expanded rows
|
||||
get_rows_leaves: function () {
|
||||
return _.filter(this.rows.headers, function (hdr) {
|
||||
return !hdr.is_expanded;
|
||||
return _.filter(this.rows.headers, function (hdr) {
|
||||
return !hdr.is_expanded;
|
||||
});
|
||||
},
|
||||
|
||||
// return all non expanded cols
|
||||
get_cols_leaves: function () {
|
||||
return _.filter(this.cols.headers, function (hdr) {
|
||||
return !hdr.is_expanded;
|
||||
return _.filter(this.cols.headers, function (hdr) {
|
||||
return !hdr.is_expanded;
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -232,54 +232,25 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({
|
|||
this.stale_data = true;
|
||||
},
|
||||
|
||||
// To obtain all the values required to draw the full table, we have to do
|
||||
// at least 2 + min(row.groupby.length, col.groupby.length)
|
||||
// calls to readgroup. For example, if row.groupby = [r1, r2, r3] and
|
||||
// col.groupby = [c1, c2, c3, c4], then a minimal set of calls is done
|
||||
// with the following groupby:
|
||||
// [], [c1, c2, c3, c4], r1, c1, c2, c3, c4], [r1, r2, c1, c2, c3, c4],
|
||||
// [r1, r2, r3, c1, c2, c3, c4]
|
||||
// To simplify the code, we will always do 2 + row.groupby.length calls,
|
||||
// unless col.groupby.length = 0, in which case we do 2 calls ([] and
|
||||
// row_groupbys), but this can be optimized later.
|
||||
load_data: function () {
|
||||
update_data: function () {
|
||||
var self = this,
|
||||
cols = this.cols.groupby,
|
||||
rows = this.rows.groupby,
|
||||
def_array,
|
||||
groupbys;
|
||||
options = {
|
||||
col_groupby: this.cols.groupby,
|
||||
row_groupby: this.rows.groupby,
|
||||
measure: this.measure,
|
||||
domain: this.domain,
|
||||
};
|
||||
|
||||
if (cols.length > 0) {
|
||||
groupbys = _.map(_.range(rows.length + 1), function (i) {
|
||||
return rows.slice(0, i).concat(cols);
|
||||
});
|
||||
groupbys.push([]);
|
||||
} else {
|
||||
groupbys = [rows, []];
|
||||
}
|
||||
def_array = _.map(groupbys, function (groupby) {
|
||||
return self.data_loader.get_groups(self.visible_fields(), self.domain, groupby);
|
||||
});
|
||||
|
||||
return $.when.apply(null, def_array).then(function () {
|
||||
var args = Array.prototype.slice.call(arguments),
|
||||
col_data = _.first(args),
|
||||
total = _.last(args)[0],
|
||||
row_data = _.last(_.initial(args)),
|
||||
cell_data = args;
|
||||
|
||||
return (total === undefined) ? undefined
|
||||
: self.format_data(total, col_data, row_data, cell_data);
|
||||
}).then(function (result) {
|
||||
return this.data_loader.load_data(options).then (function (result) {
|
||||
self.stale_data = false;
|
||||
if (result) {
|
||||
self.no_data = false;
|
||||
if (self.cols.headers) {
|
||||
self.update_headers(self.cols, result.col_headers);
|
||||
self.update_headers(self.rows, result.row_headers);
|
||||
self.update_headers(self.rows, result.row_headers);
|
||||
} else {
|
||||
self.expand_headers(self.cols, result.col_headers);
|
||||
self.expand_headers(self.rows, result.row_headers);
|
||||
self.expand_headers(self.rows, result.row_headers);
|
||||
}
|
||||
self.cells = result.cells;
|
||||
} else {
|
||||
|
@ -325,10 +296,127 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({
|
|||
root.main = root.headers[0];
|
||||
},
|
||||
|
||||
format_data: function (total, col_data, row_data, cell_data) {
|
||||
});
|
||||
|
||||
openerp.web_graph.DataLoader = openerp.web.Class.extend({
|
||||
init: function (model) {
|
||||
this.model = model;
|
||||
},
|
||||
|
||||
get_groups: function (fields, domain, groupbys, options) {
|
||||
var self = this,
|
||||
dim_row = this.rows.groupby.length,
|
||||
dim_col = this.cols.groupby.length,
|
||||
options = (options) ? options : {},
|
||||
groupings = (options.first_groupby) ? [options.first_groupby].concat(groupbys) : groupbys;
|
||||
|
||||
return this.query_db(fields, domain, groupings).then(function (groups) {
|
||||
return _.map(groups, function (group) {
|
||||
return (options.add_path) ?self.add_path(group, []) : group;
|
||||
});
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
query_db: function (fields, domain, groupbys) {
|
||||
var self = this;
|
||||
return this.model.query(fields)
|
||||
.filter(domain)
|
||||
.group_by(groupbys)
|
||||
.then(function (results) {
|
||||
var non_empty_results = _.filter(results, function (group) {
|
||||
return group.attributes.length > 0;
|
||||
});
|
||||
_.each(non_empty_results, self.sanitize_value);
|
||||
if (groupbys.length <= 1) {
|
||||
return non_empty_results;
|
||||
} else {
|
||||
var get_subgroups = $.when.apply(null, _.map(non_empty_results, function (result) {
|
||||
var new_domain = result.model._domain;
|
||||
var new_groupings = groupbys.slice(1);
|
||||
return self.query_db(fields,new_domain, new_groupings).then(function (subgroups) {
|
||||
result.subgroups_data = subgroups;
|
||||
});
|
||||
}));
|
||||
return get_subgroups.then(function () {
|
||||
return non_empty_results;
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
sanitize_value: function (group) {
|
||||
var value = group.attributes.value;
|
||||
if (value === false) {
|
||||
group.attributes.value = 'undefined';
|
||||
} else if (value instanceof Array) {
|
||||
group.attributes.value = value[1];
|
||||
} else {
|
||||
group.attributes.value = value;
|
||||
}
|
||||
},
|
||||
|
||||
add_path: function (group, current_path) {
|
||||
var self = this;
|
||||
|
||||
group.path = current_path.concat(group.attributes.value);
|
||||
var result = [group];
|
||||
_.each(group.subgroups_data, function (subgroup) {
|
||||
result = result.concat(self.add_path(subgroup, group.path));
|
||||
});
|
||||
return result;
|
||||
},
|
||||
|
||||
// To obtain all the values required to draw the full table, we have to do
|
||||
// at least 2 + min(row.groupby.length, col.groupby.length)
|
||||
// calls to readgroup. For example, if row.groupby = [r1, r2, r3] and
|
||||
// col.groupby = [c1, c2, c3, c4], then a minimal set of calls is done
|
||||
// with the following groupby:
|
||||
// [], [c1, c2, c3, c4], r1, c1, c2, c3, c4], [r1, r2, c1, c2, c3, c4],
|
||||
// [r1, r2, r3, c1, c2, c3, c4]
|
||||
// To simplify the code, we will always do 2 + row.groupby.length calls,
|
||||
// unless col.groupby.length = 0, in which case we do 2 calls ([] and
|
||||
// row_groupbys), but this can be optimized later.
|
||||
load_data: function (options) {
|
||||
var self = this,
|
||||
cols = options.col_groupby,
|
||||
rows = options.row_groupby,
|
||||
measure = options.measure,
|
||||
domain = options.domain,
|
||||
visible_fields = rows.concat(cols),
|
||||
def_array,
|
||||
groupbys;
|
||||
|
||||
if (measure) { visible_fields = visible_fields.concat(measure); }
|
||||
|
||||
if (cols.length > 0) {
|
||||
groupbys = _.map(_.range(rows.length + 1), function (i) {
|
||||
return rows.slice(0, i).concat(cols);
|
||||
});
|
||||
groupbys.push([]);
|
||||
} else {
|
||||
groupbys = [rows, []];
|
||||
}
|
||||
def_array = _.map(groupbys, function (groupby) {
|
||||
return self.get_groups(visible_fields, domain, groupby);
|
||||
});
|
||||
|
||||
return $.when.apply(null, def_array).then(function () {
|
||||
var args = Array.prototype.slice.call(arguments),
|
||||
col_data = _.first(args),
|
||||
total = _.last(args)[0],
|
||||
row_data = _.last(_.initial(args)),
|
||||
cell_data = args;
|
||||
|
||||
return (total === undefined) ? undefined
|
||||
: self.format_data(total, col_data, row_data, cell_data, options);
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
format_data: function (total, col_data, row_data, cell_data, options) {
|
||||
var self = this,
|
||||
dim_row = options.row_groupby.length,
|
||||
dim_col = options.col_groupby.length,
|
||||
measure = options.measure,
|
||||
col_headers = make_headers(col_data, dim_col),
|
||||
row_headers = make_headers(row_data, dim_row),
|
||||
cells = [];
|
||||
|
@ -353,10 +441,10 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({
|
|||
parent: null,
|
||||
children: [],
|
||||
title: '',
|
||||
domain: self.domain,
|
||||
domain: options.domain,
|
||||
};
|
||||
if (self.measure) {
|
||||
main.total = total.attributes.aggregates[self.measure];
|
||||
if (measure) {
|
||||
main.total = total.attributes.aggregates[measure];
|
||||
} else {
|
||||
main.total = total.attributes.length;
|
||||
}
|
||||
|
@ -387,8 +475,8 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({
|
|||
parent: parent,
|
||||
children: [],
|
||||
};
|
||||
if (self.measure) {
|
||||
node.total = data_pt.attributes.aggregates[self.measure];
|
||||
if (measure) {
|
||||
node.total = data_pt.attributes.aggregates[measure];
|
||||
} else {
|
||||
node.total = data_pt.attributes.length;
|
||||
}
|
||||
|
@ -412,8 +500,8 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({
|
|||
group_val = undefined;
|
||||
}
|
||||
|
||||
if (self.measure) {
|
||||
value = attr.aggregates[self.measure];
|
||||
if (measure) {
|
||||
value = attr.aggregates[measure];
|
||||
} else {
|
||||
value = attr.length;
|
||||
}
|
||||
|
@ -446,74 +534,6 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({
|
|||
}
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
openerp.web_graph.DataLoader = openerp.web.Class.extend({
|
||||
init: function (model) {
|
||||
this.model = model;
|
||||
},
|
||||
|
||||
get_groups: function (fields, domain, groupbys, options) {
|
||||
var self = this,
|
||||
options = (options) ? options : {},
|
||||
groupings = (options.first_groupby) ? [options.first_groupby].concat(groupbys) : groupbys;
|
||||
|
||||
return this._query_db(fields, domain, groupings).then(function (groups) {
|
||||
return _.map(groups, function (group) {
|
||||
return (options.add_path) ?self._add_path(group, []) : group;
|
||||
});
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
_query_db: function (fields, domain, groupbys) {
|
||||
var self = this;
|
||||
return this.model.query(fields)
|
||||
.filter(domain)
|
||||
.group_by(groupbys)
|
||||
.then(function (results) {
|
||||
var non_empty_results = _.filter(results, function (group) {
|
||||
return group.attributes.length > 0;
|
||||
});
|
||||
_.each(non_empty_results, self._sanitize_value);
|
||||
if (groupbys.length <= 1) {
|
||||
return non_empty_results;
|
||||
} else {
|
||||
var get_subgroups = $.when.apply(null, _.map(non_empty_results, function (result) {
|
||||
var new_domain = result.model._domain;
|
||||
var new_groupings = groupbys.slice(1);
|
||||
return self._query_db(fields,new_domain, new_groupings).then(function (subgroups) {
|
||||
result.subgroups_data = subgroups;
|
||||
});
|
||||
}));
|
||||
return get_subgroups.then(function () {
|
||||
return non_empty_results;
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
_sanitize_value: function (group) {
|
||||
var value = group.attributes.value;
|
||||
if (value === false) {
|
||||
group.attributes.value = 'undefined';
|
||||
} else if (value instanceof Array) {
|
||||
group.attributes.value = value[1];
|
||||
} else {
|
||||
group.attributes.value = value;
|
||||
}
|
||||
},
|
||||
|
||||
_add_path: function (group, current_path) {
|
||||
var self = this;
|
||||
|
||||
group.path = current_path.concat(group.attributes.value);
|
||||
var result = [group];
|
||||
_.each(group.subgroups_data, function (subgroup) {
|
||||
result = result.concat(self._add_path(subgroup, group.path));
|
||||
});
|
||||
return result;
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in New Issue