# Diseño: Visor de CFDI **Fecha:** 2026-02-17 **Estado:** Aprobado ## Resumen Agregar funcionalidad para visualizar facturas CFDI en formato PDF-like, recreando la representación visual desde el XML almacenado. Incluye descarga de PDF y XML. ## Decisiones de Diseño - **Tipo de vista:** PDF-like (representación visual similar a factura impresa) - **Acceso:** Botón "Ver" (icono ojo) en cada fila de la tabla - **Acciones:** Descargar PDF, Descargar XML - **Enfoque técnico:** Componente React + html2pdf.js para generación de PDF en cliente ## Arquitectura de Componentes ``` CfdiPage (existente) ├── Tabla de CFDIs │ └── Botón "Ver" (Eye icon) → abre modal │ └── CfdiViewerModal (NUEVO) ├── Header: Título + Botones (PDF, XML, Cerrar) └── CfdiInvoice (NUEVO) ├── Encabezado (Emisor + Receptor) ├── Datos del comprobante ├── Tabla de conceptos (parseados del XML) ├── Totales e impuestos └── Timbre fiscal (UUID, fechas) ``` ## Componentes Nuevos | Componente | Ubicación | Responsabilidad | |------------|-----------|-----------------| | `CfdiViewerModal` | `components/cfdi/cfdi-viewer-modal.tsx` | Modal con visor y botones de acción | | `CfdiInvoice` | `components/cfdi/cfdi-invoice.tsx` | Renderiza la factura estilo PDF | ## Diseño Visual ``` ┌──────────────────────────────────────────────────────────────┐ │ ┌─────────────────┐ FACTURA │ │ │ [LOGO] │ Serie: A Folio: 001 │ │ │ placeholder │ Fecha: 15/Ene/2025 │ │ └─────────────────┘ │ ├──────────────────────────────────────────────────────────────┤ │ EMISOR │ RECEPTOR │ │ Empresa Emisora SA de CV │ Cliente SA de CV │ │ RFC: XAXX010101000 │ RFC: XAXX010101001 │ │ │ Uso CFDI: G03 │ ├──────────────────────────────────────────────────────────────┤ │ DATOS DEL COMPROBANTE │ │ Tipo: Ingreso Método: PUE Forma: 03 - Transferencia │ │ Moneda: MXN Tipo Cambio: 1.00 │ ├──────────────────────────────────────────────────────────────┤ │ CONCEPTOS │ │ ┌──────────────────────────────────────────────────────┐ │ │ │ Descripción │ Cant │ P. Unit │ Importe │ │ │ ├──────────────────────────────────────────────────────┤ │ │ │ Servicio consultoría │ 1 │ 10,000 │ 10,000.00 │ │ │ └──────────────────────────────────────────────────────┘ │ ├──────────────────────────────────────────────────────────────┤ │ Subtotal: $10,000.00 │ │ IVA 16%: $1,600.00 │ │ TOTAL: $11,600.00 │ ├──────────────────────────────────────────────────────────────┤ │ TIMBRE FISCAL DIGITAL │ │ UUID: 12345678-1234-1234-1234-123456789012 │ │ Fecha Timbrado: 2025-01-15T12:30:45 │ └──────────────────────────────────────────────────────────────┘ ``` ## Flujo de Datos 1. Usuario hace clic en "Ver" (Eye icon) 2. Se abre CfdiViewerModal con el CFDI seleccionado 3. Si existe xmlOriginal: - Parsear XML para extraer conceptos - Mostrar factura completa 4. Si no existe XML: - Mostrar factura con datos de BD (sin conceptos) 5. Acciones disponibles: - Descargar PDF (html2pdf genera PDF) - Descargar XML (si existe) ## Cambios en Backend ### Nuevo Endpoint ``` GET /api/cfdi/:id/xml ``` Retorna el XML original del CFDI. ### Modificar Endpoint Existente ``` GET /api/cfdi/:id ``` Agregar campo `xmlOriginal` a la respuesta. ## Dependencias ```json { "html2pdf.js": "^0.10.1" } ``` ## Archivos a Crear/Modificar ### Nuevos - `apps/web/components/cfdi/cfdi-viewer-modal.tsx` - `apps/web/components/cfdi/cfdi-invoice.tsx` - `apps/api/src/controllers/cfdi.controller.ts` (nuevo método getXml) ### Modificar - `apps/web/app/(dashboard)/cfdi/page.tsx` (agregar botón Ver y modal) - `apps/api/src/routes/cfdi.routes.ts` (agregar ruta /xml) - `apps/api/src/services/cfdi.service.ts` (agregar método getXmlById) - `packages/shared/src/types/cfdi.ts` (agregar xmlOriginal a Cfdi)