feat(dashboard): LIA voz+saludo, proyección Chart.js, Excel, informe WA
- LIA: saludo de voz al abrir (1x/día), auto-escucha 3s, olas animadas - Gráfica de barras (Chart.js) con facturación real + proyección lineal - Exportar a Excel (.xls con HTML table, se abre directo en Excel) - Botón "Informe WA": envía resumen del día por WhatsApp a número elegido - Diseño accesible: texto más grande, botones claros para usuario adulto Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
a8752b9e9d
commit
34d0fed21b
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
/**
|
||||
* GET get_proyeccion.php
|
||||
* Facturación real por hora + proyección lineal para el resto del día.
|
||||
*/
|
||||
require_once __DIR__ . '/_helpers.php';
|
||||
requireTurnero();
|
||||
requireMethod('GET');
|
||||
|
||||
$pdo = db();
|
||||
$hoy = trim($_GET['fecha'] ?? date('Y-m-d'));
|
||||
if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $hoy)) $hoy = date('Y-m-d');
|
||||
|
||||
$ses = $pdo->prepare("SELECT id, inicio_at FROM turnero_sesiones WHERE fecha = ? LIMIT 1");
|
||||
$ses->execute([$hoy]);
|
||||
$sesion = $ses->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$sesion) {
|
||||
jsonOk(['labels'=>[],'real'=>[],'proyectado'=>[],'total_real'=>0,'total_proyectado'=>0]);
|
||||
}
|
||||
$sesId = (int)$sesion['id'];
|
||||
|
||||
// Facturación por hora real
|
||||
$stmt = $pdo->prepare(
|
||||
"SELECT HOUR(t.creado_at) AS hora,
|
||||
COALESCE(SUM(ts.total_cobrado), 0) AS total,
|
||||
COUNT(DISTINCT t.id) AS turnos
|
||||
FROM turnero_turnos t
|
||||
JOIN turnero_solicitudes ts ON ts.turno_id = t.id
|
||||
WHERE t.sesion_id = ? AND ts.total_cobrado > 0
|
||||
GROUP BY hora ORDER BY hora"
|
||||
);
|
||||
$stmt->execute([$sesId]);
|
||||
$porHora = [];
|
||||
foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $r) {
|
||||
$porHora[(int)$r['hora']] = ['total' => (float)$r['total'], 'turnos' => (int)$r['turnos']];
|
||||
}
|
||||
|
||||
$inicioH = $sesion['inicio_at'] ? (int)date('G', strtotime($sesion['inicio_at'])) : 6;
|
||||
$horaAct = (int)date('G');
|
||||
$finDia = 17; // 5pm cierre estimado
|
||||
|
||||
// Calcular tasa por hora basada en horas con datos
|
||||
$totalReal = array_sum(array_column($porHora, 'total'));
|
||||
$horasConDatos = max(1, $horaAct - $inicioH);
|
||||
$tasaPorHora = $totalReal / $horasConDatos;
|
||||
|
||||
$labels = $real = $proyectado = [];
|
||||
for ($h = $inicioH; $h <= max($finDia, $horaAct); $h++) {
|
||||
$labels[] = sprintf('%02d:00', $h);
|
||||
$real[] = isset($porHora[$h]) ? round($porHora[$h]['total']) : 0;
|
||||
$proyectado[] = ($h > $horaAct && $h <= $finDia) ? round($tasaPorHora) : null;
|
||||
}
|
||||
|
||||
$horasRestantes = max(0, $finDia - $horaAct);
|
||||
$totalProyectado = round($totalReal + ($tasaPorHora * $horasRestantes));
|
||||
|
||||
jsonOk([
|
||||
'labels' => $labels,
|
||||
'real' => $real,
|
||||
'proyectado' => $proyectado,
|
||||
'total_real' => $totalReal,
|
||||
'total_proyectado' => $totalProyectado,
|
||||
'tasa_por_hora' => round($tasaPorHora),
|
||||
]);
|
||||
Reference in New Issue
Block a user