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
- 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>
13 KiB
13 KiB
MII-009: Wallet y Creditos
id: MII-009 type: Epic status: Completado priority: P0 phase: 3 story_points: 13 created_date: 2026-01-10 updated_date: 2026-01-13 simco_version: "4.0.0"
Metadata
| Campo | Valor |
|---|---|
| ID | MII-009 |
| Nombre | Wallet y Creditos |
| Fase | 3 - Monetizacion |
| Prioridad | P0 |
| Story Points | 13 |
| Estado | Completado |
1. Descripcion
Implementar el sistema de wallet de creditos que permite a los usuarios consumir creditos por sesion de inventario, con registro transparente de costos y precios.
Objetivo
Crear un sistema de monetizacion justo y transparente basado en consumo, donde el usuario paga el doble del costo real de la IA.
2. Requerimientos Relacionados
| RF | Descripcion | Prioridad |
|---|---|---|
| FR-080 | Cartera de creditos por usuario/tienda | P0 |
| FR-081 | Consumo de creditos por sesion (configurable) | P0 |
| FR-082 | Motor de costos COGS IA (proveedor, frames, costo) | P0 |
| FR-083 | Regla de precio: 2x COGS IA | P0 |
| FR-084 | Transparencia: mostrar creditos y equivalencia MXN | P1 |
3. Criterios de Aceptacion
AC-001: Wallet de Usuario
DADO que soy un usuario registrado
CUANDO veo mi wallet
ENTONCES veo mi saldo de creditos
Y veo el equivalente aproximado en MXN
Y veo el historial de transacciones
AC-002: Consumo por Sesion
DADO que tengo creditos suficientes
CUANDO inicio una sesion de inventario
ENTONCES se reservan creditos estimados
Y al completar, se cobra el monto real
Y si falla, se liberan los creditos reservados
AC-003: Creditos Insuficientes
DADO que no tengo creditos suficientes
CUANDO intento iniciar una sesion
ENTONCES veo un mensaje indicando falta de saldo
Y me ofrecen comprar un paquete
Y no puedo continuar sin creditos
AC-004: Calculo de COGS
DADO que una sesion se proceso
CUANDO el sistema calcula el costo
ENTONCES registra:
- Proveedor de IA usado
- Numero de frames procesados
- Tokens/llamadas consumidas
- Costo en USD y MXN
AC-005: Precio = 2x COGS
DADO que el COGS de una sesion es X
CUANDO se calcula el precio al usuario
ENTONCES el precio es 2 * X
Y se muestra de forma transparente
AC-006: Transparencia
DADO que complete una sesion
CUANDO veo el detalle de consumo
ENTONCES veo:
- Creditos consumidos
- Costo base (COGS)
- Precio cobrado (2x)
- Equivalente en MXN
4. Tareas Tecnicas
| ID | Tarea | Estimacion | Estado |
|---|---|---|---|
| T-001 | Crear modulo credits en NestJS | 1 SP | Completado |
| T-002 | Implementar entidad CreditWallet | 1 SP | Completado |
| T-003 | Implementar transacciones atomicas | 2 SP | Completado |
| T-004 | Crear motor de COGS | 2 SP | Completado |
| T-005 | Implementar regla de pricing 2x | 1 SP | Completado |
| T-006 | Crear pantalla de wallet en mobile | 2 SP | Completado |
| T-007 | Implementar validacion pre-sesion | 1 SP | Completado |
| T-008 | Crear historial de transacciones | 2 SP | Completado |
| T-009 | Implementar jobs de reconciliacion | 1 SP | Completado |
5. Modelo de Datos
Tabla: credit_wallets
CREATE TABLE credit_wallets (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES users(id) UNIQUE,
balance DECIMAL(12,4) DEFAULT 0,
reserved DECIMAL(12,4) DEFAULT 0,
lifetime_credits DECIMAL(12,4) DEFAULT 0,
lifetime_spent DECIMAL(12,4) DEFAULT 0,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- balance: creditos disponibles
-- reserved: creditos reservados para sesiones en progreso
-- lifetime_credits: total creditos comprados
-- lifetime_spent: total creditos consumidos
Tabla: credit_transactions
CREATE TABLE credit_transactions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
wallet_id UUID REFERENCES credit_wallets(id),
type VARCHAR(20), -- 'PURCHASE', 'CONSUMPTION', 'REFUND', 'BONUS', 'REFERRAL'
amount DECIMAL(12,4) NOT NULL,
balance_after DECIMAL(12,4),
reference_type VARCHAR(50), -- 'PAYMENT', 'SESSION', 'REFERRAL_REWARD'
reference_id UUID,
metadata JSONB,
created_at TIMESTAMP DEFAULT NOW()
);
Tabla: cogs_records
CREATE TABLE cogs_records (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
session_id UUID REFERENCES inventory_sessions(id),
provider VARCHAR(50) NOT NULL,
frames_processed INT,
api_calls INT,
tokens_used INT,
cost_usd DECIMAL(10,6),
exchange_rate DECIMAL(10,4),
cost_mxn DECIMAL(10,4),
price_to_user DECIMAL(10,4), -- 2x cost_mxn
margin DECIMAL(10,4),
calculated_at TIMESTAMP DEFAULT NOW()
);
Tabla: pricing_rules
CREATE TABLE pricing_rules (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(100),
type VARCHAR(50), -- 'MULTIPLIER', 'FIXED', 'TIERED'
config JSONB,
is_active BOOLEAN DEFAULT true,
priority INT DEFAULT 0,
valid_from TIMESTAMP,
valid_until TIMESTAMP,
created_at TIMESTAMP DEFAULT NOW()
);
6. Motor de COGS
Calculo de Costo
interface COGSCalculation {
provider: string;
framesProcessed: number;
apiCalls: number;
tokensUsed: number;
// Costos
costPerFrame: number; // USD
costPerToken: number; // USD
fixedCost: number; // USD por sesion
// Totales
totalCostUSD: number;
exchangeRate: number; // USD/MXN
totalCostMXN: number;
// Precio usuario
multiplier: number; // 2x por defecto
priceToUser: number; // MXN
margin: number; // MXN
}
function calculateCOGS(session: InventorySession): COGSCalculation {
const provider = getActiveProvider();
const costs = provider.getCosts();
const totalCostUSD =
(session.framesProcessed * costs.perFrame) +
(session.tokensUsed * costs.perToken) +
costs.fixed;
const rate = getExchangeRate('USD', 'MXN');
const totalCostMXN = totalCostUSD * rate;
const multiplier = getPricingMultiplier();
const priceToUser = totalCostMXN * multiplier;
return {
provider: provider.name,
framesProcessed: session.framesProcessed,
tokensUsed: session.tokensUsed,
totalCostUSD,
exchangeRate: rate,
totalCostMXN,
multiplier,
priceToUser,
margin: priceToUser - totalCostMXN
};
}
7. Endpoints API
| Metodo | Endpoint | Descripcion | Auth |
|---|---|---|---|
| GET | /credits/wallet | Obtener wallet actual | JWT |
| GET | /credits/transactions | Historial transacciones | JWT |
| GET | /credits/balance | Solo balance | JWT |
| POST | /credits/reserve | Reservar para sesion | JWT |
| POST | /credits/consume | Consumir despues de sesion | JWT |
| POST | /credits/release | Liberar reserva | JWT |
| GET | /credits/estimate | Estimar costo sesion | JWT |
8. Pantallas Mobile
| Pantalla | Componentes |
|---|---|
| WalletScreen | Balance, equivalente MXN, botones |
| TransactionHistoryScreen | Lista transacciones, filtros |
| TransactionDetailScreen | Detalle, COGS, breakdown |
| InsufficientCreditsModal | Mensaje, CTA comprar |
| ConsumptionSummaryModal | Post-sesion, desglose |
9. UI de Wallet
┌─────────────────────────────────────────┐
│ MI WALLET │
├─────────────────────────────────────────┤
│ │
│ ┌─────────────────┐ │
│ │ │ │
│ │ 12.5 │ │
│ │ CREDITOS │ │
│ │ │ │
│ │ ≈ $156.25 MXN │ │
│ └─────────────────┘ │
│ │
│ ┌─────────────────────────────────┐ │
│ │ [+] RECARGAR CREDITOS │ │
│ └─────────────────────────────────┘ │
│ │
│ MOVIMIENTOS RECIENTES │
│ ───────────────────── │
│ │
│ 📥 Recarga $100 MXN +8.0 │
│ Ayer, 3:45 PM │
│ │
│ 📤 Inventario Tienda 1 -1.2 │
│ Ayer, 10:30 AM │
│ │
│ 📥 Bono de referido +1.0 │
│ 8 Ene, 5:00 PM │
│ │
│ [Ver todo el historial →] │
│ │
└─────────────────────────────────────────┘
10. Flujo de Consumo
┌─────────────────────────────────────────────────────────────────┐
│ FLUJO DE CONSUMO │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Iniciar │──▶│ Reservar │──▶│ Procesar │──▶│ Calcular │ │
│ │ Sesion │ │ Creditos │ │ Video │ │ COGS │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
│ │ │ │ │
│ │ │ balance -= estimated │ │
│ │ │ reserved += estimated │ │
│ │ │ │ │
│ ▼ │
│ ┌──────────┐ │
│ │ Consumir │ │
│ │ Real │ │
│ └──────────┘ │
│ │ │
│ reserved -= estimated │ │
│ balance += (estimated - real) │
│ lifetime_spent += real │
│ │
│ SI FALLA: │
│ ───────── │
│ reserved -= estimated │
│ balance += estimated (devolucion) │
│ │
└─────────────────────────────────────────────────────────────────┘
11. Dependencias
Entrada (Requiere)
- MII-002: Autenticacion (usuario)
- MII-005: Procesamiento IA (COGS)
Salida (Bloquea)
- MII-010: Paquetes de Recarga
- MII-011, 012, 013: Pagos
- MII-014: Referidos (rewards)
12. Configuracion
| Parametro | Valor Default | Descripcion |
|---|---|---|
| PRICING_MULTIPLIER | 2.0 | Factor sobre COGS |
| MIN_RESERVE | 2.0 | Creditos minimos a reservar |
| EXCHANGE_RATE_TTL | 1h | Cache de tipo de cambio |
| FREE_CREDITS_SIGNUP | 3.0 | Creditos gratis al registrar |
13. Riesgos
| Riesgo | Probabilidad | Impacto | Mitigacion |
|---|---|---|---|
| Costos IA suben | Media | Alto | Pricing dinamico, alertas |
| Race conditions | Media | Alto | Transacciones atomicas |
| Tipo cambio volatil | Baja | Medio | Cache, margen buffer |
14. Notas de Implementacion
- Usar transacciones DB para atomicidad
- Implementar lock optimista en wallet
- Cache de tipo de cambio con TTL
- Considerar creditos con expiracion (futuro)
- Log detallado de cada transaccion
15. Referencias
- REQUERIMIENTOS-FUNCIONALES.md - Seccion 5.9
- ADR-0001 - Modelo de Creditos
- ARQUITECTURA-TECNICA.md
Ultima Actualizacion: 2026-01-10