miinventario-v2/docs/01-epicas/MII-014-referidos.md
rckrdmrd c24f889f70
Some checks failed
Build / Build Backend (push) Has been cancelled
Build / Build Mobile (TypeScript Check) (push) Has been cancelled
Lint / Lint Backend (push) Has been cancelled
Lint / Lint Mobile (push) Has been cancelled
Test / Backend E2E Tests (push) Has been cancelled
Test / Mobile Unit Tests (push) Has been cancelled
Build / Build Docker Image (push) Has been cancelled
[MIINVENTARIO] feat: Add exports, reports, integrations modules and CI/CD pipeline
- Add exports module with PDF/CSV/Excel generation
- Add reports module for inventory analytics
- Add POS integrations module
- Add database migrations for exports, movements and integrations
- Add GitHub Actions CI/CD workflow with Docker support
- Add mobile export and reports screens with tests
- Update epic documentation with traceability
- Add deployment and security guides

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 06:06:34 -06:00

452 lines
13 KiB
Markdown

# MII-014: Sistema de Referidos
---
id: MII-014
type: Epic
status: Completado
priority: P1
phase: 4
story_points: 21
created_date: 2026-01-10
updated_date: 2026-01-13
simco_version: "4.0.0"
---
## Metadata
| Campo | Valor |
|-------|-------|
| **ID** | MII-014 |
| **Nombre** | Sistema de Referidos |
| **Fase** | 4 - Crecimiento |
| **Prioridad** | P1 |
| **Story Points** | 21 |
| **Estado** | Completado |
---
## 1. Descripcion
Implementar un sistema de referidos multinivel que incentive el crecimiento organico, con recompensas justas y mecanismos anti-fraude.
### Objetivo
Crear un motor de crecimiento viral donde usuarios existentes inviten a nuevos usuarios y ambos se beneficien.
---
## 2. Requerimientos Relacionados
| RF | Descripcion | Prioridad |
|----|-------------|-----------|
| FR-110 | Codigo de referido unico por usuario | P0 |
| FR-111 | Registro atribuido (nuevo usuario con codigo) | P0 |
| FR-112 | Condicion de recompensa (compra + primer inventario) | P0 |
| FR-113 | Recompensa break-even (1 credito por referido) | P0 |
| FR-114 | Multinivel configurable (niveles, %, limites) | P2 |
| FR-115 | Anti-fraude (duplicados, topes, holds) | P0 |
| FR-116 | Panel de referidos (invitaciones, referidos, creditos) | P1 |
---
## 3. Criterios de Aceptacion
### AC-001: Codigo Unico
```gherkin
DADO que soy usuario registrado
CUANDO veo mi perfil o panel de referidos
ENTONCES tengo un codigo unico para compartir
Y puedo copiarlo o compartirlo facilmente
```
### AC-002: Registro con Codigo
```gherkin
DADO que soy nuevo usuario
CUANDO me registro con un codigo de referido
ENTONCES quedo vinculado a quien me invito
Y ambos podemos ver la relacion
```
### AC-003: Condiciones de Recompensa
```gherkin
DADO que invite a un usuario
CUANDO el referido completa:
1. Primera compra de creditos
2. Primer inventario exitoso
ENTONCES recibo mi recompensa
Y el referido tambien recibe bonus
```
### AC-004: Recompensa de 1 Credito
```gherkin
DADO que mi referido cumplio las condiciones
CUANDO se activa la recompensa
ENTONCES recibo 1 credito en mi wallet
Y veo la transaccion en mi historial
```
### AC-005: Panel de Referidos
```gherkin
DADO que he invitado usuarios
CUANDO veo mi panel de referidos
ENTONCES veo:
- Mi codigo de referido
- Lista de referidos y su status
- Creditos ganados totales
- Referidos pendientes de activacion
```
### AC-006: Anti-fraude
```gherkin
DADO que el sistema detecta comportamiento sospechoso
CUANDO hay indicios de fraude
ENTONCES las recompensas quedan en hold
Y se notifica para revision manual
Y no se entregan creditos hasta verificar
```
---
## 4. Tareas Tecnicas
| ID | Tarea | Estimacion | Estado |
|----|-------|------------|--------|
| T-001 | Crear modulo referrals en NestJS | 1 SP | Completado |
| T-002 | Implementar generador de codigos | 1 SP | Completado |
| T-003 | Crear entidades ReferralCode, ReferralTree | 2 SP | Completado |
| T-004 | Implementar vinculacion en registro | 2 SP | Completado |
| T-005 | Crear motor de condiciones | 3 SP | Completado |
| T-006 | Implementar sistema de recompensas | 2 SP | Completado |
| T-007 | Crear reglas anti-fraude | 3 SP | Completado |
| T-008 | Implementar panel mobile | 3 SP | Completado |
| T-009 | Crear compartir codigo | 1 SP | Completado |
| T-010 | Implementar multinivel (P2) | 3 SP | Completado |
---
## 5. Modelo de Datos
### Tabla: referral_codes
```sql
CREATE TABLE referral_codes (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES users(id) UNIQUE,
code VARCHAR(10) UNIQUE NOT NULL,
total_referrals INT DEFAULT 0,
total_activated INT DEFAULT 0,
total_rewards DECIMAL(12,4) DEFAULT 0,
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMP DEFAULT NOW()
);
```
### Tabla: referral_tree
```sql
CREATE TABLE referral_tree (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
referrer_id UUID REFERENCES users(id),
referred_id UUID REFERENCES users(id) UNIQUE,
referral_code_id UUID REFERENCES referral_codes(id),
level INT DEFAULT 1, -- Para multinivel
status VARCHAR(20) DEFAULT 'PENDING',
first_purchase_at TIMESTAMP,
first_session_at TIMESTAMP,
activated_at TIMESTAMP,
created_at TIMESTAMP DEFAULT NOW()
);
-- Status: PENDING, PURCHASE_DONE, ACTIVATED, FRAUD_HOLD, REJECTED
```
### Tabla: referral_rewards
```sql
CREATE TABLE referral_rewards (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
referral_id UUID REFERENCES referral_tree(id),
beneficiary_id UUID REFERENCES users(id),
reward_type VARCHAR(20), -- 'REFERRER', 'REFERRED', 'LEVEL_2', etc
amount DECIMAL(12,4),
status VARCHAR(20) DEFAULT 'PENDING',
released_at TIMESTAMP,
hold_reason VARCHAR(100),
created_at TIMESTAMP DEFAULT NOW()
);
-- Status: PENDING, RELEASED, HELD, CANCELLED
```
### Tabla: referral_fraud_signals
```sql
CREATE TABLE referral_fraud_signals (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
referral_id UUID REFERENCES referral_tree(id),
signal_type VARCHAR(50),
signal_data JSONB,
severity VARCHAR(20), -- 'LOW', 'MEDIUM', 'HIGH'
reviewed BOOLEAN DEFAULT false,
reviewed_by UUID REFERENCES users(id),
reviewed_at TIMESTAMP,
created_at TIMESTAMP DEFAULT NOW()
);
```
---
## 6. Generador de Codigos
```typescript
function generateReferralCode(userId: string): string {
// Formato: 3 letras + 4 numeros (ej: MII-A1B2)
const letters = 'ABCDEFGHJKLMNPQRSTUVWXYZ'; // Sin I, O
const numbers = '0123456789';
let code = '';
for (let i = 0; i < 3; i++) {
code += letters[Math.floor(Math.random() * letters.length)];
}
for (let i = 0; i < 4; i++) {
code += numbers[Math.floor(Math.random() * numbers.length)];
}
return code; // ej: "ABC1234"
}
```
---
## 7. Motor de Condiciones
```typescript
interface ActivationConditions {
firstPurchase: boolean;
firstSession: boolean;
minPurchaseAmount?: number;
minSessionsCount?: number;
}
async function checkActivation(referralId: string): Promise<boolean> {
const referral = await this.referralRepo.findOne(referralId);
const conditions = getActivationConditions();
const checks = {
firstPurchase: referral.first_purchase_at !== null,
firstSession: referral.first_session_at !== null
};
// Verificar condiciones minimas
if (conditions.minPurchaseAmount) {
const totalPurchased = await this.getTotalPurchased(referral.referred_id);
checks.minPurchase = totalPurchased >= conditions.minPurchaseAmount;
}
const allMet = Object.values(checks).every(v => v);
if (allMet && referral.status === 'PURCHASE_DONE') {
await this.activateReferral(referralId);
}
return allMet;
}
async function activateReferral(referralId: string) {
const referral = await this.referralRepo.findOne(referralId);
// Verificar anti-fraude
const fraudSignals = await this.checkFraudSignals(referral);
if (fraudSignals.length > 0) {
await this.holdReferral(referralId, fraudSignals);
return;
}
// Liberar recompensas
await this.releaseRewards(referralId);
// Actualizar status
await this.referralRepo.update(referralId, {
status: 'ACTIVATED',
activated_at: new Date()
});
}
```
---
## 8. Reglas Anti-fraude
| Senal | Severidad | Accion |
|-------|-----------|--------|
| Mismo dispositivo | HIGH | Hold + revision |
| Mismo IP | MEDIUM | Hold si > 3 |
| Email temporal | MEDIUM | Hold |
| Patron de registro | HIGH | Hold + revision |
| Compra minima exacta | LOW | Monitor |
| Sesion artificial | HIGH | Bloquear |
```typescript
async function checkFraudSignals(referral: ReferralTree): Promise<FraudSignal[]> {
const signals: FraudSignal[] = [];
const referrer = await this.usersRepo.findOne(referral.referrer_id);
const referred = await this.usersRepo.findOne(referral.referred_id);
// Mismo dispositivo
if (referrer.device_fingerprint === referred.device_fingerprint) {
signals.push({
type: 'SAME_DEVICE',
severity: 'HIGH',
data: { fingerprint: referrer.device_fingerprint }
});
}
// Mismo IP
if (referrer.last_ip === referred.registration_ip) {
const sameIpCount = await this.countSameIPReferrals(referrer.id);
if (sameIpCount > 3) {
signals.push({
type: 'SAME_IP_MULTIPLE',
severity: 'MEDIUM',
data: { ip: referrer.last_ip, count: sameIpCount }
});
}
}
// Email temporal
if (isTemporaryEmail(referred.email)) {
signals.push({
type: 'TEMPORARY_EMAIL',
severity: 'MEDIUM',
data: { domain: referred.email.split('@')[1] }
});
}
return signals;
}
```
---
## 9. Endpoints API
| Metodo | Endpoint | Descripcion | Auth |
|--------|----------|-------------|------|
| GET | /referrals/my-code | Obtener mi codigo | JWT |
| GET | /referrals/stats | Estadisticas de referidos | JWT |
| GET | /referrals/list | Lista mis referidos | JWT |
| POST | /referrals/validate/:code | Validar codigo existe | No |
| GET | /referrals/rewards | Historial recompensas | JWT |
---
## 10. Pantallas Mobile
| Pantalla | Componentes |
|----------|-------------|
| **ReferralDashboard** | Codigo, stats, CTA compartir |
| **ReferralListScreen** | Lista referidos, status |
| **RewardsHistoryScreen** | Recompensas, timeline |
| **ShareCodeModal** | Codigo, opciones compartir |
---
## 11. UI del Panel
```
┌─────────────────────────────────────────┐
│ INVITA Y GANA │
├─────────────────────────────────────────┤
│ │
│ Tu codigo de invitacion: │
│ ┌─────────────────────────────────┐ │
│ │ ABC1234 │ │
│ │ [📋] │ │
│ └─────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────┐ │
│ │ 📤 COMPARTIR CODIGO │ │
│ └─────────────────────────────────┘ │
│ │
│ ───────────────────────────────────── │
│ │
│ TUS ESTADISTICAS │
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ 12 │ │ 8 │ │ 8.0 │ │
│ │Invitados│ │Activados│ │Creditos │ │
│ └─────────┘ └─────────┘ └─────────┘ │
│ │
│ ───────────────────────────────────── │
│ │
│ REFERIDOS RECIENTES │
│ │
│ 👤 Juan P. ✅ Activado +1.0 │
│ Hace 2 dias │
│ │
│ 👤 Maria L. ⏳ Pendiente │
│ Falta: primer inventario │
│ │
│ 👤 Carlos R. 💰 Compro │
│ Falta: primer inventario │
│ │
│ [Ver todos →] │
│ │
└─────────────────────────────────────────┘
```
---
## 12. Configuracion Multinivel (P2)
```yaml
referral_config:
levels:
- level: 1
reward_percent: 100 # 1 credito completo
max_rewards: null # Sin limite
- level: 2
reward_percent: 25 # 0.25 creditos
max_rewards: 10 # Max 10 nivel 2
- level: 3
reward_percent: 10 # 0.1 creditos
max_rewards: 5 # Max 5 nivel 3
anti_fraud:
same_device_action: "HOLD"
same_ip_threshold: 3
min_session_duration: 30 # segundos
reward_hold_hours: 24
```
---
## 13. Dependencias
### Entrada (Requiere)
- MII-002: Autenticacion (registro)
- MII-009: Wallet y Creditos (recompensas)
- MII-011/012/013: Pagos (primera compra)
- MII-005: Procesamiento IA (primera sesion)
### Salida (Bloquea)
- MII-015: Admin (moderacion de fraude)
---
## 14. Riesgos
| Riesgo | Probabilidad | Impacto | Mitigacion |
|--------|--------------|---------|------------|
| Fraude masivo | Alta | Alto | Anti-fraude robusto, holds |
| Abuso de creditos | Media | Medio | Limites, topes |
| Experiencia confusa | Media | Medio | UX clara, FAQs |
---
## 15. Referencias
- [REQUERIMIENTOS-FUNCIONALES.md](../00-vision-general/REQUERIMIENTOS-FUNCIONALES.md) - Seccion 5.12
- [VISION-PROYECTO.md](../00-vision-general/VISION-PROYECTO.md) - Modelo crecimiento
---
**Ultima Actualizacion:** 2026-01-10