mirror of
https://github.com/frappe/erpnext.git
synced 2026-08-20 09:49:58 +00:00
Convert raw `frappe.db.sql` across the Projects module to `frappe.qb` / the ORM so the same code runs on MariaDB and Postgres. Behaviour is preserved on MariaDB; the conversions also make these paths valid under Postgres' stricter SQL (GROUP BY, case-sensitivity, empty-string handling). Conversions of note (behaviour kept identical to the MariaDB original): - project.get_users_for_project: search selects the stored full_name instead of concat_ws(first, middle, last) (concat_ws diverges on Postgres, where empty Data fields are NULL) and wraps Locate in LOWER() to keep MariaDB's case-insensitive result ordering. - project costing: percent-complete and sales/billed-amount aggregates rebuilt as Sum() query-builder selects. - task.reschedule_dependent_tasks: the correlated subquery is split into a `Task Depends On` parent-pluck + a Task lookup (same rows, no nested SQL). - timesheet.get_events: user-permission match conditions move to the query-builder form via get_event_conditions_qb; calendar columns rebuilt with Concat/Round. - report/project_wise_stock_tracking & report/daily_timesheet_summary: GROUP BY cost aggregates and the timesheet date window (timestamp(to_date,'24:00:00') -> end-of-day via get_combine_datetime) rebuilt to satisfy Postgres. - search helpers (query_task, get_project, get_timesheet) use frappe.qb.get_query with ignore_permissions=False in place of build_match_conditions/get_match_cond. Tests (run on both MariaDB and Postgres, --lightmode): - Existing project/task/timesheet/activity_cost suites kept green (27 tests). - New project_wise_stock_tracking test drives all three cost aggregates with positive data (purchased / issued / delivered GROUP BY) plus get_project_details. - New daily_timesheet_summary test covers the date-window join. Not included: project_update.py is deferred. Its daily_reminder()/email_sending() select `progress`/`progress_details`, columns that do not exist on the Project Update doctype, so the function errors when invoked regardless of backend - a pre-existing bug that needs an email-rework, not just a query port. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
30 lines
908 B
Python
30 lines
908 B
Python
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
|
# License: GNU General Public License v3. See license.txt
|
|
|
|
# For license information, please see license.txt
|
|
|
|
|
|
import frappe
|
|
from frappe.query_builder import Case
|
|
|
|
|
|
@frappe.whitelist()
|
|
@frappe.validate_and_sanitize_search_inputs
|
|
def query_task(doctype: str, txt: str, searchfield: str, start: int, page_len: int, filters: dict):
|
|
search_str = f"%{txt}%"
|
|
prefix_str = f"{txt}%"
|
|
|
|
Task = frappe.qb.DocType("Task")
|
|
query = frappe.qb.get_query("Task", fields=["name", "subject"], ignore_permissions=False)
|
|
|
|
return (
|
|
query.where(Task[searchfield].like(search_str) | Task.subject.like(search_str))
|
|
.orderby(Case().when(Task.subject.like(prefix_str), 0).else_(1))
|
|
.orderby(Case().when(Task[searchfield].like(prefix_str), 0).else_(1))
|
|
.orderby(Task[searchfield])
|
|
.orderby(Task.subject)
|
|
.limit(page_len)
|
|
.offset(start)
|
|
.run()
|
|
)
|