- Added logic to reset manual_progress to FALSE when a task transitions from "done" to "todo" or "doing", allowing for accurate progress recalculation based on subtasks. - Improved logging for task status changes to provide better insights into task management actions. - Ensured parent task progress updates are triggered appropriately for subtasks during status changes.
152 lines
5.4 KiB
TypeScript
152 lines
5.4 KiB
TypeScript
import {Server, Socket} from "socket.io";
|
|
|
|
import db from "../../config/db";
|
|
import {NotificationsService} from "../../services/notifications/notifications.service";
|
|
import {TASK_STATUS_COLOR_ALPHA} from "../../shared/constants";
|
|
import {SocketEvents} from "../events";
|
|
import {getLoggedInUserIdFromSocket, log, log_error, notifyProjectUpdates} from "../util";
|
|
import TasksControllerV2 from "../../controllers/tasks-controller-v2";
|
|
import {getTaskDetails, logProgressChange, logStatusChange} from "../../services/activity-logs/activity-logs.service";
|
|
import { assignMemberIfNot } from "./on-quick-assign-or-remove";
|
|
import logger from "../../utils/logger";
|
|
|
|
export async function on_task_status_change(_io: Server, socket: Socket, data?: string) {
|
|
try {
|
|
const body = JSON.parse(data as string);
|
|
const userId = getLoggedInUserIdFromSocket(socket);
|
|
const taskData = await getTaskDetails(body.task_id, "status_id");
|
|
|
|
const canContinue = await TasksControllerV2.checkForCompletedDependencies(body.task_id, body.status_id);
|
|
|
|
if (!canContinue) {
|
|
const {color_code, color_code_dark} = await TasksControllerV2.getTaskStatusColor(taskData.status_id);
|
|
|
|
return socket.emit(SocketEvents.TASK_STATUS_CHANGE.toString(), {
|
|
id: body.task_id,
|
|
parent_task: body.parent_task,
|
|
status_id: taskData.status_id,
|
|
color_code: color_code + TASK_STATUS_COLOR_ALPHA,
|
|
color_code_dark,
|
|
completed_deps: canContinue
|
|
});
|
|
}
|
|
const q2 = "SELECT handle_on_task_status_change($1, $2, $3) AS res;";
|
|
const results1 = await db.query(q2, [userId, body.task_id, body.status_id]);
|
|
const [d] = results1.rows;
|
|
const changeResponse = d.res;
|
|
|
|
changeResponse.color_code = changeResponse.color_code + TASK_STATUS_COLOR_ALPHA;
|
|
|
|
// notify to all task members of the change
|
|
for (const member of changeResponse.members || []) {
|
|
if (member.user_id === userId) continue;
|
|
NotificationsService.createNotification({
|
|
userId: member.user_id,
|
|
teamId: member.team_id,
|
|
socketId: member.socket_id,
|
|
message: changeResponse.message,
|
|
taskId: body.task_id,
|
|
projectId: changeResponse.project_id
|
|
});
|
|
}
|
|
|
|
// Check if the new status is in a "done" category
|
|
if (changeResponse.status_category?.is_done) {
|
|
// Get current progress value
|
|
const progressResult = await db.query(`
|
|
SELECT progress_value, manual_progress
|
|
FROM tasks
|
|
WHERE id = $1
|
|
`, [body.task_id]);
|
|
|
|
const currentProgress = progressResult.rows[0]?.progress_value;
|
|
const isManualProgress = progressResult.rows[0]?.manual_progress;
|
|
|
|
// Only update if not already 100%
|
|
if (currentProgress !== 100) {
|
|
// Update progress to 100%
|
|
await db.query(`
|
|
UPDATE tasks
|
|
SET progress_value = 100, manual_progress = TRUE
|
|
WHERE id = $1
|
|
`, [body.task_id]);
|
|
|
|
log(`Task ${body.task_id} moved to done status - progress automatically set to 100%`, null);
|
|
|
|
// Log the progress change to activity logs
|
|
await logProgressChange({
|
|
task_id: body.task_id,
|
|
old_value: currentProgress !== null ? currentProgress.toString() : "0",
|
|
new_value: "100",
|
|
socket
|
|
});
|
|
|
|
// If this is a subtask, update parent task progress
|
|
if (body.parent_task) {
|
|
setTimeout(() => {
|
|
socket.emit(SocketEvents.GET_TASK_PROGRESS.toString(), body.parent_task);
|
|
}, 100);
|
|
}
|
|
}
|
|
} else {
|
|
// Task is moving from "done" to "todo" or "doing" - reset manual_progress to FALSE
|
|
// so progress can be recalculated based on subtasks
|
|
await db.query(`
|
|
UPDATE tasks
|
|
SET manual_progress = FALSE
|
|
WHERE id = $1
|
|
`, [body.task_id]);
|
|
|
|
log(`Task ${body.task_id} moved from done status - manual_progress reset to FALSE`, null);
|
|
|
|
// If this is a subtask, update parent task progress
|
|
if (body.parent_task) {
|
|
setTimeout(() => {
|
|
socket.emit(SocketEvents.GET_TASK_PROGRESS.toString(), body.parent_task);
|
|
}, 100);
|
|
}
|
|
}
|
|
|
|
const info = await TasksControllerV2.getTaskCompleteRatio(body.parent_task || body.task_id);
|
|
|
|
socket.emit(SocketEvents.TASK_STATUS_CHANGE.toString(), {
|
|
id: body.task_id,
|
|
parent_task: body.parent_task,
|
|
color_code: changeResponse.color_code,
|
|
color_code_dark: changeResponse.color_code_dark,
|
|
complete_ratio: info?.ratio,
|
|
completed_count: info?.total_completed,
|
|
total_tasks_count: info?.total_tasks,
|
|
status_id: body.status_id,
|
|
completed_at: changeResponse.completed_at,
|
|
statusCategory: changeResponse.status_category,
|
|
completed_deps: canContinue
|
|
});
|
|
|
|
socket.emit(SocketEvents.GET_TASK_PROGRESS.toString(), {
|
|
id: body.task_id,
|
|
parent_task: body.parent_task,
|
|
complete_ratio: info?.ratio,
|
|
completed_count: info?.total_completed,
|
|
total_tasks_count: info?.total_tasks
|
|
});
|
|
|
|
const isAlreadyAssigned = await TasksControllerV2.checkUserAssignedToTask(body.task_id, userId as string, body.team_id);
|
|
|
|
if (!isAlreadyAssigned) {
|
|
await assignMemberIfNot(body.task_id, userId as string, body.team_id, _io, socket);
|
|
}
|
|
|
|
logStatusChange({
|
|
task_id: body.task_id,
|
|
socket,
|
|
new_value: body.status_id,
|
|
old_value: taskData.status_id
|
|
});
|
|
|
|
notifyProjectUpdates(socket, body.task_id);
|
|
} catch (error) {
|
|
log_error(error);
|
|
}
|
|
}
|