Legan Studio
Все статьи
~ 18 мин чтения

Бот для логистики в MAX: трекинг и заявки от клиентов

Сценарии бота для логистической компании в MAX: расчёт стоимости, оформление заявки, трекинг груза, уведомления о статусах и интеграция с TMS.

  • MAX
  • логистика
  • сценарии

Логистический бизнес генерирует много типовых обращений: «сколько будет стоить», «где мой груз», «когда доставите», «можно перенести доставку». Если на эти вопросы отвечают живые диспетчеры, половина рабочего дня уходит на одни и те же ответы, а в пиковые сезоны телефония и почта захлёбываются. Бот в MAX закрывает эти запросы без участия операторов и держит клиента в курсе всю цепочку — от оформления заявки до выдачи груза получателю. Параллельно второй контур того же бота работает для водителей и диспетчеров: распределение заказов, статусы, фото подтверждения, координаты в реальном времени.

В этой статье разбираем три параллельных сценария — клиентский, водительский и диспетчерский, — а также интеграции с TMS/WMS, документооборот и нагрузочные ограничения. Все примеры — для российских реалий 2026 года: 1С, МойСклад, СДЭК, Почта России, DPD, Яндекс.Карты, 2GIS, электронные ТТН и УПД.

Три контура одного бота

Логистический бот в MAX — это не одно приложение, а три параллельных интерфейса с общей серверной частью:

КонтурКто пользуетсяКлючевые сценарии
КлиентскийОтправитель/получатель грузаРасчёт, заявка, трекинг, уведомления, претензии
ВодительскийВодители и курьеры на линииПолучение задания, статусы, фото, координаты, навигация
ДиспетчерскийДиспетчеры, логисты, начальники сменыРаспределение, мониторинг, реакция на ЧП, чаты смен

Технически это один Bot API в MAX, но разные FSM-сценарии и разные права. Разделение по user_role хранится в таблице bot_users: клиент видит только свои заказы, водитель — только назначенные ему задания, диспетчер — всю смену. Один и тот же телефон может быть в нескольких ролях (например, водитель на полставки + клиент сервиса), и FSM при старте спрашивает, в какой роли пользователь сегодня заходит.

Расчёт стоимости перевозки

Базовый клиентский сценарий — калькулятор перевозки: откуда, куда, что, габариты, срок. У междугородних перевозчиков есть тарифные сетки, которые легко перевести в формулу. У сборных грузов — расчёт по объёмному весу и зонам. У международной логистики — таможенные коэффициенты, и тут без интеграции с TMS не обойтись.

Технически логика такая: бот собирает параметры через FSM, отправляет POST в калькулятор (свой или вендорский), возвращает результат. Кэшировать имеет смысл только справочники городов и почтовых индексов — сами расчёты идут на актуальных тарифах, иначе клиент получит устаревшую цену и потом будет ругаться на «обман».

Объёмный вес считается стандартной формулой (длина × ширина × высота в см) / 5000 для авиадоставки и / 6000 для автодоставки. Бот должен показывать оба значения — фактический и объёмный — и считать тариф по большему. Это снижает количество споров у выдачи: «я платил за 5 кг, а вы говорите 18».

def calc_volumetric_weight(length_cm, width_cm, height_cm, mode="auto"):
    divisor = 5000 if mode == "air" else 6000
    return (length_cm * width_cm * height_cm) / divisor

def chargeable_weight(actual_kg, length_cm, width_cm, height_cm, mode):
    vol = calc_volumetric_weight(length_cm, width_cm, height_cm, mode)
    return max(actual_kg, vol)

Для сборных грузов и LTL (less-than-truckload) добавляется зональная сетка: страна — регион — город — район. Тариф в крупный город может быть в 2–3 раза дешевле, чем в посёлок в 50 км от него, и это надо честно показывать на этапе расчёта, а не «уточнять при оформлении».

Оформление заявки

После расчёта клиент нажимает «Оформить» — бот собирает контакт отправителя и получателя, точные адреса, желаемую дату забора, тип упаковки, особые условия (хрупкое, не кантовать, терморежим). Если клиент уже знаком, контакты подставляются из истории, и поля сворачиваются в «всё как обычно?».

