← усі кейси
Інтернет-магазин з відділом продажів E-commerce / Клієнтський сервіс ·

Хвіст замовлення: три сценарії, після яких замовлення тихо помирає

Замовлення оформлене, але не оплачене, посилка лежить на відділенні, клієнт не бере слухавку. Три сценарії, у яких магазин втрачає вже зароблене - і один сервіс, що працює з усіма трьома.

  • Три сценарії в одному конвеєрі: несплачені реквізити, посилка на відділенні, недодзвон
  • Гейт за фактичним станом доставки відсіює третину хибних адресатів, яким нагадування було б помилкою
  • Приблизно кожне четверте нагадування про оплату закінчується оплатою протягом доби
  • 40-50 замовлень щомісяця, які раніше поверталися назад, тепер доходять до клієнта
Python 3.12FastAPIAPSchedulerSQLiteDocker Compose

Найдорожчий клієнт - той, який уже погодився купити. Реклама відпрацювала, менеджер поговорив, замовлення в системі. Далі мало б бути найпростіше.

А далі воно тихо помирає. Реквізити надіслані, але не оплачені. Посилка приїхала і лежить на відділенні, доки не поїде назад. Клієнт не бере слухавку, і його просто закривають як «не вдалося звʼязатися».

У всіх трьох випадках потрібне одне й те саме: вчасно нагадати - і нагадати саме тому, кому це доречно. Про те, як повідомлення технічно доходить до клієнта, у нас є окремий кейс; цей - про рішення, кому його взагалі не варто надсилати.

3
сценарії втрати в одному конвеєрі
33%
хибних адресатів відсіяно одним правильним гейтом
кожне 4-те
нагадування закінчується оплатою

Проблема: три способи втратити вже зароблене

Ці три сценарії не схожі один на одного за причиною, але однакові за наслідком. Гроші вже вкладені в те, щоб клієнт дійшов до оформлення, а покупка не відбувається.

Де саме зникає вже оформлене замовлення

💳 Реквізити без оплати

  • Клієнт отримав реквізити і відклав на потім
  • Замовлення висить, склад не починає збірку
  • Через кілька днів привід купити вже вивітрився

📦 Посилка лежить

  • Доїхала до відділення і чекає, доки не поїде назад
  • Магазин платить за зворотну доставку, а харчові продукти не завжди можна повернути в продаж
  • Це 40-50 замовлень щомісяця

📵 Недодзвон

  • Менеджер набрав, клієнт не відповів
  • Раніше в цьому місці кожен писав руками, як умів
  • Або не писав узагалі, і замовлення закривалось як «не вдалося звʼязатися»

Кожен сценарій окремо здається дрібницею, яку «треба просто не забувати». Разом вони дають постійний потік втрат, який ніхто не бачить цілком, бо він розмазаний по трьох різних місцях.

Як автоматизація це вирішує

Сервіс регулярно проходить по замовленнях у роботі, визначає, до якого з трьох сценаріїв належить кожне, і перевіряє фактичний стан справ - не те, що записано в картці, а те, що є насправді.

Далі замовлення проходить через набір гейтів. Якщо всі пройдені, клієнт отримує повідомлення в месенджері. Якщо ні, замовлення або чекає далі, або потрапляє в ранковий список менеджеру - там уже потрібна жива людина.

Один тік: три сценарії, один набір гейтів
Замовлення в роботі який сценарій фактичний стан доставки чи оплати
гейти і вік повідомлення клієнту перевірка доставки ранковий список менеджеру

Головна знахідка: статус замовлення бреше

Здавалося б, кому нагадувати про посилку, видно зі статусу замовлення: «очікує в пункті самовивезення». Це очевидне джерело правди, і саме на ньому будувалась перша версія.

Перевірка на живих даних показала інше. Зі 171 замовлення в цьому статусі реально лежали на відділенні 111, а 57 клієнтів свою посилку вже забрали - просто статус ніхто не переставив.

Реальний зріз: 171 замовлення в статусі «очікує в пункті самовивезення»
Реально лежить на відділенні111
Клієнт уже забрав, статус не переставили57
Уже поїхало назад3

Третина людей отримала б повідомлення «заберіть посилку», тримаючи цю посилку вдома.

Для клієнта таке повідомлення - прямий сигнал, що магазин не знає, що відбувається з його замовленням. Тому головним гейтом став фактичний стан доставки з боку перевізника, а статус замовлення відсунувся на другорядну роль.

