Files
consultoria-as 9936deaa90 feat: Implementar PWA, Analytics, Reportes PDF y mejoras OCR
FASE 1 - PWA y Frontend:
- Crear templates/base.html, dashboard.html, analytics.html, executive.html
- Crear static/css/main.css con diseño responsivo
- Agregar static/js/app.js, pwa.js, camera.js, charts.js
- Implementar manifest.json y service-worker.js para PWA
- Soporte para captura de tickets desde cámara móvil

FASE 2 - Analytics:
- Crear módulo analytics/ con predictions.py, trends.py, comparisons.py
- Implementar predicción básica con promedio móvil + tendencia lineal
- Agregar endpoints /api/analytics/trends, predictions, comparisons
- Integrar Chart.js para gráficas interactivas

FASE 3 - Reportes PDF:
- Crear módulo reports/ con pdf_generator.py
- Implementar SalesReportPDF con generar_reporte_diario y ejecutivo
- Agregar comando /reporte [diario|semanal|ejecutivo]
- Agregar endpoints /api/reports/generate y /api/reports/download

FASE 4 - Mejoras OCR:
- Crear módulo ocr/ con processor.py, preprocessor.py, patterns.py
- Implementar AmountDetector con patrones múltiples de montos
- Agregar preprocesador adaptativo con pipelines para diferentes condiciones
- Soporte para corrección de rotación (deskew) y threshold Otsu

Dependencias agregadas:
- reportlab, matplotlib (PDF)
- scipy, pandas (analytics)
- imutils, deskew, cachetools (OCR)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 03:26:16 +00:00

123 lines
3.5 KiB
JavaScript

/**
* Sales Bot - PWA Registration and Install Prompt
*/
// Register Service Worker
if ('serviceWorker' in navigator) {
window.addEventListener('load', async () => {
try {
const registration = await navigator.serviceWorker.register('/service-worker.js');
console.log('Service Worker registered:', registration.scope);
// Check for updates
registration.addEventListener('updatefound', () => {
const newWorker = registration.installing;
newWorker.addEventListener('statechange', () => {
if (newWorker.state === 'installed' && navigator.serviceWorker.controller) {
// New version available
showUpdatePrompt();
}
});
});
} catch (error) {
console.error('Service Worker registration failed:', error);
}
});
}
// Install prompt handling
let deferredPrompt;
window.addEventListener('beforeinstallprompt', (e) => {
e.preventDefault();
deferredPrompt = e;
showInstallPrompt();
});
function showInstallPrompt() {
// Create install prompt UI
const prompt = document.createElement('div');
prompt.id = 'install-prompt';
prompt.className = 'install-prompt show';
prompt.innerHTML = `
<span>Instalar Sales Bot en tu dispositivo</span>
<button class="btn btn-primary" onclick="installPWA()">Instalar</button>
<button class="btn btn-secondary" onclick="dismissInstallPrompt()">Ahora no</button>
`;
document.body.appendChild(prompt);
}
async function installPWA() {
if (!deferredPrompt) return;
deferredPrompt.prompt();
const { outcome } = await deferredPrompt.userChoice;
console.log('Install prompt outcome:', outcome);
deferredPrompt = null;
dismissInstallPrompt();
if (outcome === 'accepted') {
if (window.Utils) {
window.Utils.showNotification('App instalada correctamente', 'success');
}
}
}
function dismissInstallPrompt() {
const prompt = document.getElementById('install-prompt');
if (prompt) {
prompt.remove();
}
}
function showUpdatePrompt() {
const updateBanner = document.createElement('div');
updateBanner.id = 'update-banner';
updateBanner.style.cssText = `
position: fixed;
bottom: 0;
left: 0;
right: 0;
background: #00d4ff;
color: #000;
padding: 15px;
text-align: center;
z-index: 9999;
`;
updateBanner.innerHTML = `
<span>Nueva version disponible</span>
<button onclick="updateApp()" style="margin-left: 15px; padding: 5px 15px; border: none; border-radius: 4px; cursor: pointer;">
Actualizar
</button>
`;
document.body.appendChild(updateBanner);
}
function updateApp() {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.getRegistration().then(registration => {
if (registration && registration.waiting) {
registration.waiting.postMessage({ type: 'SKIP_WAITING' });
}
});
}
window.location.reload();
}
// Detect if running as PWA
function isPWA() {
return window.matchMedia('(display-mode: standalone)').matches ||
window.navigator.standalone === true;
}
// Add PWA class to body if running as installed app
if (isPWA()) {
document.body.classList.add('pwa-mode');
}
// Export
window.installPWA = installPWA;
window.dismissInstallPrompt = dismissInstallPrompt;
window.isPWA = isPWA;