--- asset_id: MIN-EL-Jesus-20260703-v01 version: v01 tipo: MIN — Minuta del día owner: Jesús sherpa: Jess ratificador: Jesús fecha: 2026-07-03 intellibank: IB-EL-EmpowerLabs subbank: EQ-EL-Equipo proyecto: SmartPlaybooks · api-nodejs-mongo · Módulo Métricas · Rebelocity Club --- # Minuta del día — Jesús · 2026-07-03 ## Qué se hizo - **Auditoría de pendientes cross-minutas** — consolidado de todos los `[ ]` abiertos desde 20260619 a 20260702; cerrados `ms-icon-google` y `registro con correo` (ya resueltos) - **Revisión de análisis funcionales RClub** (`OUT-REB-RClub-AnalisisFuncional-v01` + `TribusRRHH-v01`) — levantamiento de pendientes accionables por Jesús: quick wins de taxonomía/Foros, aislamiento multi-tenant (MT-01) y estado real de la capa transaccional - **Auditoría de sistema de puntos** — creado `PQ-EL-RClub-BackendPuntos-v01.md` y recibida respuesta `RESP-EL-RClub-BackendPuntos-v01.md`. Confirmado: Points v2 está **implementado y funcional en backend** (18 endpoints bajo `/api/points/`). Los componentes frontend `manage-membership-user`, `manage-points` y `manage-membership-merchant` ya están construidos y se comparten entre MasterPlaybooks, TribusRRHH y Rebelocity Club - **Aclaración arquitectura multi-tenant de puntos** — el backend resuelve el `organizationId` por dominio/canal; el frontend **no necesita enviarlo**. `communityType` en `saveCard()` ya no se usa. Los componentes de puntos funcionan correctamente en las 3 apps sin cambios de frontend - **EJE 2 — Rendimiento MasterPlaybooks** — aplicados 7 fixes: R01 lector pre-fetch eager, R01 catálogo `trackBy`, R04 sesión corrupta "53h 7m", R04 precio `$null USD`, R04 URL con ID numérico → slug amigable, R05 búsqueda estado contradictorio, R06 modal checkout mostraba login con sesión activa. Ver sección EJE 2 más abajo. - **EJE 1 — Revisión del inventario funcional MPX** — aclarado el estado real de 20 ítems del `DC-MPX-InventarioFuncionalidades-v02` (U02–U22, N04, A04–A06, ADM08, ADM13). Confirmados existentes: control de versiones de contenido (A06), pestaña Categorías en admin (ADM08), lógica de recuperación de contraseña (U03). Desactivado intencionalmente: Google OAuth (U02) — oculto por homologación entre las 3 apps. No son bugs: campos de perfil vacíos (U04, usuario no los llenó), límites 100/100 en Free (U20, datos de prueba correctos). Pendientes de decisión de producto antes de estimar: cancelación self-service (U21), factura electrónica (U22), recomendaciones personalizadas (U10), flujo de upgrade/downgrade (U05). Acción identificada: formulario de personalización del Sherpa en MPX usa el de Tribus/RRHH como fallback — crear formulario propio para el canal (N04). Documentado en `RP-EL-MPX-FixesRendimiento-v01.md`. - **Auditoría de correcciones de performance de Tribus → MPX** — creado `AUD-EL-MPX-CorreccionesPerformance-v01.md`. Evaluadas las 9 correcciones aplicadas en TribusRRHH/Rebelocity contra el código de MasterPlaybooks. Resultado: C-01 (subscriptions sin cancelar) y C-06 (location.replace en rutas internas) pendientes de aplicar; C-09b (Quill doble carga) ya identificado como R02. Los banners ya tienen las correcciones aplicadas: `ad-banner` tiene `takeUntil`, `probe.onerror` y RAF throttle. `store-banner` descartado — no está en uso. C-04 (CSS `transition: background-image` inválido) pendiente en 3 archivos: dashboard-author, dashboard-user, custom-banner. --- ## Decisiones - **Sistema de puntos frontend: no requiere trabajo adicional** para conectar RClub — los componentes ya están y el backend resuelve el canal por dominio. Lo que queda de Points v2 es decisión de producto (Clearing House, gating de beneficios por tier) y no desbloquea trabajo de frontend hoy - **Análisis funcional RClub marcado como "ausente"**: los análisis fueron desde UI/browser — no veían la capa transaccional porque no estaba visible en la navegación, no porque no existiera en código --- ## Pendientes activos (consolidado de minutas anteriores) ### 🔴 Críticos / sin bloqueante - [x] **`notifications.service.ts`** — todos los fixes aplicados (guard en `connect()`, `removeAllListeners()` en `closeConnection()`, arrow properties `onStorage`/`onBeforeUnload`, `channel?.close()`) - [ ] **F7 — DAU/MAU con endpoints correctos** (`stats-metrics.component.ts`) — pendiente desde 20260702: - Usar `GET /api/metrics/dau?days=30` para DAU real (unique users por día) - Usar `GET /api/metrics/mau` para MAU real (últimos 12 meses) - Ambos endpoints funcionan, no hay bloqueante de backend ### 🟠 Desarrollo pendiente - [ ] **Catálogo de playbooks para Katia** — pendiente desde 20260629: - Crear lógica para obtener catálogo desde el API - Actualizar el MD que usa Katia por canal (campos: título, autor, url, precio) - [ ] **Fixes de robustez `api-nodejs-mongo`** — pendiente desde 20260702: - Cache `Map()` sin TTL/límite en `controllers/ai-sherpa/vectorstore.js:15` - Límite de `body-parser` (50 MB global) — restringir por ruta en `index.js:117–118` - `uncaughtException` que nunca termina el proceso (`index.js:12–17`) — enmascara leaks reales ### 🔵 Cuando se priorice (sin bloqueante técnico) - [ ] **Backend: `GET /api/metrics/users/new` y `/users/inactive`** — queries simples contra `perfil.registro`/`perfil.ultimo_acceso`, patrón ya en `PbStatsModel` - [ ] **Backend: `GET /api/metrics/users/top`** — agregación en `pb_activity_playbook`/`pb_activity_user` + enriquecer con `profileUser()` - [ ] **Producto + Backend: capa de auth/rol** antes de exponer actividad individual de usuarios en la UI (hoy ningún endpoint Node la tiene) - [x] **`ms-icon-google`** — validado, íconos de rally renderizan correctamente ### ⏳ Bloqueados / en espera - [x] **Registro con correo (`addUserValid` de `admin.php`)** — resuelto ### 🗓️ Evaluación futura (no hay acción ahora) - [ ] Fase 3 — performance SmartPlaybooks: - Lazy loading de rutas (NgModule por página — 3–5 días) - Extraer Quill.js del bundle global - Stripe con `defer` en staging - Angular Universal / SSR (decisión de infraestructura) - [ ] Retomar `shared`/`shares_count` en `getEngagementMetrics` — requiere nueva migración; descartada la anterior ### 🏟️ Rebelocity Club — pendientes identificados hoy **Quick wins (sin bloqueante, bajo esfuerzo):** - [ ] **F-01** — Poblar catálogo de Temas de Foros por canal (hoy vacío — bloquea navegación y creación de hilos) - [ ] **C-02/C-03** — Unificar taxonomía de Clasificados: categorías al publicar ≠ categorías al filtrar; ambas son de RRHH, necesitan ser deportivas - [ ] **C-06** — Agregar CTA "Publicar anuncio" visible en `/clasificados` (hoy solo accesible por menú de cuenta) - [ ] **F-05** — Typo "elminar" → "eliminar" en diálogo de borrado de tópico - [ ] **F-04/B-07** — Fix fallback de imágenes: placeholder motivacional aparece en lugar de imagen rota **Medio plazo:** - [ ] **C-04** — Galería multi-foto en Clasificados (3–8 imágenes; crítico para marketplace deportivo) - [ ] **P-01/P-02** — "Sexo" → "Género" + implementar "Rol en el ecosistema" (Atleta/Coach/Club/Organizador/Marca) - [ ] **D-01** — Filtro de Disciplina en el Directorio - [ ] **C-05** — Separar Empleos de Clasificados (módulo o pestaña propia) **Estructural (requiere decisión Victor/producto):** - [ ] **MT-01** — Aislamiento de datos por canal en todos los módulos (Clasificados, Foros, Directorio) — bloqueante del piloto - [ ] **Points v2 — Clearing House** — registro de transacción presencial en comercio + liquidación/settlement (spec Draft, sin tablas ni endpoint) - [ ] **Points v2 — gating de beneficios por tier** en otros módulos (descuentos automáticos, cuota KatIA) — solo aplica hoy en canje de recompensas - [ ] **Points v2 — regla legacy vs. v2** — definir si plan FREE/BASIC/BASIC_PRO convive con tiers o se reemplaza (decisión de producto pendiente) --- --- ## EJE 2 — Rendimiento MasterPlaybooks (trabajo de esta sesión) ### ✅ Aplicados hoy - **R01 — Lector pre-fetch eager** (`reader-view-simple.component.ts`): `loadPlaybookItems()` disparaba 1 HTTP por capítulo simultáneamente al abrir el lector. Ahora los IDs se encolan y se pre-cargan con `setTimeout` escalonado (3 s de retardo inicial + 400 ms entre peticiones). Sin cambio en comportamiento de lectura. - **R01 — Catálogo `trackBy`** (`data-view.component.html` / `.ts`): ambos `*ngFor` usan `trackBy: trackById` para que Angular no destruya y recree los nodos al cambiar bindings de hover. - **R04 — "53h 7m SESIÓN PROMEDIO"** (`stats.service.ts` → `formatDuration()`): sesiones > 12 h ahora muestran "N/A". Verificado en browser: ✅ - **R04 — "$null USD"** (`playbook-preview.component.html`): price check corregido a `(playbook?.price && playbook?.price!=='0')` para evitar interpolación de `null`. - **R05 — Búsqueda estado contradictorio** (`store-playbooks.component.ts`): `validNoResults` filtraba `homeList` (secciones) por título de sección — nunca coincidía con el término buscado → siempre `true` → "No se encontraron resultados" aparecía aunque hubiera tarjetas visibles. Fix: `sectionResultsMap: Map` acumula `hasResults` por sección (vía `onResultsStatus()`). `validNoResults` ahora es `true` solo si hay filtro activo Y ninguna sección reporta resultados. - **R06 — Modal de checkout con login redundante** (`playbook-preview.component.ts`): al abrir el modal de compra con sesión activa, siempre mostraba el paso de login (tabCheckoutSelector reseteaba a 0 al cerrar). Fix: si hay sesión, abre en paso 1 (términos) con nombre y correo precargados desde la sesión. - **R04 — URL con ID numérico** (`store-playbooks.component.ts`, `playbook-preview.component.ts`, `data-view.component.ts`, `reader-view-simple.component.ts`): la URL al abrir un playbook mostraba el ID interno (ej. `/playbook/71185`). Los slugs ya estaban guardados en `pb_about.url`. Fix: navegación usa `item.url || item.id`; el lector detecta si el param es slug o numérico y envía el campo correcto al backend (`url` o `id`). Backend ya soportaba ambos. ### ⏳ Identificados, pendientes de fix - **R01 (raíz mayor)**: `DataViewComponent` y tarjetas sin `ChangeDetectionStrategy.OnPush` + catálogo sin virtual scroll. Requiere más trabajo. - **R02**: Quill.js en `scripts[]` de `angular.json` bloquea parse síncrono. Fix: mover a import dinámico en los módulos que lo usan. ### — No es bug - **Métricas escuchado/descargado vacías**: "Sin datos disponibles" es el estado correcto en este entorno — no hay audiobooks ni materiales con registros de actividad. ## NEXTs - **R01 (raíz mayor)** — `ChangeDetectionStrategy.OnPush` en `DataViewComponent` + virtual scroll en catálogo - **R02** — Mover Quill.js de `angular.json` `scripts[]` a import dinámico - **F7** — Conectar `GET /api/metrics/dau` y `/mau` en `stats-metrics.component.ts`