trading-platform/docs/02-definicion-modulos/OQI-004-investment-accounts/historias-usuario/US-INV-006-solicitar-retiro.md
rckrdmrd a7cca885f0 feat: Major platform documentation and architecture updates
Changes include:
- Updated architecture documentation
- Enhanced module definitions (OQI-001 to OQI-008)
- ML integration documentation updates
- Trading strategies documentation
- Orchestration and inventory updates
- Docker configuration updates

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 05:33:35 -06:00

13 KiB

id title type status priority epic project story_points created_date updated_date
US-INV-006 Solicitar Retiro User Story Done Media OQI-004 trading-platform 3 2025-12-05 2026-01-04

US-INV-006: Solicitar Retiro

Metadata

Campo Valor
ID US-INV-006
Épica OQI-004 - Cuentas de Inversión
Módulo investment
Prioridad P0
Story Points 5
Sprint Sprint 5
Estado Pendiente
Asignado a Por asignar

Historia de Usuario

Como inversor, quiero solicitar retiros de mi cuenta de inversión, para retirar ganancias o capital cuando lo necesite.

Descripción Detallada

El usuario debe poder solicitar retiro de fondos desde su cuenta de inversión. El sistema debe validar balance disponible, aplicar período de espera de 72 horas, cerrar posiciones abiertas del agente si es necesario, y procesar el retiro vía Stripe. El usuario debe poder ver el estado de sus retiros pendientes.

Mockups/Wireframes

┌─────────────────────────────────────────────────────────────────┐
│                    SOLICITAR RETIRO                              │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  Balance disponible: $1,245.50                                  │
│  En posiciones abiertas: $180.70                                │
│                                                                  │
│  ⚠️ Los retiros tienen un período de procesamiento de 72 horas │
│                                                                  │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │  Monto a retirar                                         │   │
│  │  ┌──────────────────────────────────────────────┐        │   │
│  │  │  $                                            │        │   │
│  │  └──────────────────────────────────────────────┘        │   │
│  │                                                           │   │
│  │  [ ] 25%  [ ] 50%  [ ] 75%  [ ] 100% (todo)              │   │
│  │                                                           │   │
│  │  Mínimo: $50 USD                                         │   │
│  │  Máximo disponible: $1,064.80 (balance - posiciones)    │   │
│  └─────────────────────────────────────────────────────────┘   │
│                                                                  │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │  Método de pago para recibir                             │   │
│  │                                                           │   │
│  │  (*) Tarjeta terminada en ****4242                       │   │
│  │  ( ) Cuenta bancaria ****5678                            │   │
│  │                                                           │   │
│  │  [+ Agregar nuevo método]                                │   │
│  └─────────────────────────────────────────────────────────┘   │
│                                                                  │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │  📋 Resumen                                              │   │
│  │                                                           │   │
│  │  Monto solicitado:       $500.00                         │   │
│  │  Comisión (2%):           $10.00                         │   │
│  │  ─────────────────────────────                           │   │
│  │  Recibirás:              $490.00                         │   │
│  │                                                           │   │
│  │  Nuevo balance:          $745.50                         │   │
│  │  Fecha estimada:         2025-12-08 (72h)                │   │
│  └─────────────────────────────────────────────────────────┘   │
│                                                                  │
│  ⚠️ Si tienes posiciones abiertas, el agente las cerrará antes │
│     de procesar el retiro para liberar fondos.                  │
│                                                                  │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │              SOLICITAR RETIRO                            │   │
│  └─────────────────────────────────────────────────────────┘   │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

Criterios de Aceptación

Escenario 1: Solicitar retiro exitoso

DADO que el usuario tiene balance de $1,245.50
Y no tiene posiciones abiertas
CUANDO solicita retiro de $500
Y selecciona método de pago
Y hace click en "Solicitar retiro"
ENTONCES se crea solicitud de retiro con status "pending"
Y se reserva $500 del balance
Y se muestra confirmación "Retiro solicitado, procesará en 72h"
Y se envía email de confirmación
Y se muestra en lista de retiros pendientes

Escenario 2: Retiro con posiciones abiertas

DADO que el usuario tiene balance $1,245.50
Y tiene $180.70 en posiciones abiertas
CUANDO solicita retiro de $1,000
ENTONCES se muestra advertencia "Se cerrarán posiciones abiertas"
Y el usuario confirma
Y el agente cierra todas las posiciones
Y se procesa el retiro con el balance final

Escenario 3: Monto mayor al disponible

DADO que el usuario tiene balance disponible de $1,064.80
CUANDO intenta retirar $1,500
ENTONCES se muestra error "Fondos insuficientes"
Y se muestra "Máximo disponible: $1,064.80"
Y el botón de confirmar está deshabilitado

Escenario 4: Monto menor al mínimo

DADO que el usuario está solicitando retiro
CUANDO ingresa monto de $25
Y el mínimo es $50
ENTONCES se muestra error "El monto mínimo es $50 USD"
Y el botón está deshabilitado

Escenario 5: Procesar retiro después de 72h

DADO que existe retiro con status "pending"
Y han pasado 72 horas desde la solicitud
CUANDO el cron job ejecuta processWithdrawals()
ENTONCES se procesa el pago con Stripe
Y se actualiza status a "completed"
Y se actualiza balance de cuenta
Y se envía email "Retiro completado"