Заявка уходит в TMS (1С:ТМС, Logist.Pro, собственная система). Возвращается номер заказа и ссылка на трекинг. Здесь критична идемпотентность: если пользователь нажмёт «Оформить» дважды (плохая связь, лагает MAX, нетерпеливый палец), заявка не должна создаваться дважды. Реализуется через unique-ключ на стороне TMS либо короткий лок в Redis на 30–60 секунд по ключу (user_id, hash(payload)).

Адреса забора и доставки лучше валидировать через Яндекс.Геокодер или DaData: пользователь пишет «Пушкина 10», а система возвращает нормализованный «г. Москва, ул. Пушкина, д. 10, кв. ?» с уточнением квартиры/офиса. Это сокращает количество промахов курьера на последней миле в 3–5 раз. 2GIS пригождается там, где Яндекс плохо знает дворовую разметку — в промзонах и логопарках.

Трекинг груза для клиента

Главный убийца времени диспетчера — запросы «где мой груз». Бот закрывает это отдельным сценарием: пользователь вводит номер заказа (или выбирает из списка своих) → бот возвращает текущий статус, последнее событие, прогноз по времени и, если груз в пути, — кнопку «Показать на карте» с актуальной точкой машины.

Источников статусов несколько:

  • Собственная TMS даёт логистические события (принят, на сортировке, в пути, прибыл на склад).
  • GPS-трекеры на машинах — координаты в реальном времени, скорость, остановки.
  • Подрядчики на последней миле — СДЭК, Почта России, DPD, Boxberry — пушат статусы по своим API.
  • Бот водителя — события, которые водитель проставляет вручную (взял груз, прибыл к получателю, выдал).

Все статусы собираются в единый Event Store (обычно отдельная таблица tracking_events с полями order_id, source, event_code, event_time, payload jsonb) и нормализуются в общий словарь. На выходе у пользователя — простая лента из 6–8 этапов, без сырого мусора вида STATUS_CODE_47 или DELIVERY_ATTEMPT_RESULT_3.

Бот для водителя

Второй контур — приложение водителя. Раньше это был отдельный мобильный клиент, который надо устанавливать, обновлять, обучать. Сейчас MAX закрывает 90% сценариев чатом + инлайн-кнопками + Mini App для карты.

Базовый сценарий смены:

  1. Водитель заходит в бот, нажимает «Начать смену», выбирает машину.
  2. Диспетчер видит водителя в пуле «свободные» и распределяет ему задания.
  3. Водитель получает уведомление: «Заказ №L-78231, забор в 14:00 по адресу X, доставка по адресу Y. Принять / Отказаться».
  4. На каждом этапе водитель шлёт статус кнопкой: «Выехал к отправителю», «Принял груз», «В пути», «Прибыл к получателю», «Выдал».
  5. На точке выдачи прикладывает фото подтверждения (груз + подпись получателя на бумажной ТН или фото электронной подписи).
  6. Если ЧП — отдельная кнопка «Проблема»: повреждение, отказ получателя, нет на месте, ДТП.

Координаты в реальном времени бот получает либо из встроенной геолокации MAX (если водитель явно поделился), либо из сторонних телематических систем (Wialon, GLONASSsoft, Omnicomm) через их API. Прятать факт сбора координат нельзя — водитель должен явно согласиться на смене, иначе попадаем под 152-ФЗ.

🚚 Заказ №L-78231

📦 Забор: г. Москва, ул. Складская, 14, к. 3
   Контакт: +7 (903) 555-12-34, Иван
   Слот: 14:00–16:00

📍 Доставка: г. Подольск, пр-т Юных Ленинцев, 8
   Контакт: +7 (915) 222-33-44, Мария
   Слот: до 19:00

Вес: 12 кг, объём: 0.08 м³
Особые условия: хрупкое, не кантовать

[ Принять ]  [ Отказаться ]  [ На карте ]

Фотофиксация и электронные документы

Фото на приёмке и выдаче — самая частая «страховка» от споров о повреждениях. Минимум:

  • На приёмке у отправителя: общий вид груза, упаковка со всех сторон, маркировка/номер места, состояние коробки.
  • На выдаче получателю: груз в момент передачи, подпись на бумажной ТН или экране, лицо получателя по согласию.

