refactor(sistemas/proyectos): migra módulo TI al patrón multi-tenant
Alinea Proyectos TI con la arquitectura del proyecto (mismo patrón que comercial/finanzas/rh/juridico) y migra la ruta del frontend de /ti/proyectos a /sistemas/proyectos para coincidir con el seed de sub-áreas en main.py:_migrate_ti.
Backend — modelos:
- models/ti.py: cambia la base de Base_ti a Base_tenant, alineando los 8 modelos del módulo (TiProyecto, TiProyectoHistorial y 6 catálogos) con el resto de modelos de negocio del proyecto (Fase 0 multi-tenant).
- models/init.py: registra los modelos para que Base_tenant.metadata.create_all los cree al arranque.
- elimina backend/database_ti.py: era un engine paralelo redundante. TI_DATABASE_URL nunca se definió en ningún .env, así que siempre caía al fallback de DATABASE_URL — apuntaba físicamente a la misma DB que database.py, solo con su propio pool. No se importaba desde main.py ni desde ningún router; cero referencias en docker-compose, scripts de deploy o CI.
Backend — router:
- routers/ti.py: extiende el archivo existente (no se crea uno separado) siguiendo el patrón "un router por área" de comercial.py / finanzas.py / rh.py. Conserva GET /api/ti/dashboard-summary (KPIs ejecutivos OAE) y añade: GET/POST/PUT/DELETE /api/ti/proyectos GET /api/ti/proyectos/{id} GET /api/ti/proyectos/dashboard/stats GET/POST/PUT/DELETE /api/ti/catalogos/{tipo}
- /proyectos/dashboard/stats devuelve los agregados precalculados que consume el portal (por_semaforo, por_portafolio, por_etapa con ETAPAS_CANONICAS, scatter avance/tiempo, timeline gantt, stack_portafolio, próximos_deadlines), siguiendo la convención "single source of truth" de comercial/dashboard-summary.
- Todos los endpoints protegidos con Depends(require_area("ti")) y Session = Depends(get_db).
- Recuperado de la rama ti-backup-pre-merge-main-2026-04-30 (perdido durante un merge previo con main) y adaptado al patrón multi-tenant.
Backend — scripts:
- scripts/import_ti.py: portado de 'from database_ti import SessionTi' a 'from database import SessionLocal as SessionTi' para conservar el script utilitario alineado con sus hermanos (import_comercial.py, import_juicios.py, load_*_excel.py).
Frontend:
- migra app/ti/proyectos/{page, nuevo, [id], [id]/editar} a app/sistemas/proyectos/, alineando la ruta con ruta_frontend="/sistemas/proyectos" del seed de sub-áreas.
- actualiza enlaces internos /ti/proyectos -> /sistemas/proyectos en app/sistemas/proyectos/page.tsx (5 ocurrencias) y en components/proyectos/ProyectoForm.tsx (1 ocurrencia).
- elimina el directorio app/ti/ completo.
- lib/ti.api.ts queda intacto: las URLs /api/ti/* son rutas del backend (prefijo de área), no rutas de Next.js.
Co-Authored-By: Claude Opus 4.7 noreply@anthropic.com