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

5.3 KiB

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

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

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

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

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

// 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