72b616bd02
Menu propio en la barra lateral, independiente de Proyectos: - Periodicidad configurable (cada N dias/meses/años), proximo vencimiento, responsable, proyecto de origen opcional. - "Completar ciclo" avanza el proximo vencimiento sumando la periodicidad y limpia el recordatorio ya enviado. - Recordatorio por correo automatico N dias antes del vencimiento (default 7), a una hora del dia configurable. Un job en el propio proceso del backend (setInterval cada 15 min) revisa y envia, sin infraestructura nueva (cron del SO, cola, etc). - Desde la pestaña Tareas de una actividad, cada tarea tiene un boton "Convertir en recurrente" que la promueve (la tarea original no se borra). Probado en dev con curl (crear, completar ciclo avanza next_due_date, promover desde una tarea real, disparo real del job de recordatorios verificado forzando fecha/hora, segunda corrida no reenvia) y Playwright (listado, popup de creacion, popup de promocion anidado sobre el detalle de actividad) sin errores de consola. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
7.2 KiB
7.2 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, reminderDaysBefore, reminderHour: 0-23 }. - 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)