--- asset_id: MIN-EL-Jesus-20260625-v01 version: v01 tipo: MIN — Minuta owner: Jesus sherpa: Jess (SherpaX de Jesus) ratificador: Jesus fecha: 2026-06-25 intellibank: IB-EL-EmpowerLabs subbank: EQ-EL-Equipo --- # Minuta del Día · Jesús · 2026-06-25 ## Qué se hizo ### API Points · `api-nodejs-mongo` - **`GET /api/points/balance` — param `progress`:** agregado parámetro opcional `?progress=true`. Cuando está activo, incluye en la respuesta el objeto `progress` (lifetime, currentTier, nextTier, porcentaje) usando `TierService.getTierProgress`. Ambas llamadas corren en paralelo con `Promise.all`. - **Bug analizado — `referral_complete` vía `/award`:** se identificó que `POST /api/points/award` con `actionKey: 'referral_complete'` no valida la existencia de un referido real. La protección correcta está en `/api/points/referrals/reward-complete` → `ReferralService.rewardReferralComplete`. Se decidió no modificar el motor genérico; el flujo correcto sigue siendo el endpoint de referidos. - **`rewardReferralComplete` — caso comercio cubierto:** `ReferralService.rewardReferralComplete` extendido para manejar referidos por comercio. Si no encuentra referral de tipo `user`, busca en `affiliations` por `merchant_id`. Por ahora los puntos se otorgan al usuario referido (no al comercio) porque `merchant_id` referencia `genniux_rch.empresa`, que no tiene FK en `puesto`. Queda `TODO` inline para cuando se resuelva la representación del comercio como usuario. ## Decisiones - No se bloqueó `referral_complete` en el endpoint genérico `/award` — se deja el flujo correcto vía `/referrals/reward-complete` que ya tiene la validación de negocio. - En referral por comercio, los puntos van al usuario referido (no al comercio) hasta que `merchant_id` tenga un usuario representante en `puesto`. ### Admin canales · `admin-canales` (smartplaybooks) - **Tab Redes sociales rediseñado:** sustituido el `tempForm` genérico por lista compacta (icono, clave, URL truncada, badge Visible/Oculto, botones editar/eliminar) + modal `#dgSocial` para agregar y editar. Cada ítem del array `actChannel.social` se edita como copia; los cambios se aplican solo al guardar. - **Campos del modal social:** Clave (`model`) + Visibilidad en fila; Icono (URL) + preview; URL/Enlace. - **Tab Soporte:** agregado campo fijo **Página de ayuda** (`pg_help`). Nueva sección **Canales de soporte** con la misma lista compacta + modal `#dgSupport` (Nombre, Visibilidad, Icono, URL). Botón `+ Agregar canal`. - **`DomainConfig` (`config-app.service.ts`):** añadido `support: Array` (declaración + `this.support = []`) y activado `'support'` en `propsColor`. - **Métodos TS:** `openSocialModal`, `saveSocialItem`, `removeSocialItem`; `openSupportModal`, `saveSupportItem`, `removeSupportItem`; `visibilityOptions`. ### Pie de página · `footer-bar` (smartplaybooks) - **Nuevo diseño implementado:** reemplazado el layout `ms-row`/`ms-col` del footer por estructura `div.footer-wrap > div.footer-inner` con tres bloques: logo (`ft-logo`) | links (`ft-nav`) | iconos sociales + copyright (`ft-right`). - **Nav links:** `Ayuda` (condicionado a `domainConfig?.pg_help`) y `Política de Privacidad` (`domainConfig?.pg_policy`), separados por `·`. - **Copyright:** `© {{ currentYear }} {{ domainConfig?.app_info }}` — año dinámico + nombre de la app desde `domainConfig`. - **Iconos sociales:** reutilizados de `socialList` dentro de `.ft-social-icons` con bordes redondeados estilo mockup. - **Colores:** `domainConfig?.color_bg_footer` y `domainConfig?.color_text_footer` en todos los elementos — agnóstico de app. - **Mobile (≤480px):** columna centrada (logo, nav); `ft-right` con `justify-content: space-between` — iconos a la izquierda, copyright a la derecha. - **`margin-top: 50px`** conservado en `.footer-wrap`. - **TS:** agregado `currentYear = new Date().getFullYear()`; `socialList` vaciado (los iconos vienen de `domainConfig?.social`). - **`ft-nav` con support dinámico:** los ítems de `domainConfig?.support` visibles se renderizan como links antes de "Ayuda" y "Privacidad". Orden: `[support items] · Ayuda · Privacidad`. - **`pg_help` confirmado** en `DomainConfig` (ya existía). `propsColor` actualizado con `pg_help` y `support`. - **Optimización del componente:** eliminados `moment` (~67kb bundle), `Router`/`goRoute` (dead code), `ngAfterViewInit` vacío. `get domainConfig` convertido a propiedad reactiva via `config$` (evita leer localStorage en cada CD cycle). Ambas subscriptions (`config$` + `breakpointObserver`) protegidas con `takeUntil(destroyed$)` + `ngOnDestroy`. `socialList: any[]` tipado correctamente (resuelve 3 errores TS). ### Playbook card · `playbook-card` (smartplaybooks) - **`#tempInfo` hover — `author_alt`:** lógica de autor en tarjeta hover: - Resumen + `author_alt` → fila 1 "Autor: author_alt" (icono `apartment`) + fila 2 "Resumido por: autor" (icono `edit_note`) - Resumen sin `author_alt` → solo "Resumido por: autor" - Otros tipos → solo "Autor: autor" - **Naming:** el campo en BD y en el objeto es `author_alt` (no `autor_alt`). ### Field updater · `field-updater` (smartplaybooks) - **`author_alt` en `campo=='author'`:** eliminado bloque duplicado del Resumen; el bloque único muestra label dinámico "Resumido por" / "Autor". Condicionado a `actividad.type=='Resumen'`, agrega input "Autor original" → `changeValuesFU('author_alt', $event)`. - **`changeValuesFU`:** nuevo case `'author_alt'` → `this.actividad.author_alt = value`. - **`update()` — `panel-detail`:** cuando `campo=='author'` y `actividad.type=='Resumen'`, llama `updDetailPlayBook(act, 'author_alt')`. ### Manage Playbooks · `manage-playbooks` (smartplaybooks) - **`dgSettingsPb` — `author_alt`:** en el bloque de autor del modal de ajustes, label cambia a "Resumido por" cuando `actPb.type=='Resumen'`. Input adicional "Autor original" (`author_alt`) visible solo en Resumen. Sin cambios en TS — `changesValuesPlaybook` default ya asigna `actPb[row]=val` y `updPlaybook()` envía el objeto completo. - **Label dinámico:** el título del bloque de autor cambia a "Resumido por" cuando el playbook es tipo Resumen. ## NEXTs ### API Points - Resolver cómo representar el comercio (`genniux_rch.empresa`) como usuario en `puesto` para poder otorgarle puntos en `referral_complete`.