trading-platform/orchestration/tareas/TASK-2026-01-25-OQI-005-PAYMENTS-ADVANCED/06-DOCUMENTACION.md
Adrian Flores Cortes 20d3127f8d [OQI-005] docs: Add task documentation and update inventories
- Add TASK-2026-01-25-OQI-005-PAYMENTS-ADVANCED folder
- Update FRONTEND_INVENTORY: payments 4→8, progress 50%→65%
- Update MASTER_INVENTORY: frontend 135→139
- Update _INDEX.yml: total 14→15

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26 09:52:27 -06:00

255 lines
5.3 KiB
Markdown

# 06-DOCUMENTACION.md - OQI-005 Payments Advanced Components
## Documentación Técnica
### Componentes Creados
| Componente | LOC | Tipos | Descripción |
|------------|-----|-------|-------------|
| StripeElementsWrapper | 220 | 1 | Foundation PCI-DSS |
| InvoicePreview | 350 | 4 | Vista previa factura |
| RefundRequestModal | 480 | 3 | Modal reembolsos |
| RefundList | 450 | 2 | Historial reembolsos |
| **Total** | **1500** | **10** | |
---
## API de Componentes
### StripeElementsWrapper
```typescript
interface StripeConfig {
publicKey: string;
locale?: 'en' | 'es' | 'auto';
appearance?: 'stripe' | 'night' | 'flat';
}
interface StripeElementsWrapperProps {
config: StripeConfig;
children: React.ReactNode;
}
// Uso
<StripeElementsWrapper config={{ publicKey: 'pk_test_...' }}>
<PaymentForm />
</StripeElementsWrapper>
// HOC
const WrappedComponent = withStripeElements(MyComponent, config);
// Hook
const isAvailable = useStripeAvailable();
```
### InvoicePreview
```typescript
interface InvoiceLineItem {
id: string;
description: string;
quantity: number;
unitPrice: number;
total: number;
}
interface InvoiceDiscount {
code?: string;
description: string;
type: 'percentage' | 'fixed';
value: number;
amount: number;
}
interface InvoiceTax {
name: string;
rate: number;
amount: number;
}
interface InvoicePreviewData {
invoiceNumber?: string;
items: InvoiceLineItem[];
subtotal: number;
discounts?: InvoiceDiscount[];
taxes?: InvoiceTax[];
total: number;
currency?: string;
periodStart?: string;
periodEnd?: string;
notes?: string;
}
interface InvoicePreviewProps {
data: InvoicePreviewData;
onConfirm?: () => void;
onCancel?: () => void;
confirmLabel?: string;
cancelLabel?: string;
isLoading?: boolean;
showActions?: boolean;
}
```
### RefundRequestModal
```typescript
type RefundReason =
| 'duplicate'
| 'fraudulent'
| 'customer_request'
| 'product_issue'
| 'other';
interface RefundEligibility {
eligible: boolean;
maxAmount: number;
reason?: string;
daysRemaining?: number;
}
interface RefundRequestData {
transactionId: string;
amount: number;
reason: RefundReason;
explanation: string;
}
interface RefundRequestModalProps {
isOpen: boolean;
onClose: () => void;
transactionId: string;
transactionAmount: number;
transactionDate: string;
eligibility: RefundEligibility;
onSubmit: (data: RefundRequestData) => Promise<void>;
currency?: string;
}
```
### RefundList
```typescript
type RefundStatus =
| 'pending'
| 'processing'
| 'completed'
| 'failed'
| 'cancelled';
interface Refund {
id: string;
transactionId: string;
amount: number;
currency: string;
status: RefundStatus;
reason: string;
explanation?: string;
createdAt: string;
processedAt?: string;
failureReason?: string;
}
interface RefundListProps {
refunds: Refund[];
totalCount: number;
currentPage: number;
pageSize: number;
onPageChange: (page: number) => void;
onStatusFilter?: (status: RefundStatus | 'all') => void;
selectedStatus?: RefundStatus | 'all';
isLoading?: boolean;
onRefundClick?: (refund: Refund) => void;
}
```
---
## Integración con Backend
### Endpoints Requeridos
| Endpoint | Método | Componente |
|----------|--------|------------|
| `/api/payments/stripe/config` | GET | StripeElementsWrapper |
| `/api/invoices/preview` | POST | InvoicePreview |
| `/api/refunds/eligibility/:txId` | GET | RefundRequestModal |
| `/api/refunds` | POST | RefundRequestModal |
| `/api/refunds` | GET | RefundList |
### Ejemplo de Integración
```typescript
// pages/payments/refunds.tsx
import { RefundList, RefundRequestModal } from '@/components/payments';
export default function RefundsPage() {
const [refunds, setRefunds] = useState<Refund[]>([]);
const [selectedTx, setSelectedTx] = useState<string | null>(null);
// Fetch refunds
useEffect(() => {
fetch('/api/refunds')
.then(res => res.json())
.then(data => setRefunds(data.refunds));
}, []);
return (
<>
<RefundList
refunds={refunds}
totalCount={100}
currentPage={1}
pageSize={10}
onPageChange={handlePageChange}
/>
{selectedTx && (
<RefundRequestModal
isOpen={true}
onClose={() => setSelectedTx(null)}
transactionId={selectedTx}
// ...other props
/>
)}
</>
);
}
```
---
## Consideraciones de Seguridad
### PCI-DSS Compliance
1. **StripeElementsWrapper** asegura que:
- Datos de tarjeta nunca tocan nuestros servidores
- Tokenización manejada por Stripe
- Comunicación directa cliente-Stripe
2. **Recomendación**: Migrar `PaymentMethodForm` existente para usar `CardElement` de Stripe Elements en lugar de inputs manuales.
### Validaciones
- RefundRequestModal valida montos contra elegibilidad
- Explicación requerida para todas las solicitudes
- Estados de error manejados apropiadamente
---
## Próximos Pasos
1. **Backend Integration**
- Implementar endpoints de refunds
- Configurar webhooks de Stripe para status updates
2. **Frontend Enhancements**
- Migrar PaymentMethodForm a Stripe Elements
- Agregar tests unitarios
- Implementar páginas de gestión de reembolsos
3. **OQI-005 Remaining**
- Progress actual: 65%
- Pendiente: Dispute management, Advanced billing