Files
project.linkedcorp.net/BASE_DE_DATOS.md
T
Milton Gonzalez f96391d360 feat: administradores por proyecto y Configuracion solo para superadmin
- Un proyecto puede tener uno o mas administradores (role_in_project=
  'admin' en project_members), independiente del rol global del usuario.
  Nuevo PUT /api/projects/:id/members/:userId/role; canWriteProject lo
  reconoce ademas del comportamiento previo (admin/superadmin/it_manager
  global, o project_lead miembro). UI: casilla al agregar miembro + boton
  de escudo para promover/degradar (nunca toca al Dueño).
- Menu "Configuracion" (apariencia, catalogos, SMTP) visible y accesible
  solo para el superadmin: oculto en el nav y con guarda en la ruta
  /configuracion para quien la teclee directo. Escritura de catalogos
  restringida de [superadmin, admin] a solo superadmin para que el
  backend sea consistente con la UI.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-09 09:41:06 -05:00

7.0 KiB

Base de Datos - project.linkedcorp.net

Motor

  • Motor: MariaDB
  • Base principal: project_linkedcorp
  • Host desarrollo: 192.168.222.20
  • Host producción: 192.168.222.32
  • Puerto: 3306
  • Charset: utf8mb4
  • Collation: utf8mb4_unicode_ci

Fuente de verdad

  • La base ya existe: sí (creada en dev el 2026-09-03, usuario project_linkedcorp).
  • Archivo SQL base: backend/database/migrations/ (SQL idempotente, numerado, CREATE TABLE IF NOT EXISTS).
  • Seeds: backend/database/seeds/ (roles, catálogos, usuario admin de dev).

Tablas principales (MVP)

Tabla Contenido
roles catálogo fijo de 6 roles (superadmin, admin, it_manager, project_lead, collaborator, viewer)
users usuarios, con rol, departamento y ciclo de vida de registro (status, tokens)
system_settings clave/valor de configuración del sistema (hoy: SMTP, clave cifrada)
departments departamentos/áreas, jerarquía simple vía parent_id
project_types catálogo de tipos de proyecto
priorities catálogo de prioridades (baja/media/alta/crítica)
project_statuses catálogo de estados de proyecto
activity_statuses catálogo de estados de actividad
projects proyectos
project_members usuarios asignados a un proyecto (reemplaza "equipos" como módulo aparte)
activities actividades de un proyecto
activity_dependencies dependencias simples entre actividades ("depende de")
subtasks checklist liviano dentro de una actividad
comments comentarios sobre proyecto o actividad (entity_type + entity_id)
attachments archivos adjuntos a proyecto o actividad
notifications notificaciones in-app por usuario
audit_log auditoría central (quién, qué, sobre qué, cuándo)

Relaciones clave

  • users.role_id -> roles.id, users.department_id -> departments.id
  • departments.parent_id -> departments.id (jerarquía opcional, ej. TI → Desarrollo)
  • projects.status_id -> project_statuses.id, projects.priority_id -> priorities.id, projects.project_type_id -> project_types.id, projects.owner_user_id -> users.id, projects.requesting_department_id / responsible_department_id -> departments.id
  • project_members.project_id -> projects.id, project_members.user_id -> users.id
  • activities.project_id -> projects.id, activities.status_id -> activity_statuses.id, activities.priority_id -> priorities.id, activities.responsible_user_id -> users.id
  • activity_dependencies.activity_id / depends_on_activity_id -> activities.id
  • subtasks.activity_id -> activities.id, subtasks.responsible_user_id -> users.id (nullable)
  • comments.entity_id / attachments.entity_id apuntan a projects.id o activities.id según entity_type (sin FK física cruzada — se valida en el servicio)

