Club de Recompensas — Programa
Requisitos de acceso
- Permiso (módulo):
viewRewardsProgram(para leer) /manageRewardsProgram(para guardar) - Licencia/Feature:
REWARDS_CLUB - Contenedor del menú: GENERAL → grupo Club de Recompensas
Qué es / cuándo usar
La pantalla Programa es el singleton de configuración del Club de Recompensas (RCS) para el tenant. Aquí defines la identidad del club, cómo se calcula el nivel (tier) del usuario (métrica + ventana), los caps anti-fraude globales, los pools de pago (carteras-casa por activo) y las cotizaciones manuales usadas cuando no hay price-feed automático.
Úsalo al montar el club por primera vez y siempre que necesites cambiar la regla macro (ej.: pasar de "volumen de depósitos" a "puntos de misión", pausar payouts en emergencia, abastecer/monitorear el pool de pago).
Requisitos previos
- Permiso:
viewRewardsProgrampara abrir;manageRewardsProgrampara que los controles queden editables y el Guardar funcione (permiso doble: enum CPM + módulo dinámico en la DB). - Licencia/Feature:
REWARDS_CLUBhabilitada en la licencia del tenant (Vault). Si está deshabilitada, el grupo ni siquiera aparece en el menú. - Dependencias de otras pantallas: los niveles se crean en Niveles y las misiones en Misiones. Cuando la métrica de nivel es
POINTS, es necesario tener misiones que otorguen puntos.
Paso a paso
- Accede al menú Club de Recompensas → Programa (
/rewards-club/program). - Define el Estado (Activo/Pausado) y el nombre del programa.
- Elige la Métrica del nivel (volumen de depósitos, volumen negociado o puntos de misión) haciendo clic en el card correspondiente.
- Elige la Ventana del nivel (vitalicia, últimos 90 días o año corriente).
- Configura el activo predeterminado de recompensa y el fiat de referencia.
- Ajusta los caps anti-fraude (por día, por usuario/día).
- Registra los pools de pago (una cartera-casa por activo) y, si es necesario, las cotizaciones manuales.
- Haz clic en Guardar — la mutación requiere step-up (ver abajo).
Campos
| Campo | Qué es | ¿Obligatorio? | Efecto en el sistema/backend |
|---|---|---|---|
Estado (status) | ACTIVE o PAUSED | Sí | Activo: los eventos disparan payouts y el tier engine recomputa en ciclo. Pausado: los eventos continúan siendo auditados, pero las misiones no pagan; el tier engine sigue funcionando. Usa Pausado en emergencias. |
Métrica del nivel (tierMetric) | Cómo se calcula el nivel | Sí | DEPOSIT_VOLUME (suma de depósitos confirmados en fiat), TRADE_VOLUME (volumen negociado en fiat) o POINTS (puntos de misión). Valores canónicos de rcs-lib — definen qué suma el engine para posicionar al usuario en un nivel. |
Ventana del nivel (tierWindow) | Período considerado en la métrica | Sí | LIFETIME (acumulado vitalicio — nunca pierde el nivel), ROLLING_90D (ventana rodante de 90 días — puede perder el nivel), CALENDAR_YEAR (se resetea el 1 de enero). |
Activo predeterminado de recompensa (defaultRewardAsset) | Token/activo usado cuando la misión no define uno | No | Cuando una misión no tiene rewardAssetId, el payout usa este activo. Hace el token de recompensa configurable y modular (ej.: tBRL, MID, USDC) — sin atarlo al fiat. |
Fiat de referencia (referenceFiat) | Moneda de visualización de la métrica financiera | Condicional | Usado para mostrar la métrica cuando es DEPOSIT_VOLUME/TRADE_VOLUME. Cuando la métrica es POINTS, la UI muestra en "pts" e ignora este campo. Reemplaza el fiatRef legado (reflejado para retrocompat). |
Cap global por día (globalMaxPayoutsPerDay) | Límite anti-bot de payouts/24h en todo el programa | No | 0 = sin límite. |
Cap por usuario/día (globalMaxPayoutsPerUserPerDay) | Límite anti-bot de payouts/24h por usuario (todas las misiones) | No | 0 = sin límite. Capa de protección independiente del cap por misión. |
Pools de pago (pools[]) | Carteras-casa que guardan el saldo de payout por activo | Sí (para pagar) | Cada pool tiene assetId, walletAddress, balance (saldo) y minBalanceAlert (límite de alerta). La barra de saldo se pone roja cuando balance ≤ minBalanceAlert. Sin pool con saldo, el activo no puede pagar. |
Cotizaciones manuales (manualQuotes) | Override de cotización activo → fiat de referencia | No | Map ACTIVO → valor (1 unidad del activo = N de fiat). Usado por el QuoteService del RCS cuando no hay price-feed automático para ese par. Las líneas en blanco se ignoran al guardar. |
El mapa NFTs por nivel (
tierNftAssets) aparece aquí solo como lectura (retrocompat con programas legados). La generación del NFT de cada nivel se movió a la pantalla Niveles (botón "Generar NFT" por fila).
Acciones y modales
- Guardar: persiste el programa via
PUT /v1/rewards-club/admin/program. Requiere step-up (X-Step-Up-Token: re-autenticación contraseña + MFA, ventana de 5 min). Si el token expira, el gateway responde428 Step-up requiredy el interceptor solicita nueva verificación. - Agregar/Eliminar pool y Agregar/Eliminar cotización manual: manipulan las listas localmente; solo se persisten al Guardar.
Reglas de negocio / precauciones
Atención
- Pausar el programa no detiene la captura de eventos (la auditoría continúa) — solo suspende los pagos. Útil para contener un incidente sin perder el historial.
- La elección entre
LIFETIMEy ventanas rodantes cambia profundamente el comportamiento: enLIFETIMEel usuario nunca pierde el nivel; enROLLING_90D/CALENDAR_YEARpuede perder el nivel. - Cambiar la métrica a
POINTSsin misiones que otorguen puntos configuradas deja a todos en el nivel base. Asegúrate de tener misiones conmissionPoints > 0primero. - Mantén los pools abastecidos: un saldo por debajo de la alerta señala riesgo de que los payouts fallen por falta de fondos en la cartera-casa.
- Valores financieros: saldos, alertas y cotizaciones se transmiten como string BigNumber — sin redondeo; trata como BigNumber antes de cualquier aritmética.
- Idempotencia: los payouts subyacentes pasan por FinLib, que es idempotente por
externalId. El código de errorE00021("already processed") significa éxito (ya liquidado), no fallo.
Ejemplos
Escenario 1 — Club de captación por volumen de depósitos (vitalicio)
Objetivo: premiar a quienes más depositan, sin nunca degradar de nivel.
- Estado = Activo.
- Métrica = "Volumen de depósitos".
- Ventana = "Vitalicia".
- Fiat de referencia = BRL.
- Activo predeterminado de recompensa = tBRL.
- Registra un pool tBRL con la cartera-casa y un
minBalanceAlertcómodo. - Guarda (step-up). Los thresholds de cada nivel (en BRL) se definen en Niveles.
Escenario 2 — Club de engagement por puntos (rodante 90 días)
Objetivo: premiar la actividad continua; quien para, baja.
Escenario 3 — Contener un incidente sin perder el historial
Sospecha de abuso/bot disparando payouts:
- Abre Programa y cambia el Estado a Pausado, guarda (step-up).
- Los eventos continúan siendo capturados y auditados, pero ninguna misión paga.
- Ajusta los caps anti-fraude (
globalMaxPayoutsPerUserPerDay > 0) y revisa las misiones sospechosas. - Vuelve el estado a Activo cuando sea seguro.