Files
whatsapp/services/BusinessHoursService.php
2026-01-13 01:48:33 -05:00

222 lines
6.2 KiB
PHP

<?php
/**
* Servicio de Horarios de Atención
* Detecta si el bot está dentro del horario de atención
* y proporciona mensajes personalizados
*/
class BusinessHoursService
{
private $db;
public function __construct()
{
$this->db = Database::getInstance();
}
/**
* Verifica si actualmente estamos en horario de atención
* @return bool
*/
public function isBusinessHours(): bool
{
$now = new DateTime('now', new DateTimeZone('America/Bogota'));
$dayOfWeek = (int)$now->format('N'); // 1=Lunes, 7=Domingo
$currentTime = $now->format('H:i');
// Domingo (7) siempre cerrado
if ($dayOfWeek === 7) {
return false;
}
// Sábado (6)
if ($dayOfWeek === 6) {
$saturdayHours = $this->getBusinessHoursConfig('business_hours_saturday');
return $this->isTimeInRange($currentTime, $saturdayHours);
}
// Lunes a Viernes (1-5)
$weekdayHours = $this->getBusinessHoursConfig('business_hours_weekday');
return $this->isTimeInRange($currentTime, $weekdayHours);
}
/**
* Obtiene el mensaje apropiado según el horario
* @return string
*/
public function getMessage(): string
{
if ($this->isBusinessHours()) {
return $this->getWelcomeMessage();
} else {
return $this->getOutOfHoursMessage();
}
}
/**
* Obtiene el mensaje de bienvenida
* @return string
*/
private function getWelcomeMessage(): string
{
$stmt = $this->db->prepare("
SELECT config_value
FROM system_config
WHERE config_key = 'welcome_message'
LIMIT 1
");
$stmt->execute();
$result = $stmt->fetch(PDO::FETCH_ASSOC);
if ($result) {
return $result['config_value'];
}
// Mensaje por defecto
return "¡Hola! 👋 Bienvenido(a) a nuestro servicio de WhatsApp.\n\nEscribe MENÚ para ver las opciones.";
}
/**
* Obtiene el mensaje fuera de horario
* @return string
*/
private function getOutOfHoursMessage(): string
{
$stmt = $this->db->prepare("
SELECT config_value
FROM system_config
WHERE config_key = 'out_of_hours_message'
LIMIT 1
");
$stmt->execute();
$result = $stmt->fetch(PDO::FETCH_ASSOC);
if ($result) {
return $result['config_value'];
}
// Mensaje por defecto
return "GRACIAS POR COMUNICARSE CON NOSOTROS ⏳\n\nEn este momento NO nos encontramos disponibles.\n\nTe responderemos lo antes posible en nuestro horario de atención.\n\n💻 Este es un mensaje automático\nGracias por tu comprensión 😊";
}
/**
* Obtiene la configuración de horarios
* @param string $key
* @return string
*/
private function getBusinessHoursConfig(string $key): string
{
$stmt = $this->db->prepare("
SELECT config_value
FROM system_config
WHERE config_key = ?
LIMIT 1
");
$stmt->execute([$key]);
$result = $stmt->fetch(PDO::FETCH_ASSOC);
return $result ? $result['config_value'] : '';
}
/**
* Verifica si una hora está dentro de un rango
* @param string $currentTime Formato HH:mm
* @param string $rangesString Formato "HH:mm-HH:mm,HH:mm-HH:mm"
* @return bool
*/
private function isTimeInRange(string $currentTime, string $rangesString): bool
{
if (empty($rangesString) || $rangesString === 'closed') {
return false;
}
// Dividir por comas para múltiples rangos (ej: "7:00-12:00,14:00-17:00")
$ranges = explode(',', $rangesString);
foreach ($ranges as $range) {
$times = explode('-', trim($range));
if (count($times) !== 2) {
continue;
}
$start = trim($times[0]);
$end = trim($times[1]);
if ($currentTime >= $start && $currentTime <= $end) {
return true;
}
}
return false;
}
/**
* Obtiene información detallada del horario actual
* @return array
*/
public function getCurrentStatus(): array
{
$now = new DateTime('now', new DateTimeZone('America/Bogota'));
$dayOfWeek = (int)$now->format('N');
$dayName = $this->getDayName($dayOfWeek);
$currentTime = $now->format('H:i');
$isOpen = $this->isBusinessHours();
return [
'is_open' => $isOpen,
'current_day' => $dayName,
'current_time' => $currentTime,
'day_of_week' => $dayOfWeek,
'timezone' => 'America/Bogota'
];
}
/**
* Obtiene el nombre del día en español
* @param int $dayNumber 1-7 (1=Lunes)
* @return string
*/
private function getDayName(int $dayNumber): string
{
$days = [
1 => 'Lunes',
2 => 'Martes',
3 => 'Miércoles',
4 => 'Jueves',
5 => 'Viernes',
6 => 'Sábado',
7 => 'Domingo'
];
return $days[$dayNumber] ?? 'Desconocido';
}
/**
* Determina si se debe mostrar el mensaje de fuera de horario
* @param string $phoneNumber
* @return bool
*/
public function shouldShowOutOfHoursMessage(string $phoneNumber): bool
{
if ($this->isBusinessHours()) {
return false;
}
// Verificar si ya se le envió el mensaje fuera de horario hoy
$stmt = $this->db->prepare("
SELECT id
FROM conversations
WHERE phone_number = ?
AND message_type = 'outgoing'
AND message_text LIKE '%NO nos encontramos disponibles%'
AND DATE(created_at) = CURDATE()
LIMIT 1
");
$stmt->execute([$phoneNumber]);
// Si ya se le envió hoy, no enviar de nuevo
return $stmt->fetch() === false;
}
}