seitime-frappe/frappe/desk/treeview.py
Aarol D'Souza cf69e4bed1
fix(postgres): misc query building fixes + CI (#34831)
* fix(query): check standard field definitions

Signed-off-by: Akhil Narang <me@akhilnarang.dev>

* fix(postgres): fix order_by problem in pg

* fix(postgres): fix order_by in get_all for _test_connection_query

* fix: add check to a proper numeric fallback in _get_ifnull_fallback

* test(postgres): fix pg query used in assertion in test_permission_query

* fix(postgres): fix order_by in get_all for possible_link

* fix(postgres): fix order_by in get_all for set_modules

* fix(postgres): fix pg query count *

* fix(postgres): fix order_by in get_all for ask_pass_update

* fix(postgres): fix order_by statement in search_widget

* fix(postgres): fix order_by in get_list for get_stats

* test(postgres): normalize_sql for pg queries in test_arithmetic_operators_in_fields

* test(postgres): normalize_sql for pg queries in test_field_alias_in_group_by

* test(postgres): normalize_sql for pg queries in test_field_alias_permission_check

* test(postgres): fix order_by statement in get_all for test_db_keywords_as_fields

* test(postgres): fix order_by statement in get_all for test_prepare_select_args

* fix(treeview): use 0 instead of false to check since check field is an integer

* fix(postgres): fix order_by in get_all for sync_communication

* fix(postgres): fix order_by in get_all for get_references_across_doctypes_by_dynamic_link_field

* test(postgres): fix order_by in get_all for test_list_summary

* fix(postgres): fix order_by in get_all for email queries

* test(postgres): use order_by none and update assertion for postgres

* fix(postgres): use ILIKE to support case insensitive search in postgres

* test(test_query): update pg specific query assert to use ILIKE

* test(test_query): update test_nested_filters to use ilike instead for PG

* test(postgres): update pg query in assert to test updated qb query

* fix(search): update query to be db-agnostic

* test(postgres): normalize query for pg in test_build_match_conditions

* fix(postgres): suppress ORDER BY when SELECT DISTINCT in query for postgres specific behavior

* fix(postgres): suppress ORDER BY when GROUP BY is explicitly asked for pg specific behavior

* test(postgres): fix test behavior for pg ORDER BY drop when used with GROUP BY

* refactor: reducing noise in code by formatting code

* fix(query): use Star() to handle SQL wildcard character * correctly

* fix(postgres): display warning for ORDER BY fields that will be dropped

---------

Signed-off-by: Akhil Narang <me@akhilnarang.dev>
Co-authored-by: Akhil Narang <me@akhilnarang.dev>
2025-12-05 10:30:49 +05:30

89 lines
2.3 KiB
Python

# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: MIT. See LICENSE
import frappe
from frappe import _
from frappe.query_builder import Field, functions
@frappe.whitelist()
def get_all_nodes(doctype, label, parent, tree_method, **filters):
"""Recursively gets all data from tree nodes"""
filters.pop("cmd", None)
filters.pop("data", None)
tree_method = frappe.get_attr(tree_method)
frappe.is_whitelisted(tree_method)
data = tree_method(doctype, parent, **filters)
out = [dict(parent=label, data=data)]
filters.pop("is_root", None)
to_check = [d.get("value") for d in data if d.get("expandable")]
while to_check:
parent = to_check.pop()
data = tree_method(doctype, parent, is_root=False, **filters)
out.append(dict(parent=parent, data=data))
for d in data:
if d.get("expandable"):
to_check.append(d.get("value"))
return out
@frappe.whitelist()
def get_children(doctype, parent="", include_disabled=False, **filters):
if isinstance(include_disabled, str):
include_disabled = frappe.sbool(include_disabled)
return _get_children(doctype, parent, include_disabled=include_disabled)
def _get_children(doctype, parent="", ignore_permissions=False, include_disabled=False):
parent_field = "parent_" + frappe.scrub(doctype)
meta = frappe.get_meta(doctype)
qb = (
frappe.qb.from_(doctype)
.select(
Field("name").as_("value"),
Field(meta.get("title_field") or "name").as_("title"),
Field("is_group").as_("expandable"),
)
.where(functions.IfNull(Field(parent_field), "").eq(parent))
.where(Field("docstatus") < 2)
)
if frappe.db.has_column(doctype, "disabled") and not include_disabled:
# used 0 instead of `false` since type of check in postgres is smallint
qb = qb.where(Field("disabled").eq(0))
# Order by name and execute
return qb.orderby("name").run(as_dict=True)
@frappe.whitelist()
def add_node():
args = make_tree_args(**frappe.form_dict)
doc = frappe.get_doc(args)
doc.save()
def make_tree_args(**kwarg):
kwarg.pop("cmd", None)
doctype = kwarg["doctype"]
parent_field = "parent_" + frappe.scrub(doctype)
if kwarg["is_root"] == "false":
kwarg["is_root"] = False
if kwarg["is_root"] == "true":
kwarg["is_root"] = True
parent = kwarg.get("parent") or kwarg.get(parent_field)
if doctype != parent:
kwarg.update({parent_field: parent})
return frappe._dict(kwarg)