Фото уходят сразу в S3-совместимое хранилище (Yandex Object Storage, MinIO), в БД сохраняется только URL и метаданные (геокоординаты EXIF, время). При споре о повреждении за минуту поднимаются все фото по order_id.

Электронные ТТН и УПД через ЭДО (Контур.Диадок, СБИС, Такском) подключаются как отдельный модуль. Бот не сам формирует и подписывает документы, а триггерит формирование на стороне TMS/учётки и присылает водителю PDF-копию с QR-кодом для проверки на стороне получателя. Подписание УКЭП — на стороне ЭДО-провайдера; бот лишь показывает статус «подписан / ожидает подписи / отклонён».

Бот для диспетчера

Диспетчерский контур — это панель управления сменой прямо в чате. Базовые экраны:

  • Список открытых заявок — отсортирован по времени забора, цветовая маркировка по срочности.
  • Пул свободных водителей — кто на смене, где находится, какая машина, остаток рабочих часов.
  • Распределение — кнопка «Назначить» в карточке заявки → выбор водителя из пула или ручной ввод.
  • Мониторинг ЧП — отдельный канал, куда сыплются проблемные события: опоздания больше 15 минут, отказы получателей, сработки тревожной кнопки.
  • Чат смены — групповой чат всех активных водителей и диспетчеров; быстро объявить «всем — пробка на МКАД 78-й км, объезд через М-10».

Хорошая практика — реакции вместо ответов. Диспетчер увидел ЧП → ставит реакцию «🆘» — все остальные диспетчеры видят, что событие подхвачено. Это убирает классическую проблему «думал, ты ответишь / думал, ты ответишь».

Распределение заказов можно автоматизировать (алгоритм по близости водителя к точке забора, остаткам времени, типу машины), но финальное «принять/изменить» лучше оставлять диспетчеру — алгоритм не знает, что у Иванова сегодня день рождения и его лучше не грузить «вечеркой».

Уведомления для клиента: какие события и когда

Не нужно слать сообщение на каждый чих. Реальные триггеры:

  1. Заявка создана — номер, ссылка на трекинг.
  2. Груз принят у отправителя — фото упаковки, ФИО водителя.
  3. Передан на следующий хаб — для сборных грузов и междугородки.
  4. Груз в городе получателя — за сутки до выдачи.
  5. Прибудет сегодня — за 2–4 часа до выдачи, со слотом.
  6. Курьер выехал — за 30–60 минут.
  7. Доставлен — фото подтверждения, кнопка «Оценить доставку».
  8. Проблема — опоздание, повреждение, отказ получателя, недозвон.

Восьмой пункт — самый важный. Здесь бот должен не просто уведомить, а сразу предложить варианты: связаться с диспетчером, перенести доставку на завтра, оставить груз на ближайшем ПВЗ, оформить возврат отправителю. Каждая опция — отдельная инлайн-кнопка с понятным CTA, а не «свяжитесь с менеджером».

Тихие часы — обязательно. Уведомления типа 4–6 не должны прилетать в 23:00–08:00 по часовому поясу получателя (поле tz в профиле, по умолчанию — IP-геолокация при первом старте + явное подтверждение).

Интеграции с TMS, WMS и API курьеров

Бот сам по себе не источник правды — он канал. Реальные данные живут в TMS/WMS/учётной системе. Самые частые в РФ:

СистемаТип APIЛимитыЧто отдаёт
1С:ТМСOData/HTTP-сервисыЗависит от хостингаЗаказы, рейсы, ТТН, водители, машины
Logist.ProREST JSON100 req/minПолный TMS-контур
МойСкладREST JSON45 req/3 секОстатки, заказы, отгрузки (для логистики магазинов)
1С:УТ + 1С:РозницаCommerceML, RESTЗависит от хостингаЗаказы, остатки, контрагенты
Wialon / GLONASSsoftREST + websocket60 req/minGPS-координаты, телематика

