Club de Recompensas — Misiones
Requisitos de acceso
- Permiso (módulo):
viewRewardsProgram(para leer) /manageRewardsMissions(para crear/editar/activar/recalcular) - Licencia/Feature:
REWARDS_CLUB - Contenedor del menú: GENERAL → grupo Club de Recompensas
Qué es / cuándo usar
Gestiona las misiones del club: reglas orientadas a eventos que, cuando se cumplen, otorgan una recompensa (activo + valor) y/o puntos. El listado es en cards con filtros por estado, frecuencia y evento; la creación/edición usa un wizard de 4 pasos (Trigger → Identidad → Recompensa → Vigencia).
Úsalo para diseñar la gamificación: "primera orden paga X", "login diario da Y puntos", "invertir en crowdfunding da Z", etc. El catálogo cubre 28 eventos soportados, agrupados por categoría (Financiero, Registro & KYC, Referido, Crowdfunding, Marketplace & NFT, Staking, Volumen & Streak, Cambio de Nivel).
Pre-condiciones
- Permiso:
viewRewardsProgrampara leer;manageRewardsMissionspara editar (permiso doble: enum CPM + módulo dinámico en la DB). - Licencia/Feature:
REWARDS_CLUB. - Dependencias de otras pantallas: el activo de recompensa debe existir; si la misión no define uno, el payout usa el activo predeterminado del Programa. Para que las misiones con
missionPointscuenten para el nivel, el Programa debe usar la métricaPOINTS.
Paso a paso
- Accede al menú Club de Recompensas → Misiones (
/rewards-club/missions). - Filtra por estado (todas/activas/inactivas), frecuencia, evento o texto libre.
- Haz clic en Nuevo para abrir el wizard.
- Paso 1 – Trigger: elige el evento en el catálogo (tabs por grupo + cards explicativos). Aplica ejemplos de
condition_jsono edita las condiciones campo a campo. - Paso 2 – Identidad: nombre (genera el
code/slug automáticamente), descripción, ícono. - Paso 3 – Recompensa: activo, valor, puntos, frecuencia y caps anti-fraude.
- Paso 4 – Vigencia: fechas, "requiere usuario aprobado", nivel mínimo.
- Guarda. Para reaplicar la regla a eventos pasados, usa Recalcular.
Campos
| Campo | Qué es | ¿Obligatorio? | Efecto en el sistema/backend |
|---|---|---|---|
Evento (event) | Disparador de la misión (1 de los 28 del catálogo) | Sí | Define cuándo se evalúa la misión (ej.: DEPOSIT_CONFIRMED, ORDER_EXECUTED, USER_LOGIN_DAILY). |
Condiciones (condition) | Filtros específicos del evento | No | JSON editable campo a campo (ej.: thresholdFiat, minAmountFiat, everyN, assetFilter). Restringe cuándo la misión paga. |
Nombre (name) / Código (code) | Nombre mostrado y slug único | Sí | El code se genera como slug a partir del nombre (en la creación) y es estable entre replays — base de la idempotencia. |
Ícono (icon) | Ícono del card | No | Material Icons; quick-picker con sugerencias. |
Activo de recompensa (rewardAssetId) | Activo pagado al completar | Sí en el wizard (paso 3) | Si está vacío en el modelo final, el payout usa el defaultRewardAsset del Programa. |
Valor (rewardAmount) | Cuánto se paga | Sí | String BigNumber; el paso 3 exige > 0. |
Puntos (missionPoints) | Puntos otorgados al completar | No | Entero ≥ 0 (default 0). Cuentan para el nivel cuando el Programa usa la métrica POINTS. |
Frecuencia (frequency) | Cadencia de pago | Sí | ONCE_PER_USER (1x en la vida), ONCE_PER_DAY, ONCE_PER_MONTH, EVERY_N_OCCURRENCES (paga cada N — requiere everyN). |
Cada N (everyN) | N de ocurrencias para pagar | Condicional | Obligatorio cuando la frecuencia es EVERY_N_OCCURRENCES. |
Máx. por usuario (maxPerUser) | Techo absoluto por usuario | No | undefined = ilimitado (aún limitado por la frecuencia). |
Cap anti-fraude/usuario/día (maxPayoutsPerUserPerDay) | Máx. de payouts en 24h por usuario en esta misión | No | 0 = sin límite. Recomendado > 0 en misiones event-driven que se disparan repetidamente. |
Vigencia (activeFrom / activeTo) | Ventana de validez de la misión | activeFrom sí | Fuera de la ventana la misión no paga. |
Requiere usuario aprobado (requiresApprovedUser) | Solo paga usuarios APPROVED | No (default true) | Cuando está activado, el payout solo ocurre para usuarios con status === 'APPROVED'. |
Nivel mínimo (lockedUntilTier) | Restringe la misión a un nivel o superior | No | La misión solo se dispara para usuarios que hayan alcanzado el nivel indicado. |
Activa (isActive) | Activa/desactiva la misión | — | Toggle inline en el listado. |
Acciones y modales
- Guardar (wizard):
POST(nueva) oPUT(edición) en/v1/rewards-club/admin/missions. Requiere step-up (contraseña + MFA).missionPointsse normaliza a entero ≥ 0. - Toggle activa/inactiva:
PATCH .../missions/:id/toggle. En error, el toggle se revierte. - Recalcular:
POST .../missions/:id/recalculate. Pregunta si es para todos los usuarios o un userId específico, y muestra{evaluated, payoutsTriggered}al final. Requiere step-up (el interceptor responde al challenge 428 automáticamente). Es la herramienta de recompute proactivo: reevalúa la misión contra eventos ya capturados.
Reglas de negocio / precauciones
Atención
- Las misiones event-driven que pueden dispararse muchas veces deben tener
maxPayoutsPerUserPerDay > 0para contener abuso/bot. - El
codees el ancla de idempotencia — no cambies el código de una misión en producción, pues los replays/recálculos pueden duplicar concesiones. missionPointssolo influye en el nivel cuando el Programa usa la métricaPOINTS. Con métrica financiera, los puntos son solo informativos.
Irreversible
- Recalcular puede disparar payouts reales retroactivos. Revisa el alcance (todos vs. un usuario) antes de confirmar; la operación otorga recompensas reales.
- Valores financieros:
rewardAmountes un string BigNumber — sin redondeo. - Idempotencia: los payouts vía FinLib son idempotentes por
externalId; el errorE00021("already processed") es éxito (concesión ya aplicada), no fallo — por eso el recompute proactivo es seguro contra duplicación. - Estado APPROVED: con
requiresApprovedUseractivado, solo los usuarios aprobados reciben.
Ejemplos
Escenario 1 — Primera orden pagada en token (1x por usuario)
- Trigger:
ORDER_EXECUTED. - Identidad: "Primera orden" (code
PRIMERA_ORDEN). - Recompensa: activo tBRL, valor
5,missionPointsopcional. - Frecuencia:
ONCE_PER_USER. - Vigencia: a partir de hoy;
requiresApprovedUseractivado. - Guarda (step-up). Cada usuario aprobado lo recibe una vez en la vida.
Escenario 2 — Login diario da puntos (club por puntos)
- Trigger:
USER_LOGIN_DAILY. - Recompensa:
missionPoints = 50; el valor monetario puede ser0. - Frecuencia:
ONCE_PER_DAY;maxPayoutsPerUserPerDay = 1. - Guarda. Con el Programa en métrica
POINTS, los puntos alimentan el nivel.
Escenario 3 — Cada 10 órdenes, bono
- Trigger:
ORDER_EXECUTED, condicióneveryN: 10. - Frecuencia:
EVERY_N_OCCURRENCES,everyN = 10. - Recompensa: activo + valor del bono.
- Guarda. La misión acumula ocurrencias y paga cada 10.