Reglas de datos

  • projects.progress_pct y activities.progress_pct son calculados por el servicio, no editables directo por el cliente: actividad con subtareas = % de subtareas hechas; actividad sin subtareas = manual (0-100); proyecto = promedio del avance de sus actividades.
  • users.password_hash con bcrypt, nunca texto plano ni reversible.
  • users.status (pending_verification/pending_approval/active) es el ciclo de vida del autorregistro, independiente de is_active (que sigue siendo el interruptor manual del admin para desactivar a alguien ya activo). Un usuario pending_approval rechazado se borra físicamente (no hay estado "rechazado" — se audita el email en audit_log antes de borrar).
  • system_settings.value para smtp_pass_enc va cifrado (AES-256-GCM, ENCRYPTION_KEY del .env) — nunca en texto plano, nunca se devuelve por la API (solo configured: true/false).
  • Borrado lógico donde aplique (users.is_active); nunca DELETE físico de usuarios activos con historial (los pending_approval rechazados sí se borran, ver arriba).
  • projects.deleted_at/deleted_by: eliminación lógica (quien puede editar el proyecto puede "eliminarlo" — se oculta de listados/dashboard, sigue en BD). Borrado físico (DELETE, arrastra actividades/comentarios/adjuntos por ON DELETE CASCADE) solo vía permanentlyDeleteProject, solo superadmin, y solo sobre un proyecto que ya tiene deleted_at (dos pasos, nunca directo).
  • project_members.role_in_project: 'owner' (dueño, se asigna solo al crear el proyecto, nunca se toca desde el endpoint de rol), 'admin' (administrador de ese proyecto puntual — un proyecto puede tener varios, otorgado por quien ya puede escribir el proyecto, sin importar el rol global de a quién se lo otorgan), NULL/otro = miembro sin permisos de escritura (salvo que además sea project_lead global, comportamiento previo sin cambios).
  • Empresa asumida única (no hay tabla companies en el MVP).
  • Producción siempre usa 192.168.222.32. Desarrollo siempre usa 192.168.222.20. No mezclar.

Riesgos o decisiones

  • Sin triggers de BD para recalcular avances: toda la lógica vive en la capa service/ del backend (más simple de depurar y de extender en fase 2).
  • risk_level es un campo simple en projects (bajo/medio/alto) — el módulo completo de Riesgos (probabilidad/impacto/mitigación) queda para fase 2, sin necesitar migrar este campo.

Archivos relacionados

  • backend/.env.example
  • backend/database/migrations/*.sql
  • backend/database/seeds/*.sql

Crear la base de datos en DESARROLLO (.20)

Ya ejecutado para este proyecto (2026-09-03):

bash /home/mgonzalez/desarrollo/project-md-templates/crear-db-dev.sh project_linkedcorp project_linkedcorp

BD project_linkedcorp y usuario project_linkedcorp@192.168.222.40 creados en 192.168.222.20. Las credenciales están en backend/.env (no versionado).

Verificar:

mysql --defaults-extra-file=~/.config/mysql/dev20-admin.cnf -e "SHOW DATABASES LIKE 'project_linkedcorp';"

Aplicar migraciones/seeds (una vez creado backend/src/scripts/migrate-db.js):

cd backend
set -a && source .env && set +a
node src/scripts/migrate-db.js
node src/scripts/seed-db.js

Setup de base de datos en producción — ejecutado el 2026-09-06

BD project_linkedcorp creada en .32 con crear-db-prod.sh (grant a 192.168.222.3). Detalle del proceso y estado real en PRODUCCION.md.

Migración en el servidor de aplicaciones (.3):

ssh deploy@192.168.222.3 -p 2203
cd /opt/apps/project.linkedcorp.net/source/backend
set -a && source /opt/apps/project.linkedcorp.net/backend/.env && set +a
node src/scripts/migrate-db.js
node src/scripts/seed-db.js          # solo catálogos/roles; sin datos de ejemplo en produccion
node src/scripts/create-admin.js "Nombre" correo@dominio   # solo la primera vez, bootstrap manual

Actualizaciones de esquema en producción

Método: archivos SQL idempotentes en backend/database/migrations/00X-nombre.sql (CREATE TABLE IF NOT EXISTS / information_schema guards), aplicados con node src/scripts/migrate-db.js. Siempre backup (mysqldump --single-transaction) antes de migrar en producción.