API курьерских:

  • СДЭК — REST /v2/calculator/tariff, /v2/orders, /v2/deliverypoints. Возвращает тарифы, оформляет заказы, отдаёт ПВЗ. Webhooks по статусам — обязательно подписать.
  • Почта Россииtariff.russianpost.ru для расчёта, otpravka.pochta.ru для оформления, tracking.russianpost.ru для трекинга. API нестабильный, обязательно делать ретраи и таймауты.
  • DPD — SOAP (да, до сих пор), отдельный SDK на Java/.NET, для Python/Go — обёртка через zeep.
  • Boxberry — XML API, медленный, но широкая сеть ПВЗ в малых городах.
  • 5Post — REST, быстро растёт сеть постаматов в продуктовых сетях.

Универсальное правило: обмен с внешними системами всегда асинхронный, через очередь (NATS, RabbitMQ, Redis Streams) с ретраями и backoff. Если СДЭК упал на 2 часа — ваши заявки накапливаются в очереди и догоняются потом, а не валятся клиенту в лицо ошибкой 500.

Карты, маршруты и навигация

Карта в боте нужна в двух местах: клиент смотрит, где едет машина, водитель смотрит маршрут до точки.

Для клиента подойдёт статичный фрагмент карты с пином (Static API Яндекс.Карт или 2GIS) — отправляем картинкой, не грузим Mini App. Обновление — раз в 1–2 минуты по событию или по запросу пользователя.

Для водителя сложнее. Встроенный навигатор внутри MAX не сделать, поэтому бот отдаёт диплинк в Яндекс.Навигатор / 2GIS:

yandexnavi://build_route_on_map?lat_to=55.7558&lon_to=37.6173
dgis://2gis.ru/routeSearch/rsType/car/to/37.6173,55.7558

Водитель тапает кнопку → открывается родной навигатор → строит маршрут. Это в разы стабильнее любого встроенного решения.

Для распределения заявок диспетчеру помогает геокластеризация: показать на карте все открытые заборы и всех свободных водителей, чтобы быстро видеть, кому что ближе. Это уже Mini App с Yandex.Maps JS API, отдельная разработка на 2–3 недели.

KPI водителей и аналитика

Через бот удобно собирать сырьё для KPI водителей:

  • Среднее время на точке (от «прибыл» до «выехал») — выявляет медленных.
  • Срыв слота (опоздание больше 15 минут к окну выдачи) — главный показатель качества для клиента.
  • Доля доставок с первой попытки — здоровая норма 88–95%.
  • Жалобы клиентов — привязываются к водителю по assigned_driver_id в заказе.
  • Расход топлива на 100 км — из телематики, аномалии флагает скрипт.

Дашборд диспетчера / руководителя — обычно отдельный веб-интерфейс (Metabase, собственный на React), а в боте лежит только агрегированная сводка по запросу: «KPI смены за вчера», «топ-5 нарушителей слота за неделю».

Безопасность и доступ

Логистика возит деньги — буквально, в виде грузов. Поэтому базовая гигиена:

  • Каждый запрос статуса заказа проверяет, что заказ принадлежит этому пользователю (по user_id или phone). Иначе любой угадает чужой номер и узнает адрес.
  • Адреса доставки не светятся в публичных каналах и не попадают в логи в открытом виде (хеш или маскирование).
  • Финансовые действия (отмена с возвратом средств, изменение получателя, перенаправление груза) проходят через подтверждение оператором.
  • Водительский контур требует привязки к телефону + подтверждение менеджером; нельзя зарегистрироваться водителем самостоятельно.
  • Доступ к панели диспетчера — отдельная роль, выдаётся только из админки, не через бот.

Логи действий с заказами хранятся минимум 3 года (для соответствия требованиям 152-ФЗ и претензионной работы) в отдельной audit-таблице с actor_id, action, target_id, payload_diff, ts.

Стек и нагрузка

Типичный набор:

  • Bot-сервис — Go или Python (FastAPI + aiogram-подобная обвязка под MAX Bot API).
  • Очередь — NATS или RabbitMQ для событий из TMS/GPS/подрядчиков.
  • PostgreSQL — заказы, пользователи, кэш справочников, история событий, audit.
  • Redis — FSM, idempotency-ключи, антифлуд, короткоживущий кэш.
  • S3-совместимое хранилище — фото подтверждений, сканы документов.
  • Адаптеры — отдельные сервисы под каждый внешний источник, чтобы их падение не валило бот.

