- Add 01-CONTEXTO.md, 02-ANALISIS.md, 03-PLANEACION.md, 04-VALIDACION.md - Update _INDEX.yml with complete CAPVED file list - Update ET-PAY-005-frontend.md with new components section - Update TRACEABILITY.yml with frontend implementation status Full SIMCO compliance achieved for TASK-2026-01-25-OQI-005-PAYMENTS-ADVANCED Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
573 lines
17 KiB
YAML
573 lines
17 KiB
YAML
# TRACEABILITY.yml - OQI-005 Pagos y Stripe
|
|
# Mapeo de requerimientos a implementación
|
|
|
|
version: "1.1.0"
|
|
epic: OQI-005
|
|
name: "Sistema de Pagos con Stripe"
|
|
updated: "2026-01-25"
|
|
status: in_progress
|
|
|
|
# Resumen de trazabilidad
|
|
summary:
|
|
total_requirements: 6
|
|
total_specs: 6
|
|
total_user_stories: 10
|
|
total_files_to_implement: 35
|
|
test_coverage: "TBD"
|
|
story_points: 40
|
|
|
|
# Mapeo de Requerimientos Funcionales
|
|
requirements:
|
|
RF-PAY-001:
|
|
name: "Suscripciones"
|
|
status: pending
|
|
specs:
|
|
- ET-PAY-001
|
|
- ET-PAY-002
|
|
user_stories:
|
|
- US-PAY-001
|
|
- US-PAY-002
|
|
implementation:
|
|
backend:
|
|
- path: apps/backend/src/modules/payments/services/subscription.service.ts
|
|
description: "Servicio de suscripciones"
|
|
methods:
|
|
- getPlans
|
|
- createSubscription
|
|
- cancelSubscription
|
|
- updateSubscription
|
|
- getActiveSubscription
|
|
- resumeSubscription
|
|
- path: apps/backend/src/modules/payments/controllers/payments.controller.ts
|
|
methods:
|
|
- getPlans
|
|
- subscribe
|
|
- cancelSubscription
|
|
- getMySubscription
|
|
- path: apps/backend/src/modules/payments/payments.routes.ts
|
|
routes:
|
|
- "GET /payments/plans"
|
|
- "POST /payments/subscribe"
|
|
- "GET /payments/subscription"
|
|
- "DELETE /payments/subscription"
|
|
- "POST /payments/subscription/resume"
|
|
frontend:
|
|
- path: apps/frontend/src/modules/settings/pages/Billing.tsx
|
|
description: "Página de facturación"
|
|
- path: apps/frontend/src/modules/payments/components/PlanSelector.tsx
|
|
description: "Selector de planes"
|
|
- path: apps/frontend/src/modules/payments/components/SubscriptionCard.tsx
|
|
description: "Tarjeta de suscripción"
|
|
- path: apps/frontend/src/modules/payments/components/PlanComparison.tsx
|
|
description: "Comparador de planes"
|
|
database:
|
|
- path: apps/database/schemas/05_financial_schema.sql
|
|
tables:
|
|
- subscription_plans
|
|
- subscriptions
|
|
- subscription_features
|
|
enums:
|
|
- plan_interval_enum
|
|
- subscription_status_enum
|
|
external:
|
|
- service: Stripe Subscriptions
|
|
usage: "Gestión de suscripciones recurrentes"
|
|
tests:
|
|
- path: apps/backend/tests/payments/subscription.service.test.ts
|
|
status: pending
|
|
|
|
RF-PAY-002:
|
|
name: "Checkout"
|
|
status: in_progress
|
|
specs:
|
|
- ET-PAY-002
|
|
- ET-PAY-005
|
|
user_stories:
|
|
- US-PAY-005
|
|
implementation:
|
|
backend:
|
|
- path: apps/backend/src/modules/payments/services/checkout.service.ts
|
|
description: "Servicio de checkout"
|
|
methods:
|
|
- createCheckoutSession
|
|
- getCheckoutSession
|
|
- processPayment
|
|
- handleSuccess
|
|
- handleCancel
|
|
- path: apps/backend/src/modules/payments/controllers/payments.controller.ts
|
|
methods:
|
|
- createCheckout
|
|
- getCheckoutStatus
|
|
- path: apps/backend/src/modules/payments/payments.routes.ts
|
|
routes:
|
|
- "POST /payments/checkout"
|
|
- "GET /payments/checkout/:sessionId"
|
|
- "GET /payments/checkout/success"
|
|
- "GET /payments/checkout/cancel"
|
|
frontend:
|
|
- path: apps/frontend/src/modules/payments/pages/Checkout.tsx
|
|
description: "Página de checkout"
|
|
- path: apps/frontend/src/modules/payments/pages/CheckoutSuccess.tsx
|
|
description: "Página de éxito"
|
|
- path: apps/frontend/src/modules/payments/pages/CheckoutCancel.tsx
|
|
description: "Página de cancelación"
|
|
- path: apps/frontend/src/modules/payments/components/CheckoutForm.tsx
|
|
description: "Formulario de checkout"
|
|
- path: apps/frontend/src/components/payments/StripeElementsWrapper.tsx
|
|
description: "Wrapper PCI-DSS compliant para Stripe Elements"
|
|
status: done
|
|
created: "2026-01-25"
|
|
loc: 220
|
|
exports:
|
|
- StripeElementsWrapper
|
|
- withStripeElements
|
|
- useStripeAvailable
|
|
types:
|
|
- StripeConfig
|
|
- path: apps/frontend/src/components/payments/InvoicePreview.tsx
|
|
description: "Vista previa de factura pre-checkout"
|
|
status: done
|
|
created: "2026-01-25"
|
|
loc: 350
|
|
types:
|
|
- InvoiceLineItem
|
|
- InvoiceDiscount
|
|
- InvoiceTax
|
|
- InvoicePreviewData
|
|
database:
|
|
- path: apps/database/schemas/05_financial_schema.sql
|
|
tables:
|
|
- checkout_sessions
|
|
- purchases
|
|
enums:
|
|
- checkout_status_enum
|
|
- purchase_type_enum
|
|
external:
|
|
- service: Stripe Checkout
|
|
usage: "Checkout hosted por Stripe"
|
|
tests:
|
|
- path: apps/backend/tests/payments/checkout.service.test.ts
|
|
status: pending
|
|
tasks:
|
|
- id: TASK-2026-01-25-OQI-005-PAYMENTS-ADVANCED
|
|
description: "StripeElementsWrapper e InvoicePreview"
|
|
status: done
|
|
|
|
RF-PAY-003:
|
|
name: "Wallet Digital"
|
|
status: pending
|
|
specs:
|
|
- ET-PAY-001
|
|
- ET-PAY-004
|
|
user_stories: []
|
|
implementation:
|
|
backend:
|
|
- path: apps/backend/src/modules/payments/services/wallet.service.ts
|
|
description: "Servicio de wallet"
|
|
methods:
|
|
- getWallet
|
|
- addFunds
|
|
- withdrawFunds
|
|
- transferFunds
|
|
- getTransactions
|
|
- getBalance
|
|
- path: apps/backend/src/modules/payments/controllers/payments.controller.ts
|
|
methods:
|
|
- getWallet
|
|
- addToWallet
|
|
- withdrawFromWallet
|
|
- getWalletHistory
|
|
- path: apps/backend/src/modules/payments/payments.routes.ts
|
|
routes:
|
|
- "GET /payments/wallet"
|
|
- "POST /payments/wallet/add"
|
|
- "POST /payments/wallet/withdraw"
|
|
- "GET /payments/wallet/transactions"
|
|
frontend:
|
|
- path: apps/frontend/src/modules/payments/components/WalletCard.tsx
|
|
description: "Tarjeta de wallet"
|
|
- path: apps/frontend/src/modules/payments/components/AddFundsModal.tsx
|
|
description: "Modal para agregar fondos"
|
|
- path: apps/frontend/src/modules/payments/components/WalletHistory.tsx
|
|
description: "Historial de wallet"
|
|
database:
|
|
- path: apps/database/schemas/05_financial_schema.sql
|
|
tables:
|
|
- wallets
|
|
- wallet_transactions
|
|
enums:
|
|
- wallet_transaction_type_enum
|
|
tests:
|
|
- path: apps/backend/tests/payments/wallet.service.test.ts
|
|
status: pending
|
|
|
|
RF-PAY-004:
|
|
name: "Facturación"
|
|
status: pending
|
|
specs:
|
|
- ET-PAY-004
|
|
user_stories:
|
|
- US-PAY-007
|
|
implementation:
|
|
backend:
|
|
- path: apps/backend/src/modules/payments/services/invoice.service.ts
|
|
description: "Servicio de facturación"
|
|
methods:
|
|
- getInvoices
|
|
- getInvoiceById
|
|
- downloadInvoice
|
|
- sendInvoice
|
|
- generateInvoicePDF
|
|
- path: apps/backend/src/modules/payments/controllers/payments.controller.ts
|
|
methods:
|
|
- getInvoices
|
|
- getInvoice
|
|
- downloadInvoice
|
|
- path: apps/backend/src/modules/payments/payments.routes.ts
|
|
routes:
|
|
- "GET /payments/invoices"
|
|
- "GET /payments/invoices/:id"
|
|
- "GET /payments/invoices/:id/download"
|
|
frontend:
|
|
- path: apps/frontend/src/modules/payments/components/InvoiceList.tsx
|
|
description: "Lista de facturas"
|
|
- path: apps/frontend/src/modules/payments/components/InvoiceCard.tsx
|
|
description: "Tarjeta de factura"
|
|
database:
|
|
- path: apps/database/schemas/05_financial_schema.sql
|
|
tables:
|
|
- invoices
|
|
- invoice_items
|
|
enums:
|
|
- invoice_status_enum
|
|
tests:
|
|
- path: apps/backend/tests/payments/invoice.service.test.ts
|
|
status: pending
|
|
|
|
RF-PAY-005:
|
|
name: "Webhooks de Stripe"
|
|
status: pending
|
|
specs:
|
|
- ET-PAY-003
|
|
user_stories: []
|
|
implementation:
|
|
backend:
|
|
- path: apps/backend/src/modules/payments/services/webhook.service.ts
|
|
description: "Servicio de webhooks"
|
|
methods:
|
|
- handleWebhook
|
|
- verifySignature
|
|
- processPaymentIntent
|
|
- processSubscription
|
|
- processInvoice
|
|
- processDispute
|
|
- path: apps/backend/src/modules/payments/controllers/payments.controller.ts
|
|
methods:
|
|
- handleStripeWebhook
|
|
- path: apps/backend/src/modules/payments/payments.routes.ts
|
|
routes:
|
|
- "POST /payments/webhook"
|
|
- path: apps/backend/src/modules/payments/handlers/webhook.handlers.ts
|
|
description: "Handlers por tipo de evento"
|
|
database:
|
|
- path: apps/database/schemas/05_financial_schema.sql
|
|
tables:
|
|
- webhook_events
|
|
enums:
|
|
- webhook_event_type_enum
|
|
tests:
|
|
- path: apps/backend/tests/payments/webhook.service.test.ts
|
|
status: pending
|
|
|
|
RF-PAY-006:
|
|
name: "Reembolsos"
|
|
status: in_progress
|
|
specs:
|
|
- ET-PAY-002
|
|
- ET-PAY-006
|
|
user_stories: []
|
|
implementation:
|
|
backend:
|
|
- path: apps/backend/src/modules/payments/services/refund.service.ts
|
|
description: "Servicio de reembolsos"
|
|
methods:
|
|
- requestRefund
|
|
- processRefund
|
|
- getRefunds
|
|
- cancelRefund
|
|
- path: apps/backend/src/modules/payments/controllers/payments.controller.ts
|
|
methods:
|
|
- requestRefund
|
|
- getRefunds
|
|
- path: apps/backend/src/modules/payments/payments.routes.ts
|
|
routes:
|
|
- "POST /payments/refunds"
|
|
- "GET /payments/refunds"
|
|
- "GET /payments/refunds/:id"
|
|
frontend:
|
|
- path: apps/frontend/src/components/payments/RefundRequestModal.tsx
|
|
description: "Modal de solicitud de reembolso"
|
|
status: done
|
|
created: "2026-01-25"
|
|
loc: 480
|
|
types:
|
|
- RefundEligibility
|
|
- RefundRequestData
|
|
- RefundReason
|
|
- path: apps/frontend/src/components/payments/RefundList.tsx
|
|
description: "Lista paginada de reembolsos con filtros"
|
|
status: done
|
|
created: "2026-01-25"
|
|
loc: 450
|
|
types:
|
|
- Refund
|
|
- RefundStatus
|
|
database:
|
|
- path: apps/database/schemas/05_financial_schema.sql
|
|
tables:
|
|
- refunds
|
|
enums:
|
|
- refund_status_enum
|
|
- refund_reason_enum
|
|
external:
|
|
- service: Stripe Refunds
|
|
usage: "Procesamiento de reembolsos"
|
|
tests:
|
|
- path: apps/backend/tests/payments/refund.service.test.ts
|
|
status: pending
|
|
tasks:
|
|
- id: TASK-2026-01-25-OQI-005-PAYMENTS-ADVANCED
|
|
description: "Frontend components para reembolsos"
|
|
status: done
|
|
|
|
# Métodos de pago soportados
|
|
payment_methods:
|
|
- type: card
|
|
brands: [visa, mastercard, amex]
|
|
regions: [global]
|
|
- type: bank_transfer
|
|
brands: [spei]
|
|
regions: [mexico]
|
|
- type: wallet
|
|
brands: [apple_pay, google_pay]
|
|
regions: [global]
|
|
- type: oxxo
|
|
brands: [oxxo]
|
|
regions: [mexico]
|
|
|
|
# Planes de suscripción
|
|
subscription_plans:
|
|
- code: FREE
|
|
name: "Free"
|
|
price: 0
|
|
interval: month
|
|
features:
|
|
- "Acceso básico a charts"
|
|
- "1 watchlist"
|
|
- "Paper trading limitado"
|
|
- code: PRO
|
|
name: "Pro Trader"
|
|
price: 499
|
|
currency: MXN
|
|
interval: month
|
|
features:
|
|
- "Charts avanzados"
|
|
- "Watchlists ilimitadas"
|
|
- "Paper trading completo"
|
|
- "Señales ML básicas"
|
|
- code: PREMIUM
|
|
name: "Premium"
|
|
price: 999
|
|
currency: MXN
|
|
interval: month
|
|
features:
|
|
- "Todo de Pro"
|
|
- "Señales ML premium"
|
|
- "Copilot AI"
|
|
- "Soporte prioritario"
|
|
- code: ENTERPRISE
|
|
name: "Enterprise"
|
|
price: custom
|
|
interval: month
|
|
features:
|
|
- "Todo de Premium"
|
|
- "API access"
|
|
- "White-label"
|
|
- "SLA dedicado"
|
|
|
|
# Mapeo de archivos de configuración
|
|
config_files:
|
|
backend:
|
|
- path: apps/backend/src/modules/payments/payments.module.ts
|
|
description: "Módulo de pagos"
|
|
- path: apps/backend/src/modules/payments/validators/payments.validators.ts
|
|
description: "Validadores Zod"
|
|
- path: apps/backend/src/modules/payments/types/payments.types.ts
|
|
description: "Tipos TypeScript"
|
|
- path: apps/backend/src/config/stripe.config.ts
|
|
description: "Configuración de Stripe"
|
|
frontend:
|
|
- path: apps/frontend/src/modules/payments/stores/payments.store.ts
|
|
description: "Store de pagos Zustand"
|
|
- path: apps/frontend/src/modules/payments/hooks/usePayments.ts
|
|
description: "Hook principal de pagos"
|
|
- path: apps/frontend/src/modules/payments/services/payments.api.ts
|
|
description: "Cliente API de pagos"
|
|
|
|
# Dependencias externas
|
|
external_dependencies:
|
|
npm_backend:
|
|
- name: stripe
|
|
version: "^14.0.0"
|
|
usage: "SDK de Stripe"
|
|
- name: pdfkit
|
|
version: "^0.14.0"
|
|
usage: "Generación de facturas PDF"
|
|
npm_frontend:
|
|
- name: "@stripe/stripe-js"
|
|
version: "^2.2.0"
|
|
usage: "Stripe.js"
|
|
- name: "@stripe/react-stripe-js"
|
|
version: "^2.4.0"
|
|
usage: "Componentes React de Stripe"
|
|
|
|
# APIs de terceros
|
|
third_party_apis:
|
|
- name: Stripe API
|
|
docs: https://stripe.com/docs/api
|
|
usage:
|
|
- Payment Intents
|
|
- Customers
|
|
- Subscriptions
|
|
- Invoices
|
|
- Webhooks
|
|
- Refunds
|
|
- Payment Methods
|
|
- name: Stripe Checkout
|
|
docs: https://stripe.com/docs/payments/checkout
|
|
usage:
|
|
- Hosted checkout pages
|
|
- One-time payments
|
|
- Subscription checkout
|
|
|
|
# Endpoints API
|
|
api_endpoints:
|
|
base_path: /api/v1/payments
|
|
endpoints:
|
|
# Planes
|
|
- method: GET
|
|
path: /plans
|
|
requirement: RF-PAY-001
|
|
auth: false
|
|
# Suscripciones
|
|
- method: POST
|
|
path: /subscribe
|
|
requirement: RF-PAY-001
|
|
auth: true
|
|
- method: GET
|
|
path: /subscription
|
|
requirement: RF-PAY-001
|
|
auth: true
|
|
- method: DELETE
|
|
path: /subscription
|
|
requirement: RF-PAY-001
|
|
auth: true
|
|
# Checkout
|
|
- method: POST
|
|
path: /checkout
|
|
requirement: RF-PAY-002
|
|
auth: true
|
|
- method: GET
|
|
path: /checkout/:sessionId
|
|
requirement: RF-PAY-002
|
|
auth: true
|
|
# Wallet
|
|
- method: GET
|
|
path: /wallet
|
|
requirement: RF-PAY-003
|
|
auth: true
|
|
- method: POST
|
|
path: /wallet/add
|
|
requirement: RF-PAY-003
|
|
auth: true
|
|
- method: POST
|
|
path: /wallet/withdraw
|
|
requirement: RF-PAY-003
|
|
auth: true
|
|
# Facturas
|
|
- method: GET
|
|
path: /invoices
|
|
requirement: RF-PAY-004
|
|
auth: true
|
|
- method: GET
|
|
path: /invoices/:id/download
|
|
requirement: RF-PAY-004
|
|
auth: true
|
|
# Webhooks
|
|
- method: POST
|
|
path: /webhook
|
|
requirement: RF-PAY-005
|
|
auth: false
|
|
note: "Verificación por signature"
|
|
# Reembolsos
|
|
- method: POST
|
|
path: /refunds
|
|
requirement: RF-PAY-006
|
|
auth: true
|
|
# Métodos de pago
|
|
- method: GET
|
|
path: /payment-methods
|
|
requirement: RF-PAY-002
|
|
auth: true
|
|
- method: POST
|
|
path: /payment-methods
|
|
requirement: RF-PAY-002
|
|
auth: true
|
|
- method: DELETE
|
|
path: /payment-methods/:id
|
|
requirement: RF-PAY-002
|
|
auth: true
|
|
|
|
# Webhook events
|
|
webhook_events:
|
|
- event: payment_intent.succeeded
|
|
handler: handlePaymentSuccess
|
|
- event: payment_intent.payment_failed
|
|
handler: handlePaymentFailed
|
|
- event: customer.subscription.created
|
|
handler: handleSubscriptionCreated
|
|
- event: customer.subscription.updated
|
|
handler: handleSubscriptionUpdated
|
|
- event: customer.subscription.deleted
|
|
handler: handleSubscriptionCancelled
|
|
- event: invoice.paid
|
|
handler: handleInvoicePaid
|
|
- event: invoice.payment_failed
|
|
handler: handleInvoiceFailed
|
|
- event: charge.refunded
|
|
handler: handleRefund
|
|
- event: charge.dispute.created
|
|
handler: handleDispute
|
|
|
|
# Dependencias de épicas
|
|
dependencies:
|
|
blocks:
|
|
- epic: OQI-002
|
|
reason: "Compra de cursos"
|
|
type: partial
|
|
- epic: OQI-004
|
|
reason: "Depósitos en cuentas de inversión"
|
|
blocked_by:
|
|
- epic: OQI-001
|
|
reason: "Requiere autenticación de usuarios"
|
|
|
|
# Notas y decisiones
|
|
notes:
|
|
- "Stripe como único proveedor de pagos inicial"
|
|
- "OXXO habilitado solo para México"
|
|
- "Webhooks con retry automático y idempotency"
|
|
- "Precios en MXN con conversión automática"
|
|
- "Facturas generadas automáticamente"
|
|
- "Período de gracia de 3 días para suscripciones fallidas"
|
|
- "Reembolsos procesados en 5-10 días hábiles"
|