import { pool } from '../../config/db.js'; const LIST_SELECT = ` SELECT a.id, a.project_id, a.code, a.name, a.description, a.responsible_user_id, u.name AS responsible_name, a.priority_id, pr.name AS priority_name, pr.color AS priority_color, a.status_id, st.name AS status_name, st.color AS status_color, st.is_closed AS status_is_closed, a.start_date, a.due_date, a.actual_end_date, a.progress_pct, a.is_milestone, a.estimated_hours, a.created_by, a.created_at, a.updated_at FROM activities a JOIN priorities pr ON pr.id = a.priority_id JOIN activity_statuses st ON st.id = a.status_id LEFT JOIN users u ON u.id = a.responsible_user_id `; export async function findByProject(projectId) { const [rows] = await pool.query(`${LIST_SELECT} WHERE a.project_id = ? ORDER BY a.start_date, a.id`, [projectId]); return rows; } export async function findById(id) { const [rows] = await pool.query(`${LIST_SELECT} WHERE a.id = ?`, [id]); return rows[0] || null; } export async function create(projectId, data) { const [result] = await pool.query( `INSERT INTO activities (project_id, code, name, description, responsible_user_id, priority_id, status_id, start_date, due_date, is_milestone, estimated_hours, created_by) VALUES (?, 'PENDING', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [ projectId, data.name, data.description || null, data.responsibleUserId || null, data.priorityId, data.statusId, data.startDate || null, data.dueDate || null, data.isMilestone ? 1 : 0, data.estimatedHours || null, data.createdBy, ] ); const id = result.insertId; const code = `ACT-${String(id).padStart(4, '0')}`; await pool.query('UPDATE activities SET code = ? WHERE id = ?', [code, id]); return findById(id); } export async function update(id, data) { await pool.query( `UPDATE activities SET name = ?, description = ?, responsible_user_id = ?, priority_id = ?, status_id = ?, start_date = ?, due_date = ?, actual_end_date = ?, is_milestone = ?, estimated_hours = ? WHERE id = ?`, [ data.name, data.description || null, data.responsibleUserId || null, data.priorityId, data.statusId, data.startDate || null, data.dueDate || null, data.actualEndDate || null, data.isMilestone ? 1 : 0, data.estimatedHours || null, id, ] ); return findById(id); } export async function updateProgress(id, progressPct) { await pool.query('UPDATE activities SET progress_pct = ? WHERE id = ?', [progressPct, id]); } // Arrastra activity_dependencies (ambos lados) y tasks por ON DELETE CASCADE. export async function remove(id) { await pool.query('DELETE FROM activities WHERE id = ?', [id]); } export async function countTasks(id) { const [rows] = await pool.query('SELECT COUNT(*) AS c FROM tasks WHERE activity_id = ?', [id]); return rows[0].c; } export async function listDependencies(id) { const [rows] = await pool.query( `SELECT d.depends_on_activity_id AS id, a.code, a.name, a.status_id, st.is_closed AS status_is_closed FROM activity_dependencies d JOIN activities a ON a.id = d.depends_on_activity_id JOIN activity_statuses st ON st.id = a.status_id WHERE d.activity_id = ?`, [id] ); return rows; } export async function addDependency(activityId, dependsOnActivityId) { await pool.query( 'INSERT IGNORE INTO activity_dependencies (activity_id, depends_on_activity_id) VALUES (?, ?)', [activityId, dependsOnActivityId] ); return listDependencies(activityId); } export async function removeDependency(activityId, dependsOnActivityId) { await pool.query('DELETE FROM activity_dependencies WHERE activity_id = ? AND depends_on_activity_id = ?', [ activityId, dependsOnActivityId, ]); return listDependencies(activityId); } export async function findDueOrOverdue(userId, { onlyMine = false } = {}) { const clauses = ["st.is_closed = 0", "a.due_date IS NOT NULL"]; const params = []; if (onlyMine) { clauses.push('a.responsible_user_id = ?'); params.push(userId); } const [rows] = await pool.query( `${LIST_SELECT} WHERE ${clauses.join(' AND ')} ORDER BY a.due_date`, params ); return rows; }