From 7d2e30d529bf37dcf5a7eaa32302887ba77ccefe Mon Sep 17 00:00:00 2001 From: Zlash65 Date: Fri, 27 Oct 2017 17:08:51 +0530 Subject: [PATCH 1/4] count issue if child table exists in filter fix --- frappe/model/db_query.py | 20 ++++++++++++++++--- frappe/public/js/frappe/list/list_renderer.js | 4 ++-- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/frappe/model/db_query.py b/frappe/model/db_query.py index 26075f4daa..90f320b334 100644 --- a/frappe/model/db_query.py +++ b/frappe/model/db_query.py @@ -581,10 +581,24 @@ def get_list(doctype, *args, **kwargs): @frappe.whitelist() def get_count(doctype, filters=None): - if filters: - filters = json.loads(filters) - if isinstance(filters, list): filters = frappe.utils.make_filter_dict(filters) return frappe.db.count(doctype, filters=filters) + +@frappe.whitelist() +def set_filters(doctype, filters=None): + count = [] + if filters: + filters = json.loads(filters) + + for d in filters: + filt = [] + if d[0] != doctype: + doctype = d[0] + filt.append(d) + + count.append(get_count(doctype, filt)) + if count: + return min(count) + return count diff --git a/frappe/public/js/frappe/list/list_renderer.js b/frappe/public/js/frappe/list/list_renderer.js index 7a831b6606..864b15dab5 100644 --- a/frappe/public/js/frappe/list/list_renderer.js +++ b/frappe/public/js/frappe/list/list_renderer.js @@ -362,13 +362,13 @@ frappe.views.ListRenderer = Class.extend({ const $header_right = this.list_view.list_header.find('.list-item__content--activity'); frappe.call({ - method: 'frappe.model.db_query.get_count', + method: 'frappe.model.db_query.set_filters', args: { doctype: this.doctype, filters: this.list_view.get_filters_args() } }).then(r => { - const count = r.message; + const count = r.message ? r.message : current_count; const $html = $(`${current_count} of ${count}`); $html.css({ From 2b78da673a747eb9253ac275b3d5948e857a3475 Mon Sep 17 00:00:00 2001 From: Zlash65 Date: Sat, 28 Oct 2017 13:04:44 +0530 Subject: [PATCH 2/4] better table join and fetch from multiple tables --- frappe/model/db_query.py | 57 ++++++++++++------- frappe/public/js/frappe/list/list_renderer.js | 2 +- 2 files changed, 39 insertions(+), 20 deletions(-) diff --git a/frappe/model/db_query.py b/frappe/model/db_query.py index 90f320b334..06178b8dfe 100644 --- a/frappe/model/db_query.py +++ b/frappe/model/db_query.py @@ -581,24 +581,43 @@ def get_list(doctype, *args, **kwargs): @frappe.whitelist() def get_count(doctype, filters=None): - if isinstance(filters, list): - filters = frappe.utils.make_filter_dict(filters) + if filters: + filters = json.loads(filters) - return frappe.db.count(doctype, filters=filters) + if is_parent_only_filter(doctype, filters): + if isinstance(filters, list): + filters = frappe.utils.make_filter_dict(filters) -@frappe.whitelist() -def set_filters(doctype, filters=None): - count = [] - if filters: - filters = json.loads(filters) - - for d in filters: - filt = [] - if d[0] != doctype: - doctype = d[0] - filt.append(d) - - count.append(get_count(doctype, filt)) - if count: - return min(count) - return count + return frappe.db.count(doctype, filters=filters) + + else: + # If filters contain child table as well as parent doctype - Join + tables, conditions = ['`tab{0}`'.format(doctype)], [] + for f in filters: + fieldname = '`tab{0}`.{1}'.format(f[0], f[1]) + table = '`tab{0}`'.format(f[0]) + + if table not in tables: + tables.append(table) + + conditions.append('{fieldname} {operator} "{value}"'.format(fieldname=fieldname, + operator=f[2], value=f[3])) + + if doctype != f[0]: + join_condition = '`tab{child_doctype}`.parent =`tab{doctype}`.name'.format(child_doctype=f[0], doctype=doctype) + if join_condition not in conditions: + conditions.append(join_condition) + + return frappe.db.sql_list("""select count(*) from {0} + where {1}""".format(','.join(tables), ' and '.join(conditions)), debug=1) + +def is_parent_only_filter(doctype, filters): + #check if filters contains only parent doctype + only_parent_doctype = True + + if isinstance(filters, list): + for flt in filters: + if doctype not in flt: + only_parent_doctype = False + + return only_parent_doctype diff --git a/frappe/public/js/frappe/list/list_renderer.js b/frappe/public/js/frappe/list/list_renderer.js index 864b15dab5..d7faf78331 100644 --- a/frappe/public/js/frappe/list/list_renderer.js +++ b/frappe/public/js/frappe/list/list_renderer.js @@ -362,7 +362,7 @@ frappe.views.ListRenderer = Class.extend({ const $header_right = this.list_view.list_header.find('.list-item__content--activity'); frappe.call({ - method: 'frappe.model.db_query.set_filters', + method: 'frappe.model.db_query.get_count', args: { doctype: this.doctype, filters: this.list_view.get_filters_args() From fec63a32f1dd25ecd2cd2a4c4033cad029ad54e5 Mon Sep 17 00:00:00 2001 From: Zlash65 Date: Mon, 30 Oct 2017 15:12:22 +0530 Subject: [PATCH 3/4] test case added for count --- frappe/model/db_query.py | 2 +- frappe/tests/ui/test_list_count.js | 34 ++++++++++++++++++++++++++++++ frappe/tests/ui/tests.txt | 1 + 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 frappe/tests/ui/test_list_count.js diff --git a/frappe/model/db_query.py b/frappe/model/db_query.py index 06178b8dfe..4f05dace81 100644 --- a/frappe/model/db_query.py +++ b/frappe/model/db_query.py @@ -609,7 +609,7 @@ def get_count(doctype, filters=None): conditions.append(join_condition) return frappe.db.sql_list("""select count(*) from {0} - where {1}""".format(','.join(tables), ' and '.join(conditions)), debug=1) + where {1}""".format(','.join(tables), ' and '.join(conditions)), debug=0) def is_parent_only_filter(doctype, filters): #check if filters contains only parent doctype diff --git a/frappe/tests/ui/test_list_count.js b/frappe/tests/ui/test_list_count.js new file mode 100644 index 0000000000..0261555840 --- /dev/null +++ b/frappe/tests/ui/test_list_count.js @@ -0,0 +1,34 @@ +QUnit.module('Setup'); + +QUnit.test("Test List Count", function(assert) { + assert.expect(3); + const done = assert.async(); + + frappe.run_serially([ + () => frappe.set_route('List', 'DocType'), + () => frappe.timeout(0.5), + () => { + let count = $('.list-row-right').text().split(' ')[0]; + assert.equal(cur_list.data.length, count, "Correct Count"); + }, + + () => frappe.timeout(1), + () => cur_list.filter_list.add_filter('Doctype', 'module', '=', 'Desk'), + () => frappe.click_button('Refresh'), + () => { + let count = $('.list-row-right').text().split(' ')[0]; + assert.equal(cur_list.data.length, count, "Correct Count"); + }, + + () => cur_list.filter_list.clear_filters(), + () => frappe.timeout(1), + () => { + cur_list.filter_list.push_new_filter('DocField', 'fieldname', 'like', 'owner'); + frappe.click_button('Apply'); + let count = $('.list-row-right').text().split(' ')[0]; + assert.equal(cur_list.data.length, count, "Correct Count"); + }, + + done + ]); +}); \ No newline at end of file diff --git a/frappe/tests/ui/tests.txt b/frappe/tests/ui/tests.txt index 076d1a515b..7ed6e80be6 100644 --- a/frappe/tests/ui/tests.txt +++ b/frappe/tests/ui/tests.txt @@ -17,3 +17,4 @@ frappe/tests/ui/test_control_html.js frappe/tests/ui/test_control_geolocation.js frappe/core/doctype/role_profile/test_role_profile.js frappe/core/doctype/user/test_user_with_role_profile.js +frappe/tests/ui/test_list_count.js From 539328f5918be710b21ad0c7ef23ab22a696d97b Mon Sep 17 00:00:00 2001 From: Zlash65 Date: Wed, 1 Nov 2017 11:34:18 +0530 Subject: [PATCH 4/4] between date filter fix --- frappe/model/db_query.py | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/frappe/model/db_query.py b/frappe/model/db_query.py index 4f05dace81..d0db452ae7 100644 --- a/frappe/model/db_query.py +++ b/frappe/model/db_query.py @@ -308,15 +308,7 @@ class DatabaseQuery(object): if f.operator.lower() == 'between' and \ (f.fieldname in ('creation', 'modified') or (df and (df.fieldtype=="Date" or df.fieldtype=="Datetime"))): - from_date = None - to_date = None - if f.value and isinstance(f.value, (list, tuple)): - if len(f.value) >= 1: from_date = f.value[0] - if len(f.value) >= 2: to_date = f.value[1] - - value = "'%s' AND '%s'" % ( - add_to_date(get_datetime(from_date),days=-1).strftime("%Y-%m-%d %H:%M:%S.%f"), - get_datetime(to_date).strftime("%Y-%m-%d %H:%M:%S.%f")) + value = get_between_date_filter(f.value) fallback = "'0000-00-00 00:00:00'" elif df and df.fieldtype=="Date": @@ -619,5 +611,21 @@ def is_parent_only_filter(doctype, filters): for flt in filters: if doctype not in flt: only_parent_doctype = False + if 'Between' in flt: + flt[3] = get_between_date_filter(flt[3]) return only_parent_doctype + +def get_between_date_filter(value): + from_date = None + to_date = None + + if value and isinstance(value, (list, tuple)): + if len(value) >= 1: from_date = value[0] + if len(value) >= 2: to_date = value[1] + + data = "'%s' AND '%s'" % ( + add_to_date(get_datetime(from_date),days=-1).strftime("%Y-%m-%d %H:%M:%S.%f"), + get_datetime(to_date).strftime("%Y-%m-%d %H:%M:%S.%f")) + + return data