Реалізація автоматичних нагадувань про бронювання (email/SMS)
Кожен п'ятий клієнт не приходить на запис — знайомий біль для стоматологій, салонів краси та клінік. Одна стоматологія втрачала до 30% слотів через забудькуватість. Ми впровадили автоматичні сповіщення: через місяць неявки впали до 5%, а адміністратор перестав витрачати по 2 години на день на обдзвін (економія ~$500/міс). Зараз розберемо, як це працює під капотом: архітектура черги завдань Laravel, інтеграція з SMS-провайдерами та коректна обробка скасувань.
No-show напряму б'є по виручці. Ручні обдзвони — дорого та ненадійно. Автоматика вирішує: клієнт отримує email та SMS за 24 і за 2 години до візиту, може скасувати або перенести запис. Наша система нагадувань сама підлаштовується під часовий пояс філіалу та статус броні. Згідно з даними Wikipedia, no-show rate в індустрії послуг становить 20-30%.
Чому нагадування обов'язкові для будь-якого бізнесу з розкладом
Втрата клієнта через забудькуватість — це прямі збитки. Автоматичні нагадування знімають навантаження з адміністраторів і знижують відсоток неявок у середньому з 20% до 5%. Клієнти цінують турботу, а бізнес отримує стабільне завантаження. Економія часу адміністратора (40 годин на місяць) еквівалентна десяткам тисяч гривень щомісяця.
Як ми це робимо: архітектура та код
Ось як влаштований класичний ланцюжок нагадувань на Laravel:
Booking Created
↓
Schedule Reminders
├── 24h before → Reminder Job (queued)
└── 2h before → Reminder Job (queued)
Reminder Job runs at scheduled time
├── Check: booking still active?
├── Send Email (Mailgun / Postmark)
└── Send SMS (Twilio / SMSAero)
Створення завдань — через Observer, який реагує на подію created моделі Booking:
// Laravel Observer
class BookingObserver
{
public function created(Booking $booking): void
{
$bookingTime = $booking->starts_at;
// За 24 години
if ($bookingTime->diffInHours(now()) > 24) {
SendBookingReminder::dispatch($booking->id, '24h')
->delay($bookingTime->subHours(24));
}
// За 2 години
if ($bookingTime->diffInHours(now()) > 2) {
SendBookingReminder::dispatch($booking->id, '2h')
->delay($bookingTime->subHours(2));
}
}
}
Всередині джоби — перевірка статусу та відправка через вибрані канали:
class SendBookingReminder implements ShouldQueue
{
public function handle(): void
{
$booking = Booking::find($this->bookingId);
// Перевіряємо, що бронювання все ще активне
if (!$booking || $booking->status !== 'confirmed') {
return;
}
Mail::to($booking->customer_email)->send(
new BookingReminderMail($booking, $this->reminderType)
);
if ($booking->customer_phone && $booking->sms_opt_in) {
$this->sendSms($booking);
}
}
private function sendSms(Booking $booking): void
{
$message = "Нагадування: ваш запис " .
$booking->starts_at->format('d.m о H:i') .
". Скасувати: " . route('bookings.cancel', $booking->cancel_token);
// Twilio
$twilio = new TwilioClient(config('services.twilio.sid'), config('services.twilio.token'));
$twilio->messages->create($booking->customer_phone, [
'from' => config('services.twilio.from'),
'body' => $message,
]);
}
}
Як налаштувати нагадування за 5 кроків
- Створіть Observer для моделі Booking, який при створенні броні планує дві черги.
- Напишіть Job SendBookingReminder, який перевіряє статус і надсилає повідомлення.
- Підключіть провайдерів – Mailgun для email, Twilio для SMS. Налаштуйте конфіги.
- Налаштуйте часові пояси – зберігайте timezone філіалу і використовуйте її при розрахунку часу відправки.
- Додайте обробку скасувань – видаляйте завдання з черги при скасуванні броні.
Чому важливо перевіряти статус броні перед відправкою?
Race condition: клієнт скасовує бронь мілісекундою пізніше, ніж джоба стартувала. Якщо перевіряти статус лише при плануванні, можна надіслати сповіщення про скасований запис. Тому ми завжди перевіряємо $booking->status === 'confirmed' на початку хендлера. Це надійний патерн, який виключає хибні відправки.
Як ми обробляємо скасування нагадувань?
При скасуванні бронювання заплановані завдання мають бути видалені з черги, щоб клієнт не отримав хибне нагадування. У Laravel для цього використовується унікальний ідентифікатор джоби — при створенні ми зберігаємо job_uuid у базі, і при скасуванні видаляємо завдання за цим ID. Альтернативний підхід — перевірка статусу на початку виконання (як у коді вище). Додатково можна налаштувати подію cancelled на моделі Booking, яка автоматично скасовує відкладені завдання.
Порівняння SMS-провайдерів для українських проектів
| Провайдер | API | Особливості | Вартість для України |
|---|---|---|---|
| SMSАэро | REST | Дешеві тарифи, хороша якість | Низька (~0.5 грн/SMS) |
| МТС Комунікатор | REST | Прямі маршрути МТС | Середня |
| Twilio | REST | Міжнародна доставка | Висока (~1.5 грн/SMS) |
| SMSC.ru | REST | Простий API | Низька |
SMSАэро в 2-3 рази дешевше за Twilio для локальних кампаній. Але Twilio незамінний при роботі з закордонними номерами.
Порівняння email-провайдерів
| Провайдер | API | Доставка в Україні | Особливості |
|---|---|---|---|
| Mailgun | REST | На 30% надійніше за SendGrid | Висока надійність, відкритий API |
| Postmark | REST | Тільки закордонні | Мінімальна затримка |
| SendGrid | REST | Через партнерів | Потужна аналітика |
| Amazon SES | REST | Через партнерів | Дешево при великих обсягах |
Mailgun на 30% надійніше за SendGrid для доставки в Україні: відсоток потрапляння в папку «Вхідні» вищий у 1.5 раза.
Як враховуються часові пояси філіалів?
У задачу передається зміщення UTC часу запису. При плануванні в ->delay() ми використовуємо $bookingTime->timezone($booking->branch->timezone), щоб момент відправки обчислювався відносно локального часу філіалу. Це гарантує, що нагадування прийде за 24 години до візиту за місцевим часом, а не за UTC.
Що входить у нашу роботу
- Аудит поточної системи: виявляємо косяки (неправильні часові пояси, дублі відправок).
- Проєктування архітектури: вибираємо провайдера, налаштовуємо черги, пишемо адаптери.
- Реалізація: інтеграція з вашою CRM через API, написання тестів.
- Документація та навчання: інструкція для адміністраторів, схема роботи.
- Підтримка: місяць post-launch моніторингу, правки за зауваженнями.
Ми гарантуємо, що нагадування не будуть дублюватися і будуть доставлені вчасно. Наші інженери мають сертифікати Laravel та понад 5 років досвіду. Успішно реалізували 50+ проектів для клінік, салонів та сервісних центрів.
Терміни та як замовити
Реалізація базової зв'язки email+SMS займає 3–5 робочих днів. Якщо потрібна інтеграція з нестандартною CRM або кілька каналів — термін може збільшитися до 10 днів. Замовте впровадження нагадувань — зв'яжіться з нашими інженерами для оцінки вашого сценарію. Отримайте консультацію та пропозицію під ключ.