При нагрузке от тысячи заявок в день и 50–100 водителей на смене бот спокойно живёт на одном сервере 4 vCPU / 8 GB. Узкое место — это не Bot API MAX, а интеграции с подрядчиками: их API часто медленные и нестабильные. Закладывайте 30% бюджета времени именно на адаптеры с ретраями, circuit breaker и фолбэками.

При росте до 10 000+ заявок/день добавляются: репликация Postgres под чтение трекинга, шардинг истории событий по месяцам, отдельный кластер для GPS-телеметрии (в Postgres она душит индексы, лучше TimescaleDB или ClickHouse).

ROI: когда бот окупается

Грубая прикидка для средней транспортной компании 50 машин / 30 диспетчеров / 5 000 заказов в месяц:

СтатьяДо ботаС ботомЭкономия/месяц
Звонки «где груз»1500 шт × 4 мин × 250 ₽/час100 шт≈25 000 ₽
Звонки «оформить»800 шт × 6 мин × 250 ₽/час200 шт≈18 000 ₽
Срывы слотов12%6%≈40 000 ₽ (компенсации + удержание)
Споры о повреждениях25 шт/мес8 шт/мес≈30 000 ₽

Итого порядок 100–120 тыс. ₽/мес экономии при разовой стоимости разработки 800 тыс. — 1.5 млн ₽ и поддержке 30–60 тыс. ₽/мес. Окупаемость 8–14 месяцев. Дальше — чистый плюс плюс рост NPS на 15–25 пунктов.

Чек-лист готовности логистического бота к запуску

  • Идемпотентность создания заявки (Redis-лок + unique-индекс в TMS).
  • Адреса нормализуются через Яндекс.Геокодер или DaData до сохранения.
  • Объёмный вес считается и показывается на этапе расчёта.
  • Все три роли (клиент / водитель / диспетчер) разведены по FSM и правам.
  • Координаты водителя собираются только с явного согласия (152-ФЗ).
  • Фото приёмки и выдачи уходят в S3, метаданные сохраняются в БД.
  • Электронные ТТН/УПД через ЭДО, бот показывает статус подписания.
  • Уведомления уважают тихие часы по часовому поясу получателя.
  • Восьмой триггер (проблема) предлагает 3–5 вариантов решения, а не «свяжитесь с менеджером».
  • Карта для клиента — статичной картинкой, для водителя — диплинк в Яндекс.Навигатор / 2GIS.
  • Все интеграции с курьерами (СДЭК, Почта, DPD, Boxberry) — асинхронные с ретраями.
  • KPI водителей собираются автоматически и доступны диспетчеру в боте.
  • Audit-лог финансовых действий хранится не менее 3 лет.
  • Чат смены и реакция «🆘» по ЧП работают в реальном времени.
  • Нагрузочное тестирование на 3× ожидаемый пик (предновогодний сезон).

Итого

Бот для логистики в MAX — это не «ещё один чат», а замена половины работы диспетчерской и водительского планшета одновременно. Калькулятор, заявка и трекинг закрывают клиента; бот водителя со статусами и фото — линию; диспетчерский контур с распределением и реакциями — управление сменой. Сложность не в самом боте, а в адаптерах к TMS, телематике и подрядчикам последней мили: именно они определяют, насколько данные в чате будут совпадать с реальностью на дороге и складе. Запустите эти три контура — и поток типовых обращений упадёт в 5–8 раз, а NPS вырастет за счёт того, что клиент впервые видит свой груз, а не догадывается о нём.

Частые вопросы

Какие задачи закрывает бот для логистической компании в MAX?

Три параллельных контура. Клиентский — расчёт стоимости перевозки, оформление заявки, трекинг груза, уведомления о ключевых событиях, претензии и переносы доставки. Водительский — получение задания, статусы (взял / еду / прибыл / выдал), фото подтверждения, координаты в реальном времени, диплинки в Яндекс.Навигатор и 2GIS. Диспетчерский — распределение заказов по водителям, мониторинг ЧП, реакции на проблемные события, чат смены, агрегированные KPI. Всё это в одном Bot API MAX, разведённое по ролям через FSM и таблицу bot_users.

