119 lines
3.5 KiB
TypeScript
119 lines
3.5 KiB
TypeScript
// lib/tasksService.ts
|
|
import { dolibarrFetch } from "./dolibarrClient";
|
|
import { DolibarrTask, Task, mapDolibarrTask } from "@/types/task";
|
|
|
|
/**
|
|
* Obtener todas las tareas de un proyecto específico
|
|
*
|
|
* Nota: El endpoint /projects/{id}/tasks de Dolibarr no devuelve tareas correctamente,
|
|
* por lo que obtenemos todas las tareas y filtramos por fk_project en el cliente.
|
|
*/
|
|
export async function getTasksByProjectId(projectId: number): Promise<Task[]> {
|
|
try {
|
|
// Obtener todas las tareas (Dolibarr no filtra bien por proyecto)
|
|
const dolibarrTasks: DolibarrTask[] = await dolibarrFetch('tasks');
|
|
|
|
// Si no hay tareas, devolver array vacío
|
|
if (!dolibarrTasks || !Array.isArray(dolibarrTasks)) {
|
|
return [];
|
|
}
|
|
|
|
// Filtrar tareas que pertenecen a este proyecto
|
|
const projectTasks = dolibarrTasks.filter(
|
|
task => String(task.fk_project) === String(projectId)
|
|
);
|
|
|
|
// Mapear las tareas al formato de la UI
|
|
return projectTasks.map(mapDolibarrTask);
|
|
} catch (error) {
|
|
console.error('Error fetching tasks for project:', projectId, error);
|
|
// Si el error es 404 (no hay tareas), devolver array vacío
|
|
if (error instanceof Error && error.message.includes('404')) {
|
|
return [];
|
|
}
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Obtener todas las tareas (sin filtro de proyecto)
|
|
* Endpoint: /tasks
|
|
*/
|
|
export async function getAllTasks(): Promise<Task[]> {
|
|
try {
|
|
const dolibarrTasks: DolibarrTask[] = await dolibarrFetch('tasks');
|
|
|
|
if (!dolibarrTasks || !Array.isArray(dolibarrTasks)) {
|
|
return [];
|
|
}
|
|
|
|
return dolibarrTasks.map(mapDolibarrTask);
|
|
} catch (error) {
|
|
console.error('Error fetching all tasks:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Obtener una tarea específica por ID
|
|
* Endpoint: /tasks/{id}
|
|
*/
|
|
export async function getTaskById(taskId: number): Promise<Task | null> {
|
|
try {
|
|
const dolibarrTask: DolibarrTask = await dolibarrFetch(`tasks/${taskId}`);
|
|
return mapDolibarrTask(dolibarrTask);
|
|
} catch (error) {
|
|
console.error('Error fetching task:', taskId, error);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Obtener datos crudos de Dolibarr para una tarea
|
|
*/
|
|
export async function getDolibarrTaskById(taskId: number): Promise<DolibarrTask | null> {
|
|
try {
|
|
return await dolibarrFetch(`tasks/${taskId}`);
|
|
} catch (error) {
|
|
console.error('Error fetching Dolibarr task:', taskId, error);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Calcular estadísticas de las tareas de un proyecto
|
|
*/
|
|
export function calculateTaskStats(tasks: Task[]) {
|
|
const total = tasks.length;
|
|
const completed = tasks.filter(t => t.status === '2').length;
|
|
const inProgress = tasks.filter(t => t.status === '1').length;
|
|
const draft = tasks.filter(t => t.status === '0').length;
|
|
|
|
const totalPlannedHours = tasks.reduce((sum, t) => sum + t.plannedHours, 0);
|
|
const totalWorkedHours = tasks.reduce((sum, t) => sum + t.workedHours, 0);
|
|
|
|
const avgProgress = total > 0
|
|
? Math.round(tasks.reduce((sum, t) => sum + t.progress, 0) / total)
|
|
: 0;
|
|
|
|
const highPriority = tasks.filter(t => t.priority === '3').length;
|
|
const overdue = tasks.filter(t => {
|
|
if (!t.endDate && !t.plannedEndDate) return false;
|
|
const endDate = t.endDate || t.plannedEndDate;
|
|
return endDate && new Date(endDate) < new Date() && t.status !== '2';
|
|
}).length;
|
|
|
|
return {
|
|
total,
|
|
completed,
|
|
inProgress,
|
|
draft,
|
|
totalPlannedHours,
|
|
totalWorkedHours,
|
|
avgProgress,
|
|
highPriority,
|
|
overdue,
|
|
completionRate: total > 0 ? Math.round((completed / total) * 100) : 0,
|
|
};
|
|
}
|