diff --git a/frappe/__init__.py b/frappe/__init__.py index 8d9eed74a3..e123edce68 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -540,13 +540,15 @@ def build_match_conditions(doctype, as_condition=True): import frappe.widgets.reportview return frappe.widgets.reportview.build_match_conditions(doctype, as_condition) -def get_list(doctype, filters=None, fields=None, docstatus=None, +def get_list(doctype, filters=None, fields=None, or_filters=None, docstatus=None, group_by=None, order_by=None, limit_start=0, limit_page_length=None, as_list=False, debug=False, ignore_permissions=False): import frappe.model.db_query - return frappe.model.db_query.DatabaseQuery(doctype).execute(filters=filters, fields=fields, docstatus=docstatus, - group_by=group_by, order_by=order_by, limit_start=limit_start, limit_page_length=limit_page_length, - as_list=as_list, debug=debug, ignore_permissions=ignore_permissions) + return frappe.model.db_query.DatabaseQuery(doctype).execute(filters=filters, + fields=fields, docstatus=docstatus, or_filters=or_filters, + group_by=group_by, order_by=order_by, limit_start=limit_start, + limit_page_length=limit_page_length, as_list=as_list, debug=debug, + ignore_permissions=ignore_permissions) run_query = get_list diff --git a/frappe/model/db_query.py b/frappe/model/db_query.py index 905d8d53a3..db18b021f5 100644 --- a/frappe/model/db_query.py +++ b/frappe/model/db_query.py @@ -18,15 +18,17 @@ class DatabaseQuery(object): self.ignore_permissions = False self.fields = ["name"] - def execute(self, query=None, filters=None, fields=None, docstatus=None, - group_by=None, order_by=None, limit_start=0, limit_page_length=20, - as_list=False, with_childnames=False, debug=False, ignore_permissions=False): + def execute(self, query=None, filters=None, fields=None, or_filters=None, + docstatus=None, group_by=None, order_by=None, limit_start=0, + limit_page_length=20, as_list=False, with_childnames=False, debug=False, + ignore_permissions=False): if not frappe.has_permission(self.doctype, "read"): raise frappe.PermissionError if fields: self.fields = fields self.filters = filters or [] + self.or_filters = or_filters or [] self.docstatus = docstatus or [] self.group_by = group_by self.order_by = order_by @@ -67,6 +69,8 @@ class DatabaseQuery(object): # query dict args.tables = ', '.join(self.tables) + if self.or_conditions: + self.conditions.append("({0})".format(" or ".join(self.or_conditions))) args.conditions = ' and '.join(self.conditions) args.fields = ', '.join(self.fields) @@ -77,7 +81,6 @@ class DatabaseQuery(object): return args - def parse_args(self): if isinstance(self.filters, basestring): self.filters = json.loads(self.filters) @@ -134,8 +137,10 @@ class DatabaseQuery(object): def build_conditions(self): self.conditions = [] + self.or_conditions = [] self.add_docstatus_conditions() - self.build_filter_conditions() + self.build_filter_conditions(self.filters, self.conditions) + self.build_filter_conditions(self.or_filters, self.or_conditions) # join parent, child tables for tname in self.tables[1:]: @@ -153,11 +158,13 @@ class DatabaseQuery(object): else: self.conditions.append(self.tables[0] + '.docstatus < 2') - def build_filter_conditions(self): + def build_filter_conditions(self, filters, conditions): """build conditions from user filters""" - for f in self.filters: + if isinstance(filters, dict): + filters = [filters] + for f in filters: if isinstance(f, basestring): - self.conditions.append(f) + conditions.append(f) else: f = self.get_filter_tuple(f) @@ -172,7 +179,7 @@ class DatabaseQuery(object): opts = f[3].split(",") opts = ["'" + t.strip().replace("'", "\\'") + "'" for t in opts] f[3] = "(" + ', '.join(opts) + ")" - self.conditions.append('ifnull(' + tname + '.' + f[1] + ", '') " + f[2] + " " + f[3]) + conditions.append('ifnull(' + tname + '.' + f[1] + ", '') " + f[2] + " " + f[3]) else: df = frappe.get_meta(f[0]).get("fields", {"fieldname": f[1]}) @@ -182,7 +189,7 @@ class DatabaseQuery(object): else: value, default_val = flt(f[3]), 0 - self.conditions.append('ifnull({tname}.{fname}, {default_val}) {operator} {value}'.format( + conditions.append('ifnull({tname}.{fname}, {default_val}) {operator} {value}'.format( tname=tname, fname=f[1], default_val=default_val, operator=f[2], value=value)) @@ -203,7 +210,7 @@ class DatabaseQuery(object): """add match conditions if applicable""" self.match_filters = {} self.match_conditions = [] - self.or_conditions = [] + self.match_or_conditions = [] if not self.tables: self.extract_tables() @@ -214,7 +221,7 @@ class DatabaseQuery(object): restrictions = frappe.defaults.get_restrictions() if restricted_by_user: - self.or_conditions.append('`tab{doctype}`.`owner`="{user}"'.format(doctype=self.doctype, + self.match_or_conditions.append('`tab{doctype}`.`owner`="{user}"'.format(doctype=self.doctype, user=frappe.local.session.user)) self.match_filters["owner"] = frappe.session.user @@ -247,12 +254,12 @@ class DatabaseQuery(object): if doctype_conditions: conditions += ' and ' + doctype_conditions if conditions else doctype_conditions - if self.or_conditions: + if self.match_or_conditions: if conditions: conditions = '({conditions}) or {or_conditions}'.format(conditions=conditions, - or_conditions = ' or '.join(self.or_conditions)) + or_conditions = ' or '.join(self.match_or_conditions)) else: - conditions = " or ".join(self.or_conditions) + conditions = " or ".join(self.match_or_conditions) return conditions diff --git a/frappe/tests/test_db_query.py b/frappe/tests/test_db_query.py index 8aac135271..abdf219ec8 100644 --- a/frappe/tests/test_db_query.py +++ b/frappe/tests/test_db_query.py @@ -8,7 +8,7 @@ from frappe.model.db_query import DatabaseQuery class TestReportview(unittest.TestCase): def test_basic(self): self.assertTrue({"name":"DocType"} in DatabaseQuery("DocType").execute(limit_page_length=None)) - + def test_fields(self): self.assertTrue({"name":"DocType", "issingle":0} \ in DatabaseQuery("DocType").execute(fields=["name", "issingle"], limit_page_length=None)) @@ -16,7 +16,7 @@ class TestReportview(unittest.TestCase): def test_filters_1(self): self.assertFalse({"name":"DocType"} \ in DatabaseQuery("DocType").execute(filters=[["DocType", "name", "like", "J%"]])) - + def test_filters_2(self): self.assertFalse({"name":"DocType"} \ in DatabaseQuery("DocType").execute(filters=[{"name": ["like", "J%"]}])) @@ -28,4 +28,12 @@ class TestReportview(unittest.TestCase): def test_filters_4(self): self.assertTrue({"name":"DocField"} \ in DatabaseQuery("DocType").execute(filters={"name": "DocField"})) - \ No newline at end of file + + def test_or_filters(self): + data = DatabaseQuery("DocField").execute( + filters={"parent": "DocType"}, fields=["fieldname", "fieldtype"], + or_filters=[{"fieldtype":"Table"}, {"fieldtype":"Select"}]) + + self.assertTrue({"fieldtype":"Table", "fieldname":"fields"} in data) + self.assertTrue({"fieldtype":"Select", "fieldname":"document_type"} in data) + self.assertFalse({"fieldtype":"Check", "fieldname":"issingle"} in data) diff --git a/frappe/utils/sel.py b/frappe/utils/sel.py index 9783561569..1e61f058e6 100644 --- a/frappe/utils/sel.py +++ b/frappe/utils/sel.py @@ -152,7 +152,6 @@ def set_input(selector, text): def close(): global _driver, pipe - print "closing selenium" if _driver: _driver.quit() if pipe: diff --git a/frappe/widgets/reportview.py b/frappe/widgets/reportview.py index 79a1818f41..ad43f60545 100644 --- a/frappe/widgets/reportview.py +++ b/frappe/widgets/reportview.py @@ -13,10 +13,10 @@ from frappe import _ def get(): return compress(execute(**get_form_params())) -def execute(doctype, query=None, filters=None, fields=None, docstatus=None, +def execute(doctype, query=None, filters=None, fields=None, or_filters=None, docstatus=None, group_by=None, order_by=None, limit_start=0, limit_page_length=20, as_list=False, with_childnames=False, debug=False): - return DatabaseQuery(doctype).execute(query, filters, fields, docstatus, group_by, + return DatabaseQuery(doctype).execute(query, filters, fields, or_filters, docstatus, group_by, order_by, limit_start, limit_page_length, as_list, with_childnames, debug) def get_form_params(): diff --git a/frappe/widgets/search.py b/frappe/widgets/search.py index 9e67c67ae9..3a4200d7dd 100644 --- a/frappe/widgets/search.py +++ b/frappe/widgets/search.py @@ -56,10 +56,16 @@ def search_widget(doctype, txt, query=None, searchfield=None, start=0, if filters==None: filters = [] + or_filters = [] # build from doctype if txt: - filters.append([doctype, searchfield or "name", "like", txt + "%"]) + if meta.search_fields: + for f in meta.search_fields.split(","): + or_filters.append([doctype, f.strip(), "like", "%" + txt + "%"]) + else: + filters.append([doctype, searchfield or "name", "like", + "%" + txt + "%"]) if meta.get("fields", {"fieldname":"enabled", "fieldtype":"Check"}): filters.append([doctype, "enabled", "=", 1]) if meta.get("fields", {"fieldname":"disabled", "fieldtype":"Check"}): @@ -67,7 +73,8 @@ def search_widget(doctype, txt, query=None, searchfield=None, start=0, frappe.response["values"] = frappe.widgets.reportview.execute(doctype, filters=filters, fields = get_std_fields_list(meta, searchfield or "name"), - limit_start = start, limit_page_length=page_len, as_list=True) + or_filters = or_filters, limit_start = start, + limit_page_length=page_len, as_list=True, debug=1) def get_std_fields_list(meta, key): # get additional search fields