docs: add CFDI viewer design document

Design for PDF-like invoice visualization with:
- Modal viewer with invoice preview
- PDF download via html2pdf.js
- XML download from stored data

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Consultoria AS
2026-02-17 02:26:19 +00:00
parent 3466ec740e
commit 67f74538b8

View File

@@ -0,0 +1,126 @@
# 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)