222 lines
6.2 KiB
PHP
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;
|
|
}
|
|
}
|