您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 
 

737 行
24 KiB

  1. # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
  2. # License: MIT. See LICENSE
  3. import datetime
  4. import unittest
  5. import frappe
  6. from frappe.core.page.permission_manager.permission_manager import add, reset, update
  7. from frappe.custom.doctype.property_setter.property_setter import make_property_setter
  8. from frappe.desk.reportview import get_filters_cond
  9. from frappe.handler import execute_cmd
  10. from frappe.model.db_query import DatabaseQuery
  11. from frappe.permissions import add_user_permission, clear_user_permissions_for_doctype
  12. from frappe.query_builder import Column
  13. from frappe.utils.testutils import add_custom_field, clear_custom_fields
  14. test_dependencies = ["User", "Blog Post", "Blog Category", "Blogger"]
  15. class TestReportview(unittest.TestCase):
  16. def setUp(self):
  17. frappe.set_user("Administrator")
  18. def test_basic(self):
  19. self.assertTrue({"name": "DocType"} in DatabaseQuery("DocType").execute(limit_page_length=None))
  20. def test_extract_tables(self):
  21. db_query = DatabaseQuery("DocType")
  22. add_custom_field("DocType", "test_tab_field", "Data")
  23. db_query.fields = ["tabNote.creation", "test_tab_field", "tabDocType.test_tab_field"]
  24. db_query.extract_tables()
  25. self.assertIn("`tabNote`", db_query.tables)
  26. self.assertIn("`tabDocType`", db_query.tables)
  27. self.assertNotIn("test_tab_field", db_query.tables)
  28. clear_custom_fields("DocType")
  29. def test_build_match_conditions(self):
  30. clear_user_permissions_for_doctype("Blog Post", "test2@example.com")
  31. test2user = frappe.get_doc("User", "test2@example.com")
  32. test2user.add_roles("Blogger")
  33. frappe.set_user("test2@example.com")
  34. # this will get match conditions for Blog Post
  35. build_match_conditions = DatabaseQuery("Blog Post").build_match_conditions
  36. # Before any user permission is applied
  37. # get as filters
  38. self.assertEqual(build_match_conditions(as_condition=False), [])
  39. # get as conditions
  40. self.assertEqual(build_match_conditions(as_condition=True), "")
  41. add_user_permission("Blog Post", "-test-blog-post", "test2@example.com", True)
  42. add_user_permission("Blog Post", "-test-blog-post-1", "test2@example.com", True)
  43. # After applying user permission
  44. # get as filters
  45. self.assertTrue(
  46. {"Blog Post": ["-test-blog-post-1", "-test-blog-post"]}
  47. in build_match_conditions(as_condition=False)
  48. )
  49. # get as conditions
  50. self.assertEqual(
  51. build_match_conditions(as_condition=True),
  52. """(((ifnull(`tabBlog Post`.`name`, '')='' or `tabBlog Post`.`name` in ('-test-blog-post-1', '-test-blog-post'))))""",
  53. )
  54. frappe.set_user("Administrator")
  55. def test_fields(self):
  56. self.assertTrue(
  57. {"name": "DocType", "issingle": 0}
  58. in DatabaseQuery("DocType").execute(fields=["name", "issingle"], limit_page_length=None)
  59. )
  60. def test_filters_1(self):
  61. self.assertFalse(
  62. {"name": "DocType"}
  63. in DatabaseQuery("DocType").execute(filters=[["DocType", "name", "like", "J%"]])
  64. )
  65. def test_filters_2(self):
  66. self.assertFalse(
  67. {"name": "DocType"} in DatabaseQuery("DocType").execute(filters=[{"name": ["like", "J%"]}])
  68. )
  69. def test_filters_3(self):
  70. self.assertFalse(
  71. {"name": "DocType"} in DatabaseQuery("DocType").execute(filters={"name": ["like", "J%"]})
  72. )
  73. def test_filters_4(self):
  74. self.assertTrue(
  75. {"name": "DocField"} in DatabaseQuery("DocType").execute(filters={"name": "DocField"})
  76. )
  77. def test_in_not_in_filters(self):
  78. self.assertFalse(DatabaseQuery("DocType").execute(filters={"name": ["in", None]}))
  79. self.assertTrue(
  80. {"name": "DocType"} in DatabaseQuery("DocType").execute(filters={"name": ["not in", None]})
  81. )
  82. for result in [{"name": "DocType"}, {"name": "DocField"}]:
  83. self.assertTrue(
  84. result in DatabaseQuery("DocType").execute(filters={"name": ["in", "DocType,DocField"]})
  85. )
  86. for result in [{"name": "DocType"}, {"name": "DocField"}]:
  87. self.assertFalse(
  88. result in DatabaseQuery("DocType").execute(filters={"name": ["not in", "DocType,DocField"]})
  89. )
  90. def test_none_filter(self):
  91. query = frappe.db.query.get_sql("DocType", fields="name", filters={"restrict_to_domain": None})
  92. sql = str(query).replace("`", "").replace('"', "")
  93. condition = "restrict_to_domain IS NULL"
  94. self.assertIn(condition, sql)
  95. def test_or_filters(self):
  96. data = DatabaseQuery("DocField").execute(
  97. filters={"parent": "DocType"},
  98. fields=["fieldname", "fieldtype"],
  99. or_filters=[{"fieldtype": "Table"}, {"fieldtype": "Select"}],
  100. )
  101. self.assertTrue({"fieldtype": "Table", "fieldname": "fields"} in data)
  102. self.assertTrue({"fieldtype": "Select", "fieldname": "document_type"} in data)
  103. self.assertFalse({"fieldtype": "Check", "fieldname": "issingle"} in data)
  104. def test_between_filters(self):
  105. """test case to check between filter for date fields"""
  106. frappe.db.delete("Event")
  107. # create events to test the between operator filter
  108. todays_event = create_event()
  109. event1 = create_event(starts_on="2016-07-05 23:59:59")
  110. event2 = create_event(starts_on="2016-07-06 00:00:00")
  111. event3 = create_event(starts_on="2016-07-07 23:59:59")
  112. event4 = create_event(starts_on="2016-07-08 00:00:01")
  113. # if the values are not passed in filters then event should be filter as current datetime
  114. data = DatabaseQuery("Event").execute(filters={"starts_on": ["between", None]}, fields=["name"])
  115. self.assertTrue({"name": event1.name} not in data)
  116. # if both from and to_date values are passed
  117. data = DatabaseQuery("Event").execute(
  118. filters={"starts_on": ["between", ["2016-07-06", "2016-07-07"]]}, fields=["name"]
  119. )
  120. self.assertTrue({"name": event2.name} in data)
  121. self.assertTrue({"name": event3.name} in data)
  122. self.assertTrue({"name": event1.name} not in data)
  123. self.assertTrue({"name": event4.name} not in data)
  124. # if only one value is passed in the filter
  125. data = DatabaseQuery("Event").execute(
  126. filters={"starts_on": ["between", ["2016-07-07"]]}, fields=["name"]
  127. )
  128. self.assertTrue({"name": event3.name} in data)
  129. self.assertTrue({"name": event4.name} in data)
  130. self.assertTrue({"name": todays_event.name} in data)
  131. self.assertTrue({"name": event1.name} not in data)
  132. self.assertTrue({"name": event2.name} not in data)
  133. # test between is formatted for creation column
  134. data = DatabaseQuery("Event").execute(
  135. filters={"creation": ["between", ["2016-07-06", "2016-07-07"]]}, fields=["name"]
  136. )
  137. def test_ignore_permissions_for_get_filters_cond(self):
  138. frappe.set_user("test2@example.com")
  139. self.assertRaises(frappe.PermissionError, get_filters_cond, "DocType", dict(istable=1), [])
  140. self.assertTrue(get_filters_cond("DocType", dict(istable=1), [], ignore_permissions=True))
  141. frappe.set_user("Administrator")
  142. def test_query_fields_sanitizer(self):
  143. self.assertRaises(
  144. frappe.DataError,
  145. DatabaseQuery("DocType").execute,
  146. fields=["name", "issingle, version()"],
  147. limit_start=0,
  148. limit_page_length=1,
  149. )
  150. self.assertRaises(
  151. frappe.DataError,
  152. DatabaseQuery("DocType").execute,
  153. fields=["name", "issingle, IF(issingle=1, (select name from tabUser), count(name))"],
  154. limit_start=0,
  155. limit_page_length=1,
  156. )
  157. self.assertRaises(
  158. frappe.DataError,
  159. DatabaseQuery("DocType").execute,
  160. fields=["name", "issingle, (select count(*) from tabSessions)"],
  161. limit_start=0,
  162. limit_page_length=1,
  163. )
  164. self.assertRaises(
  165. frappe.DataError,
  166. DatabaseQuery("DocType").execute,
  167. fields=["name", "issingle, SELECT LOCATE('', `tabUser`.`user`) AS user;"],
  168. limit_start=0,
  169. limit_page_length=1,
  170. )
  171. self.assertRaises(
  172. frappe.DataError,
  173. DatabaseQuery("DocType").execute,
  174. fields=["name", "issingle, IF(issingle=1, (SELECT name from tabUser), count(*))"],
  175. limit_start=0,
  176. limit_page_length=1,
  177. )
  178. self.assertRaises(
  179. frappe.DataError,
  180. DatabaseQuery("DocType").execute,
  181. fields=["name", "issingle ''"],
  182. limit_start=0,
  183. limit_page_length=1,
  184. )
  185. self.assertRaises(
  186. frappe.DataError,
  187. DatabaseQuery("DocType").execute,
  188. fields=["name", "issingle,'"],
  189. limit_start=0,
  190. limit_page_length=1,
  191. )
  192. self.assertRaises(
  193. frappe.DataError,
  194. DatabaseQuery("DocType").execute,
  195. fields=["name", "select * from tabSessions"],
  196. limit_start=0,
  197. limit_page_length=1,
  198. )
  199. self.assertRaises(
  200. frappe.DataError,
  201. DatabaseQuery("DocType").execute,
  202. fields=["name", "issingle from --"],
  203. limit_start=0,
  204. limit_page_length=1,
  205. )
  206. self.assertRaises(
  207. frappe.DataError,
  208. DatabaseQuery("DocType").execute,
  209. fields=["name", "issingle from tabDocType order by 2 --"],
  210. limit_start=0,
  211. limit_page_length=1,
  212. )
  213. self.assertRaises(
  214. frappe.DataError,
  215. DatabaseQuery("DocType").execute,
  216. fields=["name", "1' UNION SELECT * FROM __Auth --"],
  217. limit_start=0,
  218. limit_page_length=1,
  219. )
  220. self.assertRaises(
  221. frappe.DataError,
  222. DatabaseQuery("DocType").execute,
  223. fields=["@@version"],
  224. limit_start=0,
  225. limit_page_length=1,
  226. )
  227. data = DatabaseQuery("DocType").execute(
  228. fields=["count(`name`) as count"], limit_start=0, limit_page_length=1
  229. )
  230. self.assertTrue("count" in data[0])
  231. data = DatabaseQuery("DocType").execute(
  232. fields=["name", "issingle", "locate('', name) as _relevance"],
  233. limit_start=0,
  234. limit_page_length=1,
  235. )
  236. self.assertTrue("_relevance" in data[0])
  237. data = DatabaseQuery("DocType").execute(
  238. fields=["name", "issingle", "date(creation) as creation"], limit_start=0, limit_page_length=1
  239. )
  240. self.assertTrue("creation" in data[0])
  241. if frappe.db.db_type != "postgres":
  242. # datediff function does not exist in postgres
  243. data = DatabaseQuery("DocType").execute(
  244. fields=["name", "issingle", "datediff(modified, creation) as date_diff"],
  245. limit_start=0,
  246. limit_page_length=1,
  247. )
  248. self.assertTrue("date_diff" in data[0])
  249. def test_nested_permission(self):
  250. frappe.set_user("Administrator")
  251. create_nested_doctype()
  252. create_nested_doctype_records()
  253. clear_user_permissions_for_doctype("Nested DocType")
  254. # user permission for only one root folder
  255. add_user_permission("Nested DocType", "Level 1 A", "test2@example.com")
  256. from frappe.core.page.permission_manager.permission_manager import update
  257. # to avoid if_owner filter
  258. update("Nested DocType", "All", 0, "if_owner", 0)
  259. frappe.set_user("test2@example.com")
  260. data = DatabaseQuery("Nested DocType").execute()
  261. # children of root folder (for which we added user permission) should be accessible
  262. self.assertTrue({"name": "Level 2 A"} in data)
  263. self.assertTrue({"name": "Level 2 A"} in data)
  264. # other folders should not be accessible
  265. self.assertFalse({"name": "Level 1 B"} in data)
  266. self.assertFalse({"name": "Level 2 B"} in data)
  267. update("Nested DocType", "All", 0, "if_owner", 1)
  268. frappe.set_user("Administrator")
  269. def test_filter_sanitizer(self):
  270. self.assertRaises(
  271. frappe.DataError,
  272. DatabaseQuery("DocType").execute,
  273. fields=["name"],
  274. filters={"istable,": 1},
  275. limit_start=0,
  276. limit_page_length=1,
  277. )
  278. self.assertRaises(
  279. frappe.DataError,
  280. DatabaseQuery("DocType").execute,
  281. fields=["name"],
  282. filters={"editable_grid,": 1},
  283. or_filters={"istable,": 1},
  284. limit_start=0,
  285. limit_page_length=1,
  286. )
  287. self.assertRaises(
  288. frappe.DataError,
  289. DatabaseQuery("DocType").execute,
  290. fields=["name"],
  291. filters={"editable_grid,": 1},
  292. or_filters=[["DocType", "istable,", "=", 1]],
  293. limit_start=0,
  294. limit_page_length=1,
  295. )
  296. self.assertRaises(
  297. frappe.DataError,
  298. DatabaseQuery("DocType").execute,
  299. fields=["name"],
  300. filters={"editable_grid,": 1},
  301. or_filters=[["DocType", "istable", "=", 1], ["DocType", "beta and 1=1", "=", 0]],
  302. limit_start=0,
  303. limit_page_length=1,
  304. )
  305. out = DatabaseQuery("DocType").execute(
  306. fields=["name"],
  307. filters={"editable_grid": 1, "module": "Core"},
  308. or_filters=[["DocType", "istable", "=", 1]],
  309. order_by="creation",
  310. )
  311. self.assertTrue("DocField" in [d["name"] for d in out])
  312. out = DatabaseQuery("DocType").execute(
  313. fields=["name"],
  314. filters={"issingle": 1},
  315. or_filters=[["DocType", "module", "=", "Core"]],
  316. order_by="creation",
  317. )
  318. self.assertTrue("Role Permission for Page and Report" in [d["name"] for d in out])
  319. out = DatabaseQuery("DocType").execute(
  320. fields=["name"], filters={"track_changes": 1, "module": "Core"}, order_by="creation"
  321. )
  322. self.assertTrue("File" in [d["name"] for d in out])
  323. out = DatabaseQuery("DocType").execute(
  324. fields=["name"],
  325. filters=[["DocType", "ifnull(track_changes, 0)", "=", 0], ["DocType", "module", "=", "Core"]],
  326. order_by="creation",
  327. )
  328. self.assertTrue("DefaultValue" in [d["name"] for d in out])
  329. def test_of_not_of_descendant_ancestors(self):
  330. frappe.set_user("Administrator")
  331. clear_user_permissions_for_doctype("Nested DocType")
  332. # in descendants filter
  333. data = frappe.get_all("Nested DocType", {"name": ("descendants of", "Level 2 A")})
  334. self.assertTrue({"name": "Level 3 A"} in data)
  335. data = frappe.get_all("Nested DocType", {"name": ("descendants of", "Level 1 A")})
  336. self.assertTrue({"name": "Level 3 A"} in data)
  337. self.assertTrue({"name": "Level 2 A"} in data)
  338. self.assertFalse({"name": "Level 2 B"} in data)
  339. self.assertFalse({"name": "Level 1 B"} in data)
  340. self.assertFalse({"name": "Level 1 A"} in data)
  341. self.assertFalse({"name": "Root"} in data)
  342. # in ancestors of filter
  343. data = frappe.get_all("Nested DocType", {"name": ("ancestors of", "Level 2 A")})
  344. self.assertFalse({"name": "Level 3 A"} in data)
  345. self.assertFalse({"name": "Level 2 A"} in data)
  346. self.assertFalse({"name": "Level 2 B"} in data)
  347. self.assertFalse({"name": "Level 1 B"} in data)
  348. self.assertTrue({"name": "Level 1 A"} in data)
  349. self.assertTrue({"name": "Root"} in data)
  350. data = frappe.get_all("Nested DocType", {"name": ("ancestors of", "Level 1 A")})
  351. self.assertFalse({"name": "Level 3 A"} in data)
  352. self.assertFalse({"name": "Level 2 A"} in data)
  353. self.assertFalse({"name": "Level 2 B"} in data)
  354. self.assertFalse({"name": "Level 1 B"} in data)
  355. self.assertFalse({"name": "Level 1 A"} in data)
  356. self.assertTrue({"name": "Root"} in data)
  357. # not descendants filter
  358. data = frappe.get_all("Nested DocType", {"name": ("not descendants of", "Level 2 A")})
  359. self.assertFalse({"name": "Level 3 A"} in data)
  360. self.assertTrue({"name": "Level 2 A"} in data)
  361. self.assertTrue({"name": "Level 2 B"} in data)
  362. self.assertTrue({"name": "Level 1 A"} in data)
  363. self.assertTrue({"name": "Root"} in data)
  364. data = frappe.get_all("Nested DocType", {"name": ("not descendants of", "Level 1 A")})
  365. self.assertFalse({"name": "Level 3 A"} in data)
  366. self.assertFalse({"name": "Level 2 A"} in data)
  367. self.assertTrue({"name": "Level 2 B"} in data)
  368. self.assertTrue({"name": "Level 1 B"} in data)
  369. self.assertTrue({"name": "Level 1 A"} in data)
  370. self.assertTrue({"name": "Root"} in data)
  371. # not ancestors of filter
  372. data = frappe.get_all("Nested DocType", {"name": ("not ancestors of", "Level 2 A")})
  373. self.assertTrue({"name": "Level 3 A"} in data)
  374. self.assertTrue({"name": "Level 2 A"} in data)
  375. self.assertTrue({"name": "Level 2 B"} in data)
  376. self.assertTrue({"name": "Level 1 B"} in data)
  377. self.assertTrue({"name": "Level 1 A"} not in data)
  378. self.assertTrue({"name": "Root"} not in data)
  379. data = frappe.get_all("Nested DocType", {"name": ("not ancestors of", "Level 1 A")})
  380. self.assertTrue({"name": "Level 3 A"} in data)
  381. self.assertTrue({"name": "Level 2 A"} in data)
  382. self.assertTrue({"name": "Level 2 B"} in data)
  383. self.assertTrue({"name": "Level 1 B"} in data)
  384. self.assertTrue({"name": "Level 1 A"} in data)
  385. self.assertFalse({"name": "Root"} in data)
  386. data = frappe.get_all("Nested DocType", {"name": ("ancestors of", "Root")})
  387. self.assertTrue(len(data) == 0)
  388. self.assertTrue(
  389. len(frappe.get_all("Nested DocType", {"name": ("not ancestors of", "Root")}))
  390. == len(frappe.get_all("Nested DocType"))
  391. )
  392. def test_is_set_is_not_set(self):
  393. res = DatabaseQuery("DocType").execute(filters={"autoname": ["is", "not set"]})
  394. self.assertTrue({"name": "Integration Request"} in res)
  395. self.assertTrue({"name": "User"} in res)
  396. self.assertFalse({"name": "Blogger"} in res)
  397. res = DatabaseQuery("DocType").execute(filters={"autoname": ["is", "set"]})
  398. self.assertTrue({"name": "DocField"} in res)
  399. self.assertTrue({"name": "Prepared Report"} in res)
  400. self.assertFalse({"name": "Property Setter"} in res)
  401. def test_set_field_tables(self):
  402. # Tests _in_standard_sql_methods method in test_set_field_tables
  403. # The following query will break if the above method is broken
  404. data = frappe.db.get_list(
  405. "Web Form",
  406. filters=[["Web Form Field", "reqd", "=", 1]],
  407. group_by="amount_field",
  408. fields=["count(*) as count", "`amount_field` as name"],
  409. order_by="count desc",
  410. limit=50,
  411. )
  412. def test_pluck_name(self):
  413. names = DatabaseQuery("DocType").execute(filters={"name": "DocType"}, pluck="name")
  414. self.assertEqual(names, ["DocType"])
  415. def test_pluck_any_field(self):
  416. owners = DatabaseQuery("DocType").execute(filters={"name": "DocType"}, pluck="owner")
  417. self.assertEqual(owners, ["Administrator"])
  418. def test_prepare_select_args(self):
  419. # frappe.get_all inserts modified field into order_by clause
  420. # test to make sure this is inserted into select field when postgres
  421. doctypes = frappe.get_all(
  422. "DocType",
  423. filters={"docstatus": 0, "document_type": ("!=", "")},
  424. group_by="document_type",
  425. fields=["document_type", "sum(is_submittable) as is_submittable"],
  426. limit=1,
  427. as_list=True,
  428. )
  429. if frappe.conf.db_type == "mariadb":
  430. self.assertTrue(len(doctypes[0]) == 2)
  431. else:
  432. self.assertTrue(len(doctypes[0]) == 3)
  433. self.assertTrue(isinstance(doctypes[0][2], datetime.datetime))
  434. def test_column_comparison(self):
  435. """Test DatabaseQuery.execute to test column comparison"""
  436. users_unedited = frappe.get_all(
  437. "User",
  438. filters={"creation": Column("modified")},
  439. fields=["name", "creation", "modified"],
  440. limit=1,
  441. )
  442. users_edited = frappe.get_all(
  443. "User",
  444. filters={"creation": ("!=", Column("modified"))},
  445. fields=["name", "creation", "modified"],
  446. limit=1,
  447. )
  448. self.assertEqual(users_unedited[0].modified, users_unedited[0].creation)
  449. self.assertNotEqual(users_edited[0].modified, users_edited[0].creation)
  450. def test_reportview_get(self):
  451. user = frappe.get_doc("User", "test@example.com")
  452. add_child_table_to_blog_post()
  453. user_roles = frappe.get_roles()
  454. user.remove_roles(*user_roles)
  455. user.add_roles("Blogger")
  456. make_property_setter("Blog Post", "published", "permlevel", 1, "Int")
  457. reset("Blog Post")
  458. add("Blog Post", "Website Manager", 1)
  459. update("Blog Post", "Website Manager", 1, "write", 1)
  460. frappe.set_user(user.name)
  461. frappe.local.request = frappe._dict()
  462. frappe.local.request.method = "POST"
  463. frappe.local.form_dict = frappe._dict(
  464. {
  465. "doctype": "Blog Post",
  466. "fields": ["published", "title", "`tabTest Child`.`test_field`"],
  467. }
  468. )
  469. # even if * is passed, fields which are not accessible should be filtered out
  470. response = execute_cmd("frappe.desk.reportview.get")
  471. self.assertListEqual(response["keys"], ["title"])
  472. frappe.local.form_dict = frappe._dict(
  473. {
  474. "doctype": "Blog Post",
  475. "fields": ["*"],
  476. }
  477. )
  478. response = execute_cmd("frappe.desk.reportview.get")
  479. self.assertNotIn("published", response["keys"])
  480. frappe.set_user("Administrator")
  481. user.add_roles("Website Manager")
  482. frappe.set_user(user.name)
  483. frappe.set_user("Administrator")
  484. # Admin should be able to see access all fields
  485. frappe.local.form_dict = frappe._dict(
  486. {
  487. "doctype": "Blog Post",
  488. "fields": ["published", "title", "`tabTest Child`.`test_field`"],
  489. }
  490. )
  491. response = execute_cmd("frappe.desk.reportview.get")
  492. self.assertListEqual(response["keys"], ["published", "title", "test_field"])
  493. # reset user roles
  494. user.remove_roles("Blogger", "Website Manager")
  495. user.add_roles(*user_roles)
  496. def test_reportview_get_aggregation(self):
  497. # test aggregation based on child table field
  498. frappe.local.form_dict = frappe._dict(
  499. {
  500. "doctype": "DocType",
  501. "fields": """["`tabDocField`.`label` as field_label","`tabDocField`.`name` as field_name"]""",
  502. "filters": "[]",
  503. "order_by": "_aggregate_column desc",
  504. "start": 0,
  505. "page_length": 20,
  506. "view": "Report",
  507. "with_comment_count": 0,
  508. "group_by": "field_label, field_name",
  509. "aggregate_on_field": "columns",
  510. "aggregate_on_doctype": "DocField",
  511. "aggregate_function": "sum",
  512. }
  513. )
  514. response = execute_cmd("frappe.desk.reportview.get")
  515. self.assertListEqual(
  516. response["keys"], ["field_label", "field_name", "_aggregate_column", "columns"]
  517. )
  518. def test_cast_name(self):
  519. from frappe.core.doctype.doctype.test_doctype import new_doctype
  520. dt = new_doctype("autoinc_dt_test", autoname="autoincrement").insert(ignore_permissions=True)
  521. query = DatabaseQuery("autoinc_dt_test").execute(
  522. fields=["locate('1', `tabautoinc_dt_test`.`name`)", "`tabautoinc_dt_test`.`name`"],
  523. filters={"name": 1},
  524. run=False,
  525. )
  526. if frappe.db.db_type == "postgres":
  527. self.assertTrue('strpos( cast( "tabautoinc_dt_test"."name" as varchar), \'1\')' in query)
  528. self.assertTrue('where cast("tabautoinc_dt_test"."name" as varchar) = \'1\'' in query)
  529. else:
  530. self.assertTrue("locate('1', `tabautoinc_dt_test`.`name`)" in query)
  531. self.assertTrue("where `tabautoinc_dt_test`.`name` = 1" in query)
  532. dt.delete(ignore_permissions=True)
  533. def test_fieldname_starting_with_int(self):
  534. from frappe.core.doctype.doctype.test_doctype import new_doctype
  535. dt = new_doctype(
  536. "dt_with_int_named_fieldname",
  537. fields=[{"label": "1field", "fieldname": "1field", "fieldtype": "Int"}],
  538. ).insert(ignore_permissions=True)
  539. frappe.get_doc({"doctype": "dt_with_int_named_fieldname", "1field": 10}).insert(
  540. ignore_permissions=True
  541. )
  542. query = DatabaseQuery("dt_with_int_named_fieldname")
  543. self.assertTrue(query.execute(filters={"1field": 10}))
  544. self.assertTrue(query.execute(filters={"1field": ["like", "1%"]}))
  545. self.assertTrue(query.execute(filters={"1field": ["in", "1,2,10"]}))
  546. self.assertTrue(query.execute(filters={"1field": ["is", "set"]}))
  547. self.assertFalse(query.execute(filters={"1field": ["not like", "1%"]}))
  548. dt.delete()
  549. def add_child_table_to_blog_post():
  550. child_table = frappe.get_doc(
  551. {
  552. "doctype": "DocType",
  553. "istable": 1,
  554. "custom": 1,
  555. "name": "Test Child",
  556. "module": "Custom",
  557. "autoname": "Prompt",
  558. "fields": [{"fieldname": "test_field", "fieldtype": "Data", "permlevel": 1}],
  559. }
  560. )
  561. child_table.insert(ignore_permissions=True, ignore_if_duplicate=True)
  562. clear_custom_fields("Blog Post")
  563. add_custom_field("Blog Post", "child_table", "Table", child_table.name)
  564. def create_event(subject="_Test Event", starts_on=None):
  565. """create a test event"""
  566. from frappe.utils import get_datetime
  567. event = frappe.get_doc(
  568. {
  569. "doctype": "Event",
  570. "subject": subject,
  571. "event_type": "Public",
  572. "starts_on": get_datetime(starts_on),
  573. }
  574. ).insert(ignore_permissions=True)
  575. return event
  576. def create_nested_doctype():
  577. if frappe.db.exists("DocType", "Nested DocType"):
  578. return
  579. frappe.get_doc(
  580. {
  581. "doctype": "DocType",
  582. "name": "Nested DocType",
  583. "module": "Custom",
  584. "is_tree": 1,
  585. "custom": 1,
  586. "autoname": "Prompt",
  587. "fields": [{"label": "Description", "fieldname": "description"}],
  588. "permissions": [{"role": "Blogger"}],
  589. }
  590. ).insert()
  591. def create_nested_doctype_records():
  592. """
  593. Create a structure like:
  594. - Root
  595. - Level 1 A
  596. - Level 2 A
  597. - Level 3 A
  598. - Level 1 B
  599. - Level 2 B
  600. """
  601. records = [
  602. {"name": "Root", "is_group": 1},
  603. {"name": "Level 1 A", "parent_nested_doctype": "Root", "is_group": 1},
  604. {"name": "Level 2 A", "parent_nested_doctype": "Level 1 A", "is_group": 1},
  605. {"name": "Level 3 A", "parent_nested_doctype": "Level 2 A"},
  606. {"name": "Level 1 B", "parent_nested_doctype": "Root", "is_group": 1},
  607. {"name": "Level 2 B", "parent_nested_doctype": "Level 1 B"},
  608. ]
  609. for r in records:
  610. d = frappe.new_doc("Nested DocType")
  611. d.update(r)
  612. d.insert(ignore_permissions=True, ignore_if_duplicate=True)