fix(report): move count, aggregation to serverside

This commit is contained in:
Rushabh Mehta 2021-03-30 09:47:07 +05:30
parent c9b367933a
commit 6d978a1df0
3 changed files with 33 additions and 21 deletions

View file

@ -27,6 +27,13 @@ def get_list():
# uncompressed (refactored from frappe.model.db_query.get_list)
return execute(**get_form_params())
@frappe.whitelist()
@frappe.read_only()
def get_count():
args = get_form_params()
args.fields = ['{distinct}count(name) as total_count'.format(distinct = 'distinct ' if args.distinct=='true' else '')]
return execute(**args)[0].get('total_count')
def execute(doctype, *args, **kwargs):
return DatabaseQuery(doctype).execute(*args, **kwargs)
@ -35,6 +42,7 @@ def get_form_params():
data = frappe._dict(frappe.local.form_dict)
clean_params(data)
parse_json(data)
setup_group_by(data)
validate_fields(data)
if data.filters:
@ -99,6 +107,22 @@ def validate_filters(data, filters):
if not df:
raise_invalid_field(fieldname)
def setup_group_by(data):
'''
Add columns for aggregated values e.g. count(name)
'''
if data.group_by:
if data.aggregate_function.lower() not in ('count', 'sum', 'avg'):
frappe.throw('Invalid aggregate function')
if '`' in data.aggregate_on:
raise_invalid_field(data.aggregate_on)
data.fields.append('{aggregate_function}(`tab{doctype}`.`{aggregate_on}`) AS _aggregate_column'.format(**data))
if data.aggregate_on:
data.fields.append(data.aggregate_on)
data.pop('aggregate_on')
data.pop('aggregate_function')
def raise_invalid_field(fieldname):
frappe.throw(_('Field not permitted in query') + ': {0}'.format(fieldname), frappe.DataError)

View file

@ -92,25 +92,25 @@ frappe.db = {
},
count: function(doctype, args={}) {
let filters = args.filters || {};
const with_child_table_filter = Array.isArray(filters) && filters.some(filter => {
// has a filter with childtable?
const distinct = Array.isArray(filters) && filters.some(filter => {
return filter[0] !== doctype;
});
const fields = [
// cannot break this line as it adds extra \n's and \t's which breaks the query
`count(${with_child_table_filter ? 'distinct': ''} ${frappe.model.get_full_column_name('name', doctype)}) AS total_count`
];
const fields = [];
return frappe.call({
type: 'GET',
method: 'frappe.desk.reportview.get',
method: 'frappe.desk.reportview.get_count',
args: {
doctype,
filters,
fields,
distinct,
}
}).then(r => {
return r.message.values[0][0];
return r.message.values;
});
},
get_link_options(doctype, txt = '', filters={}) {

View file

@ -286,15 +286,6 @@ frappe.ui.GroupBy = class {
set_args(args) {
if (this.aggregate_function && this.group_by) {
let aggregate_column, aggregate_on_field;
if (this.aggregate_function === 'count') {
aggregate_column = 'count(`tab' + this.doctype + '`.`name`)';
} else {
aggregate_column = `${this.aggregate_function}(${this.aggregate_on})`;
aggregate_on_field = this.aggregate_on;
}
this.report_view.group_by = this.group_by;
this.report_view.sort_by = '_aggregate_column';
this.report_view.sort_order = 'desc';
@ -316,17 +307,14 @@ frappe.ui.GroupBy = class {
'_aggregate_column',
this.aggregate_on_doctype || this.doctype,
]);
args.fields.push(aggregate_column + ' as _aggregate_column');
if (aggregate_on_field) {
args.fields.push(aggregate_on_field);
}
// setup columns in datatable
this.report_view.setup_columns();
Object.assign(args, {
with_comment_count: false,
aggregate_on: this.aggregate_on || 'name',
aggregate_function: this.aggregate_function || 'count',
group_by: this.report_view.group_by || null,
order_by: '_aggregate_column desc',
});