Как реализовать расчёт стоимости в логистическом боте MAX?

Бот собирает параметры через FSM (откуда, куда, что, габариты, срок), отправляет POST в калькулятор (свой или вендорский), возвращает результат. Объёмный вес считается формулой длина × ширина × высота / 5000 для авиа и / 6000 для авто; тариф берётся по большему из фактического и объёмного веса, чтобы не было споров у выдачи. Для сборных грузов и LTL добавляется зональная сетка страна-регион-город-район. Кэшировать имеет смысл только справочники городов и индексов — сами расчёты идут на актуальных тарифах, иначе клиент получит устаревшую цену.

Как избежать дублирования заявок при оформлении в боте?

Через идемпотентность. Если пользователь нажмёт «Оформить» дважды (плохая связь, лагает MAX), заявка не должна создаваться дважды. Реализуется через unique-ключ на стороне TMS либо короткий лок в Redis на 30–60 секунд по комбинации user_id и hash(payload). Адреса при этом валидируются через Яндекс.Геокодер или DaData: пользователь пишет «Пушкина 10», система возвращает нормализованный адрес с уточнением квартиры или офиса. Это сокращает количество промахов курьера на последней миле в 3–5 раз. 2GIS используется там, где Яндекс плохо знает дворовую разметку — в промзонах и логопарках.

Как организовать работу водителя через бот в MAX?

Водитель заходит в бот, нажимает «Начать смену», выбирает машину. Диспетчер видит его в пуле свободных и распределяет задания. На каждом этапе водитель шлёт статус кнопкой: «Выехал к отправителю», «Принял груз», «В пути», «Прибыл к получателю», «Выдал». На точке выдачи прикладывает фото подтверждения. При ЧП — отдельная кнопка «Проблема» с типом события. Координаты собираются либо встроенной геолокацией MAX (с явного согласия по 152-ФЗ), либо через телематику Wialon/GLONASSsoft. Для маршрута бот отдаёт диплинк в Яндекс.Навигатор или 2GIS — родной навигатор стабильнее любого встроенного решения.

Откуда бот берёт данные для трекинга груза?

Из четырёх источников, объединённых в единый Event Store в таблице tracking_events. Собственная TMS даёт логистические события (принят, на сортировке, в пути, прибыл на склад). GPS-трекеры на машинах — координаты в реальном времени, скорость, остановки. Подрядчики последней мили (СДЭК, Почта России, DPD, Boxberry, 5Post) пушат статусы через webhooks. Бот водителя — события, которые водитель проставляет вручную. Все статусы нормализуются в общий словарь, на выходе у пользователя простая лента из 6–8 этапов без сырого мусора вида STATUS_CODE_47.

По каким событиям бот должен уведомлять клиента и когда молчать?

Восемь триггеров: заявка создана, груз принят у отправителя, передан на следующий хаб, груз в городе получателя, прибудет сегодня (за 2–4 часа), курьер выехал (за 30–60 минут), доставлен с фото, проблема. Восьмое событие — самое важное: бот не просто уведомляет, а сразу предлагает 3–5 вариантов решения (связаться с диспетчером, перенести на завтра, оставить в ПВЗ, вернуть отправителю), каждое — отдельной инлайн-кнопкой. Тихие часы обязательны: уведомления о промежуточных статусах не приходят в 23:00–08:00 по часовому поясу получателя.

Какой стек используют для бота логистической компании в MAX?

Bot-сервис на Go или Python (FastAPI с обвязкой под MAX Bot API). Очередь NATS или RabbitMQ для событий из TMS, GPS и подрядчиков. PostgreSQL для заказов, пользователей, истории событий и audit-лога. Redis для FSM, idempotency-ключей и антифлуда. S3-совместимое хранилище (Yandex Object Storage, MinIO) для фото подтверждений и сканов документов. Адаптеры — отдельные сервисы под каждый внешний источник, чтобы их падение не валило бот. При тысяче заявок в день и 50–100 водителях на смене бот живёт на одном сервере 4 vCPU / 8 GB. При росте до 10 000+ заявок добавляется реплика Postgres под чтение трекинга и отдельный кластер под GPS-телеметрию (TimescaleDB или ClickHouse).