# Sprint 1.5 — Etapa 7: PDF ROI — Páginas 2-5 con identidad InQ > **Objetivo:** completar el rediseño del PDF ROI aplicando identidad InQ a las páginas 2, 3 y 4. Implementar la trayectoria del ahorro acumulado en la página 5 (que en Etapa 6 quedó como placeholder). > > **Pre-requisitos:** Etapa 6 cerrada — Página 1 del PDF ROI con KPI Hero gradiente, banner narrativo, grid 2x2, Top 3. PDF ROI con 5 páginas (página 5 placeholder). > > **Etapa siguiente:** Etapa 8 — PDFs Actual y Automatizado con identidad InQ aplicada (rediseño consistente con el ROI). --- ## 1. Alcance estricto ### Sí entra - ✅ Página 2 (Comparación por actividad) — aplicar paleta naranja a tabla, mantener estructura - ✅ Página 3 (Análisis del ahorro + Transparencia metodológica) — rediseñar con paleta InQ - ✅ Página 4 (Nota metodológica) — paleta InQ aplicada - ✅ Página 5 (NUEVA — Trayectoria del ahorro acumulado) — gráfico SVG nativo en jsPDF (sin html2canvas) - ✅ Mantener consistencia visual con la página 1 ya rediseñada ### NO entra - ❌ Modificar la página 1 (cerrada en Etapa 6) - ❌ Refinamientos visuales del KPI Hero, Top 3, banner narrativo (agendados para Etapa 11 — polish final) - ❌ Resolver fórmulas truncadas en nota metodológica (Sprint 2 — font embedding) - ❌ Resolver caracteres Unicode rotos en general (Sprint 2) - ❌ Modificar PDFs Actual y Automatizado (Etapa 8) --- ## 2. Decisiones ya tomadas (no consultar de nuevo) | Decisión | Justificación | |---|---| | Trayectoria del ahorro: SVG nativo en jsPDF (no html2canvas) | Brief sección 3.2 — html2canvas borrosea el chart | | Trayectoria empieza en (Año 0, -inversión), no en (0, 0) | Decisión Etapa 3 — TODO.md | | Tabla comparativa con header naranja `#FFF8ED` + border-bottom `#F59845` | Brief sección 2.5 | | Sección Transparencia con fondo `#FFFBEB` + border `#F59E0B` | Brief sección 2.4 (warning) | | PDF ROI mantiene 5 páginas | Decisión Etapa 6 | | Nota metodológica con caracteres Unicode rotos se mantiene | Sprint 2 | --- ## 3. Especificación detallada por página ### 3.1 Página 2 — Comparación por actividad **Estado actual (post-Etapa 6):** - Header denso ✓ - Tabla con `Actividad / Act. (USD) / Auto. (USD) / Ahorro (USD) / Ahorro % / Prob.` - Texto "(*) Actividades en negrita están marcadas como automatizables" - Footer "Página 2 de 5" **Cambios en Etapa 7:** ``` TABLA (autotable): Header row: - Fondo: #FFF8ED (inq-orange-lighter) - Border-bottom: 1.5pt solid #F59845 - Padding: 8pt 6pt - Texto: 10pt / peso 500 / color #92400E (inq-orange-dark) - Letter-spacing: 0.5pt - Uppercase Body row (default / actividad automatizable): - Fondo: white - Border-bottom: 0.5pt solid #E2E8F0 - Padding: 7pt 6pt - Texto: 10pt / peso 400 / color #0F172A - Números: font mono, color #0F172A Body row (actividad NO automatizable): - Fondo: #F8FAFC (slate-50) - Texto: color #94A3B8 (más tenue) - Em dash "—" en columnas Ahorro y Ahorro % Total row (si aplica): - Fondo: #FFF8ED - Border-top: 1.5pt solid #F59845 - Texto: 10pt / peso 500 / color #0F172A ``` **Mantener el texto "(*) Actividades en negrita..."** con el formato actual. ### 3.2 Página 3 — Análisis del ahorro + Transparencia **Estado actual (post-Etapa 6):** - Título "Análisis del ahorro" - Sección "Composición del ahorro" con 3 bullets de actividades - Sección "Trayectoria del ahorro acumulado" (texto narrativo) - Sección "Transparencia metodológica" con caja ámbar (cuando aplica) - Footer "Página 3 de 5" **Cambios en Etapa 7:** **Sección "Composición del ahorro":** ``` Título: - Texto: "COMPOSICIÓN DEL AHORRO" - Tamaño: 11pt - Peso: 500 - Color: #92400E (inq-orange-dark) - Letter-spacing: 1pt - Uppercase - Margin-bottom: 8mm Texto descriptivo: - Tamaño: 11pt - Color: #0F172A - Line-height: 1.5 - Margin-bottom: 6mm Bullets: - Bullet symbol: "•" - Texto: 10pt / color #475569 - Línea: " • [actividad]: USD [N] ([NN]% del ahorro total)" - Margin-bottom: 3mm cada uno ``` **Sección "Trayectoria del ahorro acumulado" (texto):** ``` Mantener el bloque narrativo actual. Aplicar paleta: - Título: 11pt / peso 500 / color #92400E / uppercase - Texto: 11pt / color #475569 / line-height 1.5 NOTA: el gráfico de la trayectoria va en página 5, no acá. En esta página solo el texto narrativo descriptivo. ``` **Sección "Transparencia metodológica" (cuando aplica):** ``` Caja: - Fondo: #FFFBEB (warning-bg) - Border: 0.5pt solid #F59E0B (warning) - Padding: 12pt 14pt - Border-radius: 6pt - Margin-top: 10mm Título: - Texto: "⚠ Transparencia metodológica" - Tamaño: 11pt - Peso: 500 - Color: #92400E - NOTA: el ⚠ (U+26A0) puede no renderizar. Si no funciona, usar texto plano "[!]" o "Transparencia metodológica" sin símbolo. Texto: - Tamaño: 10pt - Peso: 400 - Color: #78350F (text on warning) - Line-height: 1.6 Bullets de casos (cuando ROI > 1000%): - Frecuencia anual del proceso sobreestimada - Costo automatizado por ejecución subestimado - Inversión en automatización subestimada Formato: - "• [caso]" con bullet symbol • - Margin-bottom 3mm ``` ### 3.3 Página 4 — Nota metodológica **Estado actual (post-Etapa 6):** - Sigue con caracteres `£` (Σ) y `"` (−) rotos. Decisión Sprint 2. **Cambios en Etapa 7:** ``` Título: - Texto: "NOTA METODOLÓGICA — ANÁLISIS DE ROI" - Tamaño: 11pt - Peso: 500 - Color: #92400E (inq-orange-dark) - Letter-spacing: 1pt - Uppercase - Margin-bottom: 10mm Caja contenedora (opcional, sutil): - Fondo: #F8FAFC (slate-50) - Padding: 14pt - Border-radius: 4pt - Border-left: 2pt solid #94A3B8 (text-tertiary) Cada fórmula (5-6 bloques): Sub-título: - Tamaño: 10pt - Peso: 600 - Color: #0F172A - Margin-bottom: 2mm Fórmula: - Tamaño: 10pt - Font-family: mono (para alineación) - Color: #475569 - Line-height: 1.5 - Margin-bottom: 6mm ``` **Mantener el contenido textual actual:** - Costo por ejecución actual - Costo por ejecución automatizado - Ahorro anual - Payback (meses) - Ahorro acumulado - ROI anualizado ### 3.4 Página 5 — Trayectoria del ahorro acumulado (NUEVA) Esta es la página técnicamente más compleja de Etapa 7. Reemplaza el placeholder de Etapa 6. **Layout vertical de la página 5:** ``` ┌─────────────────────────────────────────────────────────┐ │ HEADER ESTÁNDAR │ └─────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────┐ │ TÍTULO: TRAYECTORIA DEL AHORRO ACUMULADO │ │ │ │ Subtítulo narrativo (1-2 líneas): │ │ "Evolución del ahorro neto acumulado a lo largo del │ │ horizonte de [N] años. El payback se alcanza en el │ │ mes [N]." │ └─────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────┐ │ GRÁFICO SVG NATIVO (60-70% del alto disponible) │ │ │ │ Eje Y (USD acumulado): │ │ - 0 al medio │ │ - Rango: de -inversion a +max_acumulado │ │ │ │ Eje X (tiempo en meses o años): │ │ - 0 a horizon_months │ │ - Labels: "Año 0", "Año 1", "Año 2", "Año 3" │ │ │ │ Curva: │ │ - Inicio: (Año 0, -inversion) → punto rojo │ │ - Cruza el cero en payback_month → marker │ │ - Final: (Año N, ahorro_acumulado_final) │ │ │ │ Área NEGATIVA (antes del payback): │ │ - Fill: #FEE2E2 (light red) │ │ │ │ Área POSITIVA (después del payback): │ │ - Fill: #FED7AA (light orange) │ │ │ │ Línea principal: │ │ - Color: #F59845 (inq-orange) │ │ - Grosor: 1.5pt │ │ │ │ Marker vertical en payback: │ │ - Línea vertical punteada, color #B45309 │ │ - Label "Payback: [N.N] meses" (offset 4mm a la │ │ derecha del marker para no superponer eje Y) │ └─────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────┐ │ ANOTACIONES (al pie del gráfico): │ │ - Inversión inicial: USD [N] │ │ - Ahorro acumulado al final: USD [N] │ │ - Multiplicador de retorno: [N.N]× la inversión │ └─────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────┐ │ FOOTER: Página 5 de 5 │ └─────────────────────────────────────────────────────────┘ ``` **Implementación técnica del gráfico SVG nativo:** Usar primitivas de jsPDF directamente (`doc.line`, `doc.rect`, `doc.text`, `doc.setFillColor`, `doc.setDrawColor`). **NO usar html2canvas** — el chart se ve borroso con conversión a imagen. Pseudocódigo: ```typescript function drawTrajectoryChart(doc, config) { const { x, y, width, height, data, paybackMonth, currency } = config; // 1. Dibujar ejes const yZero = y + (height * (data.maxNegative / (data.maxPositive - data.maxNegative))); doc.setDrawColor(148, 163, 184); // text-tertiary doc.line(x, yZero, x + width, yZero); // eje X (en y=0) doc.line(x, y, x, y + height); // eje Y // 2. Dibujar área negativa (antes del payback) doc.setFillColor(254, 226, 226); // #FEE2E2 // ... path complejo // 3. Dibujar área positiva (después del payback) doc.setFillColor(254, 215, 170); // #FED7AA // ... path complejo // 4. Dibujar línea principal doc.setDrawColor(245, 152, 69); // #F59845 doc.setLineWidth(1.5); // doc.lines() para path de la línea // 5. Dibujar marker de payback doc.setDrawColor(180, 83, 9); // #B45309 doc.setLineDashPattern([2, 2], 0); // línea vertical en x = payback // 6. Labels de ejes doc.setFontSize(8); doc.setTextColor(100, 116, 139); // labels "Año 0", "Año 1", etc. // 7. Label del payback (offset a la derecha) doc.text("Payback: " + formatPayback(paybackMonth), x_payback + 4, y_payback); } ``` **Datos para construir el gráfico:** ```typescript // Cálculo de la trayectoria const monthsArray = Array.from({length: horizonMonths + 1}, (_, i) => i); const trajectoryData = monthsArray.map(month => ({ month, acumulado: -inversion + (annualSavings / 12) * month })); // Encontrar el mes exacto del payback (cuando acumulado cruza 0) const paybackMonth = inversion / (annualSavings / 12); ``` --- ## 4. Validaciones automatizadas mandatorias ``` PDF ROI debe cumplir: 1. 5 páginas, todas portrait 2. Página 5 ahora tiene contenido real (NO placeholder): - Título "TRAYECTORIA DEL AHORRO ACUMULADO" presente - Gráfico SVG embebido (detectado por análisis de píxeles: presencia de naranja #F59845 + áreas rojas/naranjas claras) - Anotaciones al pie con cifras 3. Página 2 (Tabla): - Header de tabla con fondo naranja claro (#FFF8ED visible en análisis) - Border-bottom naranja en header - Em dash "—" en filas no automatizables (Ahorro y Ahorro %) 4. Página 3 (Análisis + Transparencia): - Título "COMPOSICIÓN DEL AHORRO" en naranja oscuro - Caja de Transparencia presente cuando ROI > 1000% (fondo ámbar) - Bullets de casos (cuando aplica) 5. Página 4 (Nota metodológica): - Título "NOTA METODOLÓGICA — ANÁLISIS DE ROI" en naranja oscuro - 5-6 sub-secciones con fórmulas - Caracteres £ y " todavía rotos (Sprint 2) — esperado 6. Sin regresiones: - Página 1 SIN CAMBIOS visualmente - Footers correctos en todas las páginas (1, 2, 3, 4, 5 de 5) - "InQ ROI", "Powered by InQuality" presentes - "Process Cost Platform" ausente 7. PDFs Actual y Automatizado: idénticos a Etapa 6 8. Tests previos verdes: ≥ 483 + nuevos de Etapa 7 ``` --- ## 5. Entregables (Definition of Done) ``` [ ] Página 2 (Tabla) con paleta InQ aplicada [ ] Página 3 (Análisis + Transparencia) con paleta InQ aplicada [ ] Página 4 (Nota metodológica) con paleta InQ aplicada [ ] Página 5 con gráfico SVG nativo de trayectoria del ahorro [ ] Trayectoria empieza en (Año 0, -inversión), cruza 0 en payback, termina en (Año N, ahorro_acumulado_final) [ ] Áreas roja y naranja diferenciadas (antes/después del payback) [ ] Marker vertical en payback con label "Payback: N.N meses" [ ] Anotaciones al pie del gráfico (inversión, acumulado, multiplicador) [ ] Página 1 NO MODIFICADA [ ] PDFs Actual y Automatizado NO MODIFICADOS [ ] 8 validaciones automatizadas confirmadas [ ] Tests previos verdes + nuevos tests del gráfico SVG (al menos 4 casos) [ ] npm run build limpio [ ] PDF presentado para validación visual [ ] Decisiones por iniciativa documentadas según política CLAUDE.md ``` --- ## 6. Reporte final a entregar 1. Tabla de archivos modificados/creados 2. 8 validaciones automatizadas confirmadas (resultado de cada una) 3. Cantidad final de tests verdes 4. **PDF ROI con paths absolutos del filesystem para que el usuario abra en Finder** - NO usar enlaces vscode-webview, que no funcionan fuera de VS Code - Path tipo `/Users/marcos/.../tests/e2e/__output__/etapa-7-roi.pdf` 5. PDFs Actual y Automatizado regenerados (para confirmar no-regresión) 6. **Detalle del gráfico SVG de trayectoria:** - Coordenadas del punto de inicio (debería ser y < 0) - Coordenadas del payback (debería ser y = 0) - Coordenadas del final (debería ser y > 0) - Esto valida que la curva está bien construida matemáticamente 7. Hallazgos no esperados 8. Decisiones tomadas por iniciativa (con clasificación según niveles) --- ## 7. Reglas operativas 1. **NO TOCAR LA PÁGINA 1.** Cerrada en Etapa 6. Cualquier cambio visual ahí es Nivel 3 (consultar previa). Refinamientos están agendados para Etapa 11. 2. **NO TOCAR PDFs Actual y Automatizado.** Etapa 8 los rediseña. 3. **NO ARREGLAR FÓRMULAS TRUNCADAS O UNICODE.** Sprint 2 — font embedding. Si te tienta, pará. 4. **Para el gráfico SVG, usar SOLO primitivas de jsPDF.** Sin html2canvas, sin canvas, sin librerías externas. El chart se construye con `doc.line`, `doc.rect`, `doc.text`. 5. **Política de iniciativa proactiva refinada (de Etapa 5):** - Cualquier cambio que afecte layout, paginación, o contenido visible más allá del scope: mínimo Nivel 2 (ejecutar y reportar) - Cambio que choca con restricción explícita del prompt: Nivel 3 (consultar previo) - Cambio en página 1 o en PDFs no-ROI: SIEMPRE Nivel 3 en esta etapa 6. **Si la implementación del gráfico SVG nativo se complica más de 2 horas, consultá.** Hay caminos intermedios (chart como imagen pre-renderizada del web app, etc.) que podemos evaluar. 7. **Si encontrás contradicción** entre prompt y código: PARÁ y consultá. --- ## 8. Por qué esta etapa importa La página 5 es donde el reporte demuestra **rigor técnico**. El cliente que abra el PDF en una reunión va a ver: - Página 1: el resumen ejecutivo con el número grande (KPI Hero) - Página 5: la curva financiera que justifica ese número Sin la página 5, el KPI Hero es "te creo o no". Con la página 5, es **evidencia visual** de cómo se construye el ahorro a lo largo del tiempo. Es la diferencia entre vendedor y consultor. Si la curva queda mal, el reporte pierde credibilidad. Si queda bien, vale como diferenciador frente a competencia. Apuntá alto.