Друга пастка того самого роду: годинник

Щоб вирішити, чи вже час нагадувати, потрібен момент відліку. Найдоступніше поле - час останнього оновлення доставки, і воно виглядає логічним.

Насправді воно оновлюється при кожній синхронізації з перевізником. Через це 109 зі 111 посилок виглядали б як «прибули щойно», і жодне нагадування ніколи б не надійшло. Правильний годинник - момент, коли замовлення востаннє змінило статус.

Що це дало бізнесу

Приблизно кожне четверте нагадування про оплату закінчується оплатою протягом доби. Це не про переконування, а про те, що людині просто вчасно нагадали про річ, яку вона вже вирішила купити.

Зі сценарію з посилками магазин повертає собі 40-50 замовлень щомісяця, які раніше їхали назад. Плюс третина адресатів, яким повідомлення було б помилкою, тепер його не отримує взагалі.

Межу системи варто назвати чесно. Замовлення старші за десять днів автоматика не чіпає - вона передає їх менеджеру, бо на такій дистанції автоматичне нагадування вже не працює, там потрібна розмова. Сервіс не рятує всі втрачені замовлення, він знімає ту частину, яку можна закрити вчасним повідомленням.

Як це влаштовано всередині

Далі - інженерна частина

Наступний розділ пояснює, як система влаштована. Якщо вас цікавить лише результат, його можна пропустити - нижче є розділ про те, кому це підходить.

Половина коду тут - це умови, за яких повідомлення НЕ надсилається. Кожен гейт зʼявився після того, як стало зрозуміло, кому саме писати не можна.

Гейти: сім умов, і всі мають бути виконані
Факт доставкиГоловна умова: фактичний стан з боку перевізника, а не статус у картці замовлення. Саме цей гейт відсіює третину адресатів
Вік відЗамовленню має бути щонайменше три доби. Раніше нагадувати немає сенсу - людина ще памʼятає про нього сама
Вік доСтарше десяти діб автоматика не бере. Такі замовлення йдуть менеджеру: там уже потрібна людина, а не повідомлення
Ручна позначкаЯкщо менеджер поставив «не нагадувати», система мовчить. Людське рішення завжди старше за автоматичне
Список відмовНомер не має бути в списку тих, хто відмовився від повідомлень або в кого месенджера немає
Робоче вікноЧас рахується за годинником клієнта, а не сервера. Нагадування о шостій ранку шкодить більше, ніж його відсутність
Без повторівПо цьому замовленню в цьому сценарії раніше не писали. Друге нагадування про те саме - це вже настирливість

Порядок перевірки тут не косметичний. Гейти перевіряються до відсічки за віком - інакше причина «занадто старе» ховає справжню причину «клієнт уже забрав», і в журналі неможливо побачити, що логіка бракована.

Дрібниці, які видно клієнту

Група працює під кількома вивісками. Назва магазину в тексті береться з джерела замовлення: клієнт одного бренду не має читати в повідомленні назву іншого.

Перевізник називається брендом, без юридичної особи-відправника, хоча в довіднику він записаний саме з нею. Якщо перевізника в довіднику немає взагалі, бренд визначається за форматом номера накладної.

Доставка кожного повідомлення перевіряється окремо. Ті, у кого месенджера немає, автоматично потрапляють у список виключень, і гроші на них більше не витрачаються.

Ціна помилки в тестуванні

У першій версії режим тестової відправки працював не так, як здавалося. Він слав увесь пакет на тестовий номер і при цьому позначав справжніх клієнтів як оброблених - тобто після одного тестового прогону вони вже ніколи не отримали б справжнє нагадування.

Виправлено так, що тестовий прогін зупиняється після першого повідомлення і нічого не позначає. Урок формулюється просто: тестовий режим має бути безпечним не тільки для клієнта, а й для журналу.

Кому це підходить

Магазинам з післяплатою і самовивозом, будь-кому, хто відправляє через відділення перевізника, і будь-якому бізнесу, де між «клієнт погодився» і «клієнт заплатив» проходить кілька днів.

Ознака, за якою легко перевірити, чи це про вас: якщо у вас є замовлення, про які ніхто не памʼятає, і ви дізнаєтесь про них тільки коли посилка повертається назад - так, це про вас.

Половина роботи такої системи - вирішити, кому писати. Друга половина - вирішити, кому не писати.

Потрібне схоже рішення?

Опишіть задачу - підберу архітектуру під ваш бюджет і дані.