13a69aadc3
Vacio = se repite sin fin (comportamiento previo). Al completar un ciclo cuyo proximo vencimiento supera "hasta", la tarea se desactiva sola. Probado en dev con curl (3 ciclos seguidos, se desactiva justo al superar la fecha) y validacion de que "hasta" no puede ser anterior al proximo vencimiento. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
7.3 KiB
7.3 KiB
API - project.linkedcorp.net
Base URL
- Desarrollo:
http://localhost:4019/api - Producción:
https://project.linkedcorp.net/api
Autenticacion
- Tipo: Bearer JWT (
Authorization: Bearer <token>), emitido por/api/auth/login. - El backend revalida
is_activedel usuario en cada request (no solo la firma del JWT).
Formato de respuesta
{
"success": true,
"data": {},
"error": null
}
Endpoints principales
Auth
POST /api/auth/login—{ email, password }→{ token, user }. Si el usuario no estaactive(pending_verification/pending_approval) ois_active=0,403con mensaje especifico.POST /api/auth/register— público.{ name, email, password }→ si es el primer usuario del sistema:{ bootstrap: true, token, user }(superadmin, sesion directa); si no:{ bootstrap: false }y se envia (o loguea, sin SMTP) un correo de verificación.GET /api/auth/verify-email?token=...— público. Pasa el usuario apending_approvaly notifica in-app a losadmin/superadminactivos.GET /api/auth/invite?token=...— público.{ email }de la invitación (para prellenar el formulario), o400si es inválida/expiró.POST /api/auth/accept-invite— público.{ token, name, password }→ completa la cuenta creada porPOST /api/projects/:id/memberscon{ email }(ver arriba): elige nombre y clave, pasa aactivedirecto (sin aprobación — quien invitó ya la vetó) y devuelve{ token, user }con sesión iniciada, igual que el bootstrap del primer usuario.POST /api/auth/forgot-password— público.{ email }→ respuesta siempre genérica.POST /api/auth/reset-password— público.{ token, password }.PUT /api/auth/change-password— autenticado.{ currentPassword, newPassword }, exige la clave actual (distinto dereset-password, que usa un token de correo sin sesión).POST /api/auth/logoutGET /api/auth/me— usuario actual
Usuarios (/api/users) — lectura para cualquier autenticado; escritura solo Administrador/Superadministrador
GET /api/users·POST /api/users·PUT /api/users/:id·PATCH /api/users/:id/activePOST /api/users/:id/approve—{ roleId?, departmentId? }, solo sobre usuariospending_approvalPOST /api/users/:id/reject— borra al usuariopending_approval(se audita el email antes)
Departamentos (/api/departments)
GET /api/departments(árbol) ·POST /api/departments·PUT /api/departments/:id·DELETE /api/departments/:id
Proyectos (/api/projects)
GET /api/projects(filtros: estado, responsable, prioridad;trash=true= papelera, solo superadmin) ·POST /api/projectsGET /api/projects/:id·PUT /api/projects/:idDELETE /api/projects/:id— eliminación lógica (deleted_at/deleted_by), mismo permiso que editar el proyecto.POST /api/projects/:id/restoreyDELETE /api/projects/:id/permanent(borrado físico, irreversible, arrastra actividades/comentarios/adjuntos) — ambos solo superadmin;permanentexige que el proyecto ya esté en la papelera (400 si no).POST /api/projects/:id/members—{ userId }(usuario existente) o{ email }(si el correo no pertenece a nadie todavía, crea una cuentainvitedy le manda un correo de invitación para que complete su registro; la fila deproject_membersya queda creada de una vez).roleInProjectopcional:'admin'= administrador del proyecto. Responde{ members, invited }.PUT /api/projects/:id/members/:userId/role({ admin: true|false }, otorga o quita el rol de administrador de ese proyecto — un proyecto puede tener uno o más administradores, sin importar el rol global del usuario; nunca toca alowner) ·DELETE /api/projects/:id/members/:userId
Actividades (/api/activities)
GET /api/projects/:projectId/activities·POST /api/projects/:projectId/activitiesGET /api/activities/:id·PUT /api/activities/:idPOST /api/activities/:id/dependencies·DELETE /api/activities/:id/dependencies/:dependsOnId
Tareas (/api/activities/:activityId/tasks)
GET·POST·PUT /api/tasks/:id·PATCH /api/tasks/:id/done·DELETE /api/tasks/:id
Tareas recurrentes (/api/recurring-tasks) — menú propio, independiente de Proyectos
GET·POST·PUT /api/recurring-tasks/:id·DELETE /api/recurring-tasks/:idPOST /api/recurring-tasks/:id/complete— cierra el ciclo actual y calcula el próximo vencimiento sumando la periodicidad (interval_value+interval_unit).POST /api/recurring-tasks/from-task/:taskId— crea una tarea recurrente a partir de una tarea puntual de una actividad (la original no se borra); mismo body quePOST /.- Body:
{ name, description?, projectId?, responsibleUserId?, intervalUnit: 'days'|'months'|'years', intervalValue, nextDueDate, endDate?, reminderDaysBefore, reminderHour: 0-23 }.endDatevacío = se repite sin fin; al completar un ciclo que la supera,is_activepasa afalsesolo. - Recordatorio por correo: un job en el propio proceso del backend revisa cada 15 minutos
(
src/jobs/recurringTaskReminders.js) y manda el correo cuandonext_due_date - reminderDaysBeforecae hoy, a la horareminderHour. Un solo envío por ciclo (last_reminder_sent_at, se limpia al completar el ciclo).
Comentarios (/api/comments)
GET /api/comments?entityType=project&entityId=1·POST /api/comments
Adjuntos (/api/attachments)
GET /api/attachments?entityType=activity&entityId=1·POST /api/attachments(multipart)GET /api/attachments/:id/download·DELETE /api/attachments/:id
Notificaciones (/api/notifications)
GET /api/notifications·PATCH /api/notifications/:id/read·PATCH /api/notifications/read-all
Dashboard (/api/dashboard)
GET /api/dashboard/summary— KPIs (activos, atrasados, pendientes/vencidas/hoy, avance promedio)GET /api/dashboard/calendar?month=2026-09— actividades por fecha límiteGET /api/projects/:id/gantt— actividades con fechas/avance para el Gantt
Catálogos (/api/catalogs) — lectura general, escritura solo Superadministrador
GET/POST/PUT/DELETE /api/catalogs/project-statusesGET/POST/PUT/DELETE /api/catalogs/activity-statusesGET/POST/PUT/DELETE /api/catalogs/prioritiesGET/POST/PUT/DELETE /api/catalogs/project-types
Auditoría (/api/audit) — solo Superadministrador / Administrador / Jefe de TI
GET /api/audit?entityType=project&entityId=1
Configuración SMTP (/api/settings) — solo Superadministrador
GET /api/settings/smtp—{ host, port, user, from, configured }(nunca la clave)PUT /api/settings/smtp—{ host, port, user, from, pass? }(passvacío = no cambiarla)POST /api/settings/smtp/test—{ host, port, user, from, pass?, to }(passvacío = usa la guardada). Envía un correo real con los valores del formulario (aunque no se hayan guardado) y responde{ sent: true }o400con el error real del servidor SMTP. Rate-limited (10/15min).
Errores esperados
400validación401no autenticado / token inválido o expirado403sin permisos para la acción (según rol)404no encontrado (incluye cuando el recurso existe pero no pertenece al usuario/alcance)500error interno (sanitizado, sin detalle de stack en producción)