refactor(tasks-controller): enhance SQL query structure and improve task filtering

- Updated SQL queries in TasksControllerV2 to use table aliases for clarity and consistency.
- Improved filtering logic for project IDs and assignees to ensure accurate task retrieval.
- Refactored JSON object construction in SQL queries for better readability and maintainability.
- Adjusted parameter handling in query execution to streamline data retrieval processes.
This commit is contained in:
chamikaJ
2025-07-07 14:10:04 +05:30
parent 0b96d59285
commit 3887cc477d

View File

@@ -69,13 +69,13 @@ export default class TasksControllerV2 extends TasksControllerBase {
} }
private static getFilterByProjectsWhereClosure(text: string) { private static getFilterByProjectsWhereClosure(text: string) {
return text ? `project_id IN (${this.flatString(text)})` : ""; return text ? `t.project_id IN (${this.flatString(text)})` : "";
} }
private static getFilterByAssignee(filterBy: string) { private static getFilterByAssignee(filterBy: string) {
return filterBy === "member" return filterBy === "member"
? `id IN (SELECT task_id FROM tasks_assignees WHERE team_member_id = $1)` ? `t.id IN (SELECT task_id FROM tasks_assignees WHERE team_member_id = $1)`
: "project_id = $1"; : "t.project_id = $1";
} }
private static getStatusesQuery(filterBy: string) { private static getStatusesQuery(filterBy: string) {
@@ -136,14 +136,14 @@ export default class TasksControllerV2 extends TasksControllerBase {
? `, COALESCE(cc_data.custom_column_values, '{}'::JSONB) AS custom_column_values` ? `, COALESCE(cc_data.custom_column_values, '{}'::JSONB) AS custom_column_values`
: ""; : "";
const archivedFilter = options.archived === "true" ? "archived IS TRUE" : "archived IS FALSE"; const archivedFilter = options.archived === "true" ? "t.archived IS TRUE" : "t.archived IS FALSE";
let subTasksFilter; let subTasksFilter;
if (options.isSubtasksInclude === "true") { if (options.isSubtasksInclude === "true") {
subTasksFilter = ""; subTasksFilter = "";
} else { } else {
subTasksFilter = isSubTasks ? "parent_task_id = $2" : "parent_task_id IS NULL"; subTasksFilter = isSubTasks ? "t.parent_task_id = $2" : "t.parent_task_id IS NULL";
} }
const filters = [ const filters = [
@@ -186,18 +186,18 @@ export default class TasksControllerV2 extends TasksControllerBase {
SELECT SELECT
ta.task_id, ta.task_id,
JSON_AGG(JSON_BUILD_OBJECT( JSON_AGG(JSON_BUILD_OBJECT(
"team_member_id", ta.team_member_id, 'team_member_id', ta.team_member_id,
"project_member_id", ta.project_member_id, 'project_member_id', ta.project_member_id,
"name", COALESCE(tmiv.name, ""), 'name', COALESCE(tmiv.name, ''),
"avatar_url", COALESCE(tmiv.avatar_url, ""), 'avatar_url', COALESCE(tmiv.avatar_url, ''),
"email", COALESCE(tmiv.email, ""), 'email', COALESCE(tmiv.email, ''),
"user_id", tmiv.user_id, 'user_id', tmiv.user_id,
"socket_id", COALESCE(u.socket_id, ""), 'socket_id', COALESCE(u.socket_id, ''),
"team_id", tmiv.team_id, 'team_id', tmiv.team_id,
"email_notifications_enabled", COALESCE(ns.email_notifications_enabled, false) 'email_notifications_enabled', COALESCE(ns.email_notifications_enabled, false)
)) AS assignees, )) AS assignees,
STRING_AGG(COALESCE(tmiv.name, \"\"), \", \") AS assignee_names, STRING_AGG(COALESCE(tmiv.name, ''), ', ') AS assignee_names,
STRING_AGG(COALESCE(tmiv.name, \"\"), \", \") AS names STRING_AGG(COALESCE(tmiv.name, ''), ', ') AS names
FROM tasks_assignees ta FROM tasks_assignees ta
LEFT JOIN team_member_info_view tmiv ON ta.team_member_id = tmiv.team_member_id LEFT JOIN team_member_info_view tmiv ON ta.team_member_id = tmiv.team_member_id
LEFT JOIN users u ON tmiv.user_id = u.id LEFT JOIN users u ON tmiv.user_id = u.id
@@ -208,16 +208,16 @@ export default class TasksControllerV2 extends TasksControllerBase {
SELECT SELECT
tl.task_id, tl.task_id,
JSON_AGG(JSON_BUILD_OBJECT( JSON_AGG(JSON_BUILD_OBJECT(
"id", tl.label_id, 'id', tl.label_id,
"label_id", tl.label_id, 'label_id', tl.label_id,
"name", team_l.name, 'name', team_l.name,
"color_code", team_l.color_code 'color_code', team_l.color_code
)) AS labels, )) AS labels,
JSON_AGG(JSON_BUILD_OBJECT( JSON_AGG(JSON_BUILD_OBJECT(
"id", tl.label_id, 'id', tl.label_id,
"label_id", tl.label_id, 'label_id', tl.label_id,
"name", team_l.name, 'name', team_l.name,
"color_code", team_l.color_code 'color_code', team_l.color_code
)) AS all_labels )) AS all_labels
FROM task_labels tl FROM task_labels tl
JOIN team_labels team_l ON tl.label_id = team_l.id JOIN team_labels team_l ON tl.label_id = team_l.id
@@ -241,7 +241,7 @@ export default class TasksControllerV2 extends TasksControllerBase {
FROM cc_column_values ccv FROM cc_column_values ccv
JOIN cc_custom_columns cc ON ccv.column_id = cc.id JOIN cc_custom_columns cc ON ccv.column_id = cc.id
GROUP BY ccv.task_id GROUP BY ccv.task_id
)` : ""} )` : ""}
SELECT SELECT
t.id, t.id,
t.name, t.name,
@@ -270,11 +270,11 @@ export default class TasksControllerV2 extends TasksControllerBase {
-- Status information via JOINs -- Status information via JOINs
stsc.color_code AS status_color, stsc.color_code AS status_color,
stsc.color_code_dark AS status_color_dark, stsc.color_code_dark AS status_color_dark,
JSON_BUILD_OBJECT( JSON_BUILD_OBJECT(
"is_done", stsc.is_done, 'is_done', stsc.is_done,
"is_doing", stsc.is_doing, 'is_doing', stsc.is_doing,
"is_todo", stsc.is_todo 'is_todo', stsc.is_todo
) AS status_category, ) AS status_category,
-- Aggregated counts -- Aggregated counts
COALESCE(agg.sub_tasks_count, 0) AS sub_tasks_count, COALESCE(agg.sub_tasks_count, 0) AS sub_tasks_count,
COALESCE(agg.completed_sub_tasks, 0) AS completed_sub_tasks, COALESCE(agg.completed_sub_tasks, 0) AS completed_sub_tasks,
@@ -286,11 +286,11 @@ export default class TasksControllerV2 extends TasksControllerBase {
-- Task completion status -- Task completion status
CASE WHEN stsc.is_done THEN 1 ELSE 0 END AS parent_task_completed, CASE WHEN stsc.is_done THEN 1 ELSE 0 END AS parent_task_completed,
-- Assignees and labels via JOINs -- Assignees and labels via JOINs
COALESCE(assignees.assignees, "[]"::JSON) AS assignees, COALESCE(assignees.assignees, '[]'::JSON) AS assignees,
COALESCE(assignees.assignee_names, "") AS assignee_names, COALESCE(assignees.assignee_names, '') AS assignee_names,
COALESCE(assignees.names, "") AS names, COALESCE(assignees.names, '') AS names,
COALESCE(labels.labels, "[]"::JSON) AS labels, COALESCE(labels.labels, '[]'::JSON) AS labels,
COALESCE(labels.all_labels, "[]"::JSON) AS all_labels, COALESCE(labels.all_labels, '[]'::JSON) AS all_labels,
-- Other fields -- Other fields
stsc.is_done AS is_complete, stsc.is_done AS is_complete,
reporter.name AS reporter, reporter.name AS reporter,
@@ -317,7 +317,7 @@ export default class TasksControllerV2 extends TasksControllerBase {
LEFT JOIN project_phases pp ON tp.phase_id = pp.id LEFT JOIN project_phases pp ON tp.phase_id = pp.id
LEFT JOIN task_priorities tp_priority ON t.priority_id = tp_priority.id LEFT JOIN task_priorities tp_priority ON t.priority_id = tp_priority.id
LEFT JOIN users reporter ON t.reporter_id = reporter.id LEFT JOIN users reporter ON t.reporter_id = reporter.id
LEFT JOIN task_timers tt ON t.id = tt.task_id AND tt.user_id = "${userId}" LEFT JOIN task_timers tt ON t.id = tt.task_id AND tt.user_id = $${isSubTasks ? "3" : "2"}
LEFT JOIN task_aggregates agg ON t.id = agg.id LEFT JOIN task_aggregates agg ON t.id = agg.id
LEFT JOIN task_assignees assignees ON t.id = assignees.task_id LEFT JOIN task_assignees assignees ON t.id = assignees.task_id
LEFT JOIN task_labels labels ON t.id = labels.task_id LEFT JOIN task_labels labels ON t.id = labels.task_id
@@ -402,7 +402,7 @@ export default class TasksControllerV2 extends TasksControllerBase {
req.query.customColumns = "true"; req.query.customColumns = "true";
const q = TasksControllerV2.getQuery(req.user?.id as string, req.query); const q = TasksControllerV2.getQuery(req.user?.id as string, req.query);
const params = isSubTasks ? [req.params.id || null, req.query.parent_task] : [req.params.id || null]; const params = isSubTasks ? [req.params.id || null, req.query.parent_task, req.user?.id] : [req.params.id || null, req.user?.id];
const result = await db.query(q, params); const result = await db.query(q, params);
const tasks = [...result.rows]; const tasks = [...result.rows];
@@ -510,7 +510,7 @@ export default class TasksControllerV2 extends TasksControllerBase {
req.query.customColumns = "true"; req.query.customColumns = "true";
const q = TasksControllerV2.getQuery(req.user?.id as string, req.query); const q = TasksControllerV2.getQuery(req.user?.id as string, req.query);
const params = isSubTasks ? [req.params.id || null, req.query.parent_task] : [req.params.id || null]; const params = isSubTasks ? [req.params.id || null, req.query.parent_task, req.user?.id] : [req.params.id || null, req.user?.id];
const result = await db.query(q, params); const result = await db.query(q, params);
let data: any[] = []; let data: any[] = [];
@@ -1060,7 +1060,7 @@ export default class TasksControllerV2 extends TasksControllerBase {
const queryStartTime = performance.now(); const queryStartTime = performance.now();
const q = TasksControllerV2.getQuery(req.user?.id as string, req.query); const q = TasksControllerV2.getQuery(req.user?.id as string, req.query);
const params = isSubTasks ? [req.params.id || null, req.query.parent_task] : [req.params.id || null]; const params = isSubTasks ? [req.params.id || null, req.query.parent_task, req.user?.id] : [req.params.id || null, req.user?.id];
const result = await db.query(q, params); const result = await db.query(q, params);
const tasks = [...result.rows]; const tasks = [...result.rows];
@@ -1126,7 +1126,7 @@ export default class TasksControllerV2 extends TasksControllerBase {
phase: task.phase_name || "Development", phase: task.phase_name || "Development",
progress: typeof task.complete_ratio === "number" ? task.complete_ratio : 0, progress: typeof task.complete_ratio === "number" ? task.complete_ratio : 0,
assignees: task.assignees?.map((a: any) => a.team_member_id) || [], assignees: task.assignees?.map((a: any) => a.team_member_id) || [],
assignee_names: task.assignee_names || task.names || [], assignee_names: task.assignees || [],
labels: task.labels?.map((l: any) => ({ labels: task.labels?.map((l: any) => ({
id: l.id || l.label_id, id: l.id || l.label_id,
name: l.name, name: l.name,