- 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>
90 lines
3.3 KiB
PHP
90 lines
3.3 KiB
PHP
<?php
|
|
/**
|
|
* POST enviar_informe_dia.php
|
|
* Envía por WhatsApp un resumen del día al número indicado.
|
|
* Body JSON: { phone: string }
|
|
*/
|
|
require_once __DIR__ . '/_helpers.php';
|
|
require_once __DIR__ . '/../../../services/WhatsAppService.php';
|
|
requireMethod('POST');
|
|
requireTurnero();
|
|
|
|
$body = inputJson();
|
|
$phone = preg_replace('/[^0-9]/', '', $body['phone'] ?? '');
|
|
if (strlen($phone) < 7) jsonError('Número de teléfono inválido.');
|
|
|
|
$pdo = db();
|
|
$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) jsonError('No hay sesión activa hoy.');
|
|
$sesId = (int)$sesion['id'];
|
|
|
|
// Resumen de estados
|
|
$stmt = $pdo->prepare("SELECT estado, COUNT(*) AS n FROM turnero_turnos WHERE sesion_id = ? GROUP BY estado");
|
|
$stmt->execute([$sesId]);
|
|
$estados = [];
|
|
foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $r) $estados[$r['estado']] = (int)$r['n'];
|
|
$total = array_sum($estados);
|
|
$atendidos = ($estados['finalizado'] ?? 0);
|
|
$enEspera = ($estados['espera'] ?? 0) + ($estados['en_recepcion'] ?? 0) + ($estados['en_espera_lugar'] ?? 0) + ($estados['en_servicio'] ?? 0);
|
|
$ausentes = ($estados['ausente'] ?? 0);
|
|
|
|
// Tiempos promedio
|
|
$tRow = $pdo->prepare(
|
|
"SELECT
|
|
ROUND(AVG(TIMESTAMPDIFF(SECOND, creado_at, COALESCE(inicio_recepcion_at, NOW())) / 60), 0) AS espera,
|
|
ROUND(AVG(TIMESTAMPDIFF(SECOND, inicio_lugar_at, COALESCE(fin_lugar_at, NOW())) / 60), 0) AS servicio,
|
|
ROUND(AVG(TIMESTAMPDIFF(SECOND, creado_at, fin_lugar_at) / 60), 0) AS total
|
|
FROM turnero_turnos WHERE sesion_id = ?"
|
|
);
|
|
$tRow->execute([$sesId]);
|
|
$t = $tRow->fetch(PDO::FETCH_ASSOC);
|
|
|
|
// Facturación
|
|
$fRows = $pdo->prepare(
|
|
"SELECT ts.metodo_pago, SUM(ts.total_cobrado) AS total, COUNT(*) AS n
|
|
FROM turnero_solicitudes ts
|
|
JOIN turnero_turnos tt ON tt.id = ts.turno_id
|
|
WHERE tt.sesion_id = ? AND ts.total_cobrado > 0
|
|
GROUP BY ts.metodo_pago"
|
|
);
|
|
$fRows->execute([$sesId]);
|
|
$fact = $fRows->fetchAll(PDO::FETCH_ASSOC);
|
|
$totalFact = array_sum(array_column($fact, 'total'));
|
|
|
|
// Armar mensaje
|
|
$fecha = date('d/m/Y');
|
|
$hora = date('H:i');
|
|
$msg = "📊 *Informe del día - Lab. Ximena Caicedo*\n";
|
|
$msg .= "📅 {$fecha} · {$hora}\n\n";
|
|
$msg .= "👥 *Turnos:*\n";
|
|
$msg .= "• Total: {$total}\n";
|
|
$msg .= "• Finalizados: {$atendidos}\n";
|
|
if ($enEspera) $msg .= "• En atención/espera: {$enEspera}\n";
|
|
if ($ausentes) $msg .= "• Ausentes: {$ausentes}\n";
|
|
$msg .= "\n";
|
|
|
|
if ($fact) {
|
|
$msg .= "💰 *Facturación:*\n";
|
|
foreach ($fact as $f) {
|
|
$msg .= "• {$f['metodo_pago']}: $" . number_format((float)$f['total'], 0, ',', '.') . " ({$f['n']} pac.)\n";
|
|
}
|
|
$msg .= "• *Total: $" . number_format($totalFact, 0, ',', '.') . "*\n\n";
|
|
}
|
|
|
|
$msg .= "⏱ *Tiempos promedio:*\n";
|
|
$msg .= "• Espera hasta recepción: " . ($t['espera'] ?? '—') . " min\n";
|
|
$msg .= "• Servicio en muestras: " . ($t['servicio'] ?? '—') . " min\n";
|
|
$msg .= "• Total puerta a puerta: " . ($t['total'] ?? '—') . " min\n";
|
|
|
|
try {
|
|
$wa = new WhatsAppService('turnero');
|
|
$wa->sendMessage($phone, $msg);
|
|
jsonOk(['mensaje' => "Informe enviado a {$phone}"]);
|
|
} catch (\Throwable $e) {
|
|
jsonError('Error al enviar: ' . $e->getMessage());
|
|
}
|