
Клієнт веде невелику e-commerce операцію — товари ручної роботи, 50–80 замовлень у завантажений день. Кожен ранок починався однаково: відкрити Нову Пошту, перевірити кожен трек-номер, відкрити KeepinCRM, перемістити кожну угоду на відповідний етап. Сорок п’ять хвилин щодня на задачу, яку має володіти машина.
Проблема
Ручний трекінг замовлень у такому обсязі — не просто нудно, це джерело помилок. Пропущені зміни статусу означали затримані фолоу-апи. Посилки поверталися відправнику, бо ніхто не помічав статус “зберігання закінчується через 2 дні” аж до третього дня. Фіскальні чеки генерувалися вручну після підтвердження доставки, що іноді означало повне забуття.
У клієнта KeepinCRM була налаштована з етапами угод, що напряму мапилися на стани життєвого циклу посилки: Відправлено, В дорозі, Очікує отримання, Доставлено, Ініційовано повернення, Повернуто. Мапінг був чіткий. Проблема була в тому, що хтось мав виконувати його вручну, двічі на день.
Рішення
Go-демон на невеликому VPS, що опитує API трекінгу Нової Пошти кожні 30 хвилин і керує пайплайном з трьох подальших дій.
Стадія 1: опитування Нової Пошти
Нова Пошта надає JSON API для трекінгу. Демон підтримує таблицю SQLite з активними трек-номерами та їхнім останнім відомим статусом. На кожному циклі опитування:
statuses, err := np.GetTrackingStatuses(ctx, activeTTNs)
for _, s := range statuses {
if s.StatusCode != cache.Get(s.TTN) {
events <- TrackingEvent{TTN: s.TTN, OldStatus: cache.Get(s.TTN), NewStatus: s.StatusCode}
cache.Set(s.TTN, s.StatusCode)
}
}
Коди статусів Нової Пошти числові. Демон мапить їх на назви етапів KeepinCRM через конфігураційний файл — клієнт може коригувати мапінг без зміни коду.
Стадія 2: пайплайн KeepinCRM
KeepinCRM має REST API для керування угодами. Коли надходить подія трекінгу, демон знаходить угоду, пов’язану з цим трек-номером (збережену як кастомне поле при створенні угоди), і переміщує її на цільовий етап:
dealID, err := crm.FindDealByTTN(ctx, event.TTN)
if err != nil { log.Error(...); continue }
err = crm.MoveDeal(ctx, dealID, stageMap[event.NewStatus])
Якщо FindDealByTTN нічого не повертає — угоду закрито, заархівовано, або TTN введено неправильно — подія логується, і в оперативний Telegram-чат клієнта надсилається повідомлення. Жодних тихих збоїв.
Стадія 3: фіскальні чеки через Checkbox
Україна вимагає фіскальні чеки для роздрібних продажів. Клієнт використовував Checkbox, у якого є API для програмної генерації чеків. Коли угода переходить у стан Доставлено, демон отримує позиції угоди з KeepinCRM і надсилає запит на створення чека в Checkbox:
if event.NewStatus == StatusDelivered {
items, err := crm.GetDealLineItems(ctx, dealID)
receiptID, err := checkbox.CreateReceipt(ctx, items, deal.CustomerPhone)
crm.AddNote(ctx, dealID, "Fiscal receipt: "+receiptID)
}
ID чека записується назад у KeepinCRM як нотатка угоди. Клієнт може миттєво його підняти, якщо запитає покупець.
Стадія 4: сповіщення TurboSMS
Останній крок надсилає SMS покупцю, коли статус посилки змінюється на Очікує отримання — найчутливіше до часу сповіщення, оскільки зберігання на Новій Пошті обмежене п’ятьма робочими днями.
TurboSMS має простий HTTP API. Шаблон повідомлення конфігурований:
Ваше замовлення #{order_id} чекає у відділенні {branch_address}.
Зберігання до {expiry_date}. Трекінг: https://novaposhta.ua/tracking/#{ttn}
Адреса відділення й дата закінчення зберігання беруться з відповіді трекінгу Нової Пошти.
Результати
Після двох тижнів паралельної роботи з ручним трекінгом (для валідації коректності) клієнт перейшов на повністю автоматизований режим:
- Нуль ручних переміщень угод з моменту запуску. Демон обробляє 150–200 подій трекінгу на день.
- Фіскальні чеки генеруються автоматично для кожного доставленого замовлення. Раніше близько 15% пропускалися або затримувалися.
- Приблизно 2 години на день повернуто — ранкова сесія трекінгу й денна перевірка, обидві скасовані.
- Дві події повернення відправнику спіймано рано в перший місяць, які були б пропущені за ручного процесу.
Демон працює вже чотири місяці. Єдине операційне втручання — зміна схеми API Нової Пошти, що зламала парсинг коду статусу на три години — спіймано через Telegram-алерт, виправлено оновленням конфігурації, без втрати даних.