Escenario 6: Ver retiros pendientes

DADO que el usuario tiene 2 retiros pendientes
CUANDO navega a sección de retiros
ENTONCES se muestra lista de retiros
Y cada retiro muestra: monto, fecha solicitud, tiempo restante, status
Y puede cancelar retiros que aún están en período de espera

Criterios Adicionales

  • Permitir cancelar retiro dentro de las primeras 24h
  • Mostrar countdown de tiempo restante para retiros pendientes
  • Límite de 1 retiro activo por vez
  • Validar que cuenta no esté en status "closed"
  • Logging detallado para auditoría

Tareas Técnicas

Database:

  • DB-INV-001: Schema investment.withdrawals
  • DB-INV-002: Enum withdrawal_status (pending, processing, completed, failed, cancelled)
  • DB-INV-003: Índice en (account_id, status)

Backend:

  • BE-INV-001: Endpoint POST /investment/accounts/:id/withdraw
  • BE-INV-002: Implementar WithdrawalService.requestWithdrawal()
  • BE-INV-003: Validar balance disponible
  • BE-INV-004: Integración con agente ML para cerrar posiciones
  • BE-INV-005: Implementar WithdrawalService.processWithdrawal()
  • BE-INV-006: Integración Stripe Transfers/Payouts
  • BE-INV-007: Cron job para procesar retiros después de 72h
  • BE-INV-008: Endpoint GET /investment/accounts/:id/withdrawals
  • BE-INV-009: Endpoint DELETE /investment/withdrawals/:id (cancelar)

Frontend:

  • FE-INV-001: Crear página WithdrawPage.tsx
  • FE-INV-002: Crear componente WithdrawForm.tsx
  • FE-INV-003: Crear componente WithdrawSummary.tsx
  • FE-INV-004: Crear componente PendingWithdrawals.tsx
  • FE-INV-005: Crear componente CountdownTimer.tsx
  • FE-INV-006: Implementar withdrawalStore

Tests:

  • TEST-INV-001: Test unitario WithdrawalService
  • TEST-INV-002: Test validaciones de balance
  • TEST-INV-003: Test integración Stripe
  • TEST-INV-004: Test cron job procesamiento
  • TEST-INV-005: Test E2E flujo completo retiro

Dependencias

Depende de:

  • US-INV-003: Realizar depósito - Estado: Pendiente
  • OQI-005: Integración Stripe - Estado: Pendiente
  • OQI-006: ML Agents (cerrar posiciones) - Estado: Pendiente

Bloquea:

  • US-INV-007: Ver historial transacciones
  • US-INV-009: Cerrar cuenta

Notas Técnicas

Endpoints involucrados:

Método Endpoint Descripción
POST /investment/accounts/:id/withdraw Solicitar retiro
GET /investment/accounts/:id/withdrawals Lista de retiros
DELETE /investment/withdrawals/:id Cancelar retiro

Entidades/Tablas:

  • investment.withdrawals: Solicitudes de retiro
  • investment.accounts: Actualizar balance
  • investment.transactions: Registrar transacción

Request Body POST /withdraw:

{
  amount: 500,
  paymentMethodId: "pm_xxx",
  closePositions: true, // si tiene posiciones abiertas
  reason: "profit_withdrawal" // opcional
}

Response:

{
  withdrawal: {
    id: "uuid",
    accountId: "uuid",
    amount: 500,
    fee: 10,
    netAmount: 490,
    status: "pending",
    requestedAt: "2025-12-05T10:00:00Z",
    estimatedCompletionAt: "2025-12-08T10:00:00Z",
    paymentMethodId: "pm_xxx"
  },
  account: {
    balance: 745.50,
    reservedBalance: 500
  }
}

Estados de Retiro:

  • pending: Solicitado, esperando 72h
  • processing: Procesando pago con Stripe
  • completed: Retiro completado exitosamente
  • failed: Fallo en procesamiento (reintentable)
  • cancelled: Cancelado por usuario

Flujo de Retiro:

  1. Usuario solicita retiro
  2. Sistema valida balance y cierra posiciones si es necesario
  3. Se crea withdrawal con status "pending"
  4. Balance se reserva (no disponible para trading)
  5. Después de 72h, cron job cambia status a "processing"
  6. Se procesa pago con Stripe
  7. Si éxito: status "completed", se actualiza balance
  8. Si falla: status "failed", se libera balance reservado

Límites:

  • Retiro mínimo: $50 USD
  • Retiro máximo: Balance disponible
  • Comisión: 2% del monto
  • Período de espera: 72 horas
  • Máximo 1 retiro pendiente por cuenta

Definition of Ready (DoR)

  • Historia claramente escrita
  • Criterios de aceptación definidos
  • Story points estimados
  • Dependencias identificadas
  • Integración Stripe documentada
  • Diseño/mockup disponible
  • API spec disponible

Definition of Done (DoD)

  • Código implementado según criterios
  • Tests unitarios escritos y pasando
  • Tests de integración pasando
  • Integración Stripe funcionando
  • Cron job configurado y probado
  • Code review aprobado
  • Documentación actualizada
  • QA aprobado
  • Desplegado en ambiente de pruebas

Historial de Cambios

Fecha Cambio Autor
2025-12-05 Creación Requirements-Analyst

Creada por: Requirements-Analyst Fecha: 2025-12-05 Última actualización: 2025-12-05