132 lines
5.1 KiB
PHP
132 lines
5.1 KiB
PHP
<?php
|
|
/**
|
|
* GET /api/kpi_actividad.php
|
|
*
|
|
* Devuelve métricas de actividad de pacientes por rango de fechas:
|
|
* - Por día: usuarios únicos que escriben y agendamientos creados.
|
|
* - Por día de la semana: agregado del rango seleccionado.
|
|
*
|
|
* Parámetros GET:
|
|
* desde (YYYY-MM-DD) — fecha inicio, default hoy-29 días
|
|
* hasta (YYYY-MM-DD) — fecha fin, default hoy
|
|
*/
|
|
|
|
require_once __DIR__ . '/../config/config.php';
|
|
|
|
error_reporting(E_ERROR | E_PARSE);
|
|
ini_set('display_errors', '0');
|
|
|
|
requireAuthentication();
|
|
|
|
header('Content-Type: application/json; charset=utf-8');
|
|
header('Cache-Control: no-store');
|
|
|
|
try {
|
|
$db = Database::getInstance();
|
|
|
|
// ── Rango de fechas ──────────────────────────────────────
|
|
$hoy = date('Y-m-d');
|
|
$desde = $_GET['desde'] ?? date('Y-m-d', strtotime('-29 days'));
|
|
$hasta = $_GET['hasta'] ?? $hoy;
|
|
|
|
// Sanitizar: solo fechas válidas
|
|
if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $desde)) $desde = date('Y-m-d', strtotime('-29 days'));
|
|
if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $hasta)) $hasta = $hoy;
|
|
// No permitir rangos invertidos
|
|
if ($desde > $hasta) [$desde, $hasta] = [$hasta, $desde];
|
|
|
|
// ── Mensajes entrantes por día (usuarios únicos) ─────────
|
|
$msgRows = $db->fetchAll("
|
|
SELECT
|
|
DATE(created_at) AS fecha,
|
|
COUNT(DISTINCT user_id) AS usuarios,
|
|
COUNT(*) AS total_mensajes
|
|
FROM conversations
|
|
WHERE direction = 'incoming'
|
|
AND DATE(created_at) BETWEEN ? AND ?
|
|
GROUP BY DATE(created_at)
|
|
ORDER BY fecha ASC
|
|
", [$desde, $hasta]);
|
|
|
|
// ── Agendamientos (turnos creados) por día ───────────────
|
|
$turnosRows = $db->fetchAll("
|
|
SELECT
|
|
DATE(creado_at) AS fecha,
|
|
COUNT(*) AS agendamientos
|
|
FROM turnero_turnos
|
|
WHERE DATE(creado_at) BETWEEN ? AND ?
|
|
GROUP BY DATE(creado_at)
|
|
ORDER BY fecha ASC
|
|
", [$desde, $hasta]);
|
|
|
|
// ── Construir mapa fecha → datos combinados ──────────────
|
|
$dias = [];
|
|
|
|
// Generar todos los días del rango para que no haya huecos
|
|
$cur = new DateTime($desde);
|
|
$fin = new DateTime($hasta);
|
|
while ($cur <= $fin) {
|
|
$f = $cur->format('Y-m-d');
|
|
$dias[$f] = ['fecha' => $f, 'usuarios' => 0, 'total_mensajes' => 0, 'agendamientos' => 0];
|
|
$cur->modify('+1 day');
|
|
}
|
|
|
|
foreach ($msgRows as $r) {
|
|
if (isset($dias[$r['fecha']])) {
|
|
$dias[$r['fecha']]['usuarios'] = (int)$r['usuarios'];
|
|
$dias[$r['fecha']]['total_mensajes'] = (int)$r['total_mensajes'];
|
|
}
|
|
}
|
|
foreach ($turnosRows as $r) {
|
|
if (isset($dias[$r['fecha']])) {
|
|
$dias[$r['fecha']]['agendamientos'] = (int)$r['agendamientos'];
|
|
}
|
|
}
|
|
|
|
$porDia = array_values($dias);
|
|
|
|
// ── Agrupado por día de la semana (0=Domingo … 6=Sábado) ─
|
|
$semana = [
|
|
0 => ['dia' => 'Domingo', 'usuarios' => 0, 'agendamientos' => 0],
|
|
1 => ['dia' => 'Lunes', 'usuarios' => 0, 'agendamientos' => 0],
|
|
2 => ['dia' => 'Martes', 'usuarios' => 0, 'agendamientos' => 0],
|
|
3 => ['dia' => 'Miércoles', 'usuarios' => 0, 'agendamientos' => 0],
|
|
4 => ['dia' => 'Jueves', 'usuarios' => 0, 'agendamientos' => 0],
|
|
5 => ['dia' => 'Viernes', 'usuarios' => 0, 'agendamientos' => 0],
|
|
6 => ['dia' => 'Sábado', 'usuarios' => 0, 'agendamientos' => 0],
|
|
];
|
|
|
|
foreach ($porDia as $d) {
|
|
$dow = (int)(new DateTime($d['fecha']))->format('w'); // 0=Dom
|
|
$semana[$dow]['usuarios'] += $d['usuarios'];
|
|
$semana[$dow]['agendamientos'] += $d['agendamientos'];
|
|
}
|
|
|
|
// ── Totales del rango ────────────────────────────────────
|
|
$totalUsuarios = array_sum(array_column($porDia, 'usuarios'));
|
|
$totalMensajes = array_sum(array_column($porDia, 'total_mensajes'));
|
|
$totalAgendamientos = array_sum(array_column($porDia, 'agendamientos'));
|
|
|
|
// Día de semana pico (más usuarios)
|
|
$picoDow = array_keys($semana, max($semana, fn($a,$b) => $a['usuarios'] <=> $b['usuarios']))[0] ?? null;
|
|
$picoDow = array_reduce(array_keys($semana), fn($carry, $k) => ($semana[$k]['usuarios'] > $semana[$carry]['usuarios'] ? $k : $carry), 0);
|
|
|
|
echo json_encode([
|
|
'ok' => true,
|
|
'desde' => $desde,
|
|
'hasta' => $hasta,
|
|
'totales' => [
|
|
'usuarios' => $totalUsuarios,
|
|
'mensajes' => $totalMensajes,
|
|
'agendamientos' => $totalAgendamientos,
|
|
'pico_semana' => $semana[$picoDow]['dia'] ?? '—',
|
|
],
|
|
'por_dia' => $porDia,
|
|
'por_dia_semana' => array_values($semana),
|
|
], JSON_UNESCAPED_UNICODE);
|
|
|
|
} catch (Exception $e) {
|
|
http_response_code(500);
|
|
echo json_encode(['ok' => false, 'error' => $e->getMessage()]);
|
|
}
|