# 📱 Sistema de Recibos PNG - Especificación Completa ## 🎯 Objetivo Crear un sistema paralelo que genere recibos PNG elegantes para enviar a clientes, manteniendo el sistema de impresión térmica actual intacto. **Archivo de descarga**: `Ticket_{FOLIO}.png` (ej: `Ticket_AP-k8hcg.png`) --- ## 🎨 Assets Structure ``` /assets/receipt/ ├── background.png (fondo decorativo completo) ├── logo.png (logotipo del negocio) ├── business-name.png (nombre del negocio) ├── tagline.png (tagline: "Beauty Expert", etc.) ├── comprobante-title.png (título "COMPROBANTE DE PAGO") └── rectangle-white.png (rectángulo contenedor blanco/transparente) ``` ## 🏗️ Arquitectura del Sistema ### HTML Structure ```html
``` ### CSS Base ```css @import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@400;600;700&display=swap'); .receipt-wrapper { width: 400px; font-family: 'Montserrat', sans-serif; } .receipt-background { background-size: cover; background-position: center; background-repeat: no-repeat; } .receipt-content { background-size: contain; background-position: center; background-repeat: no-repeat; } .montserrat { font-family: 'Montserrat', sans-serif; } .bold { font-weight: 600; } .extra-bold { font-weight: 700; } ``` --- ## 🎫 Tipos de Tickets y Casos de Uso ### Matriz de Combinaciones | Tipo | Cita | Anticipo | Consentimiento | Oncológico | Notas Especiales | |------|------|----------|----------------|------------|------------------| | **Servicio Simple** | ❌ | ❌ | ❌ | ❌ | - | | **Servicio con Cita** | ✅ | ❌ | ❌ | ❌ | Fecha/Hora | | **Anticipo Puro** | ✅ | ✅ | ❌ | ❌ | Notas anticipo | | **Servicio + Anticipo Aplicado** | ✅ | ✅ | ❌ | ❌ | **SIN** notas anticipo | | **Servicio + Consentimiento** | ✅ | ❌ | ✅ | ❌ | Texto consentimiento | | **Servicio + Oncológico** | ✅ | ❌ | ✅ | ✅ | Datos médico | | **Combo Completo** | ✅ | ✅ | ✅ | ✅ | Todo combinado | ### Lógica de Detección ```javascript function analyzeTicketType(movement) { return { hasAppointment: !!(movement.fechaCita && movement.horaCita), isAnticipo: movement.tipo === 'Anticipo' || movement.concepto?.toLowerCase().includes('anticipo'), hasAnticipoApplied: movement.discountInfo?.type === 'anticipo', hasConsent: movement.client?.consentimiento || movement.client?.esOncologico, isOncology: movement.client?.esOncologico, needsAnticipoNotes: function() { // Solo mostrar notas si es anticipo PURO (no aplicado a servicio) return this.isAnticipo && !this.hasAnticipoApplied; } }; } ``` ### Casos Específicos #### 1. Anticipo Puro - **Mostrar**: Notas de compromiso y cancelación - **Condición**: `movement.tipo === 'Anticipo'` Y NO tiene `discountInfo.type === 'anticipo'` #### 2. Servicio + Anticipo Aplicado - **NO mostrar**: Notas de anticipo - **Condición**: Servicio normal con descuento de anticipo aplicado #### 3. Paciente Oncológico - **Mostrar**: Datos del médico (nombre, teléfono, cédula) - **Condición**: `movement.client.esOncologico === true` #### 4. Consentimiento Médico - **Mostrar**: Texto de consentimiento específico - **Condición**: `movement.client.consentimiento === true` --- ## 🔄 Plan de Desarrollo ### **FASE 1: Setup con Assets (45 min)** - [ ] Agregar librerías: `html2canvas` + `FileSaver.js` - [ ] Crear archivo `receipt.js` para lógica PNG - [ ] Crear archivo `receipt.css` para estilos móviles - [ ] Setup HTML base con assets structure - [ ] Test de carga de assets ### **FASE 2: Template Engine + Lógica de Casos (60 min)** - [ ] Sistema de detección de tipos de ticket - [ ] Templates dinámicos por caso de uso - [ ] Mapeo de datos del movimiento a template - [ ] Test de renderizado por tipo ### **FASE 3: Contenido Dinámico y Datos Médicos (45 min)** - [ ] Sección de consentimiento médico - [ ] Datos de pacientes oncológicos - [ ] Información de citas (fecha/hora) - [ ] Test con datos médicos reales ### **FASE 4: Notas de Anticipo Inteligentes (30 min)** - [ ] Lógica para mostrar/ocultar notas de anticipo - [ ] Templates condicionales - [ ] Test de casos anticipo vs servicio+anticipo ### **FASE 5: Generación PNG y Descarga (30 min)** - [ ] Configuración `html2canvas` optimizada para móvil - [ ] Sistema de nombres: `Ticket_{FOLIO}.png` - [ ] Función de descarga automática - [ ] Test de calidad de imagen ### **FASE 6: Testing Exhaustivo (45 min)** - [ ] Test matrix con todos los casos - [ ] Verificación de calidad PNG - [ ] Compatibilidad navegadores - [ ] Test de rendimiento --- ## 🧪 Test Scenarios ```javascript const testScenarios = [ // Básicos { desc: "Servicio simple", data: { tipo: "service", client: null, fechaCita: null }, expect: { noAnticipoNotes: true, noMedicalData: true } }, { desc: "Servicio con cita", data: { tipo: "service", client: "normal", fechaCita: "2025-01-15", horaCita: "10:00" }, expect: { hasAppointment: true } }, // Anticipos { desc: "Anticipo puro", data: { tipo: "Anticipo" }, expect: { hasAnticipoNotes: true } }, { desc: "Servicio + anticipo aplicado", data: { tipo: "service", discountInfo: { type: "anticipo" }}, expect: { hasAnticipoNotes: false } }, // Médicos { desc: "Paciente oncológico completo", data: { client: { esOncologico: true, nombreMedico: "Dr. Juan", telefonoMedico: "123456", cedulaMedico: "ABC123" } }, expect: { hasMedicalData: true, hasConsentText: true } } ]; ``` --- ## 📦 Dependencias Requeridas ### Librerías JavaScript ```html ``` ### Google Fonts ```css @import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@400;600;700&display=swap'); ``` --- ## 🚀 Integración con Sistema Actual ### Botón en Tabla de Tickets ```html ``` ### Función Principal ```javascript async function downloadReceiptPNG(movementId) { try { // 1. Obtener datos del movimiento const movement = await getMovementById(movementId); // 2. Analizar tipo de ticket const ticketType = analyzeTicketType(movement); // 3. Generar HTML del recibo const receiptHTML = generateReceiptHTML(movement, ticketType); // 4. Convertir a PNG const canvas = await html2canvas(receiptHTML, pngConfig); // 5. Descargar canvas.toBlob(blob => { saveAs(blob, `Ticket_${movement.folio}.png`); }); } catch (error) { console.error('Error generating receipt:', error); alert('Error al generar el recibo'); } } ``` --- ## 📏 Configuración PNG ```javascript const pngConfig = { scale: 2, // HD quality width: 400, // Mobile optimal width height: 'auto', backgroundColor: 'transparent', // Usar fondo del asset useCORS: true, // Para assets externos allowTaint: true, ignoreElements: (element) => { // Ignorar elementos que no queremos en el PNG return element.classList?.contains('no-png'); } }; ``` --- ## 🎯 Resultado Final **✅ Sistema que genera recibos PNG:** - Diseño profesional idéntico al mockup - Maneja TODOS los casos del negocio - Descarga automática con nombre correcto - No interfiere con sistema de impresión actual - Optimizado para móvil y WhatsApp **📱 Flujo de Usuario:** 1. Cliente termina servicio → Se imprime ticket térmico (como siempre) 2. Si cliente quiere recibo digital → Staff hace clic en "📱 Enviar Recibo" 3. Se descarga PNG → Staff envía por WhatsApp/email **Estimación Total: 4 horas de desarrollo + testing**