Привет, Хабр. Меня зовут Андрей, я бэкенд-разработчик в команде Flowwow. 

Я довольно давно работаю в компании и хочу рассказать об истории создания  собственного сервиса доставки (не без боли) и интеграциях с крупными игроками, которые нам удалось реализовать. 

Приходит тот день, когда бизнес задает себе философский вопрос «что дальше?», в нашем случае это «куда расти маркетплейсу?». Такой вопрос касается всей команды, включая ИТ. Увидев бэкенд в моей роли, вы наверняка ожидаете техническую мясорубку. Не без этого, но во многом хочу рассказать про сам путь. 

Мы развиваем платформу Flowwow, это маркетплейс для продавцов и покупателей, где магазины размещают свои товары, клиенты выбирают, а курьеры принимают заказы на доставку. 

Доставка цветов и подарков — дело деликатное. Вы можете выбрать прекрасный букет, его соберут из свежих цветов, но есть финальный, самый важный штрих, — доставка. Пару лет назад мы поняли, что здесь не все зависит от нашего сервиса. И это нужно исправить. Было две предпосылки:

  • желание расти и масштабировать бизнес,

  • автоматизация ручных процессов.

Сейчас у нас средняя оценка всего клиентского сервиса 4,9. И, конечно, к такому результату мы пришли не сразу — через боль, ошибки и забавные истории. Обо всем по порядку. 

Доставка 1.0. Свободу для всех

Сначала у нас было желание создать сервис со свободным входом людей, где каждый мог поработать курьером и заработать сумму на карманные расходы. Все просто: курьер регистрируется в приложении, указывает свое имя, присылает фото персональных данных и видео о себе. После нам требовалось время на модерацию, иногда до 3–4 дней. Успешное ее прохождение = уведомления о новых заказах.

Подход выявил, что люди есть люди, у них бывают свои проблемы, которые часто лежат вне технической плоскости. Например, курьеры могли заболеть, пропасть в виду форс-мажоров или просто утилизировать подарок в ближайшей урне по своим личным причинам. Это помимо проблем языкового барьера и незнания карты города.

Тук-тук, вам букет

Мы пробовали решить вышеописанные проблемы — блокировать средства с банковских карт курьеров до завершения доставки, создавать интерактивную карту с указанием маршрута, предварительными уведомлениями о начале работы и высоком спросе в конкретное время. 

В результате при росте числа курьеров мы получили еще проблемы:

  • Экспоненциальный рост ручного сопровождения доставки со стороны нашей поддержки;

  • Видимый рост проблем в полях: курьеры могли не понимать, как работает приложение, или просто теряться в городе;

  • Невозможность прогнозировать загруженность доставки в определенный период и, соответственно, управлять количеством заказов.

Было принято волевое решение, и проект в первой редакции был приостановлен.

Доставка с помощью других или доставка 2.0

С ручным контролем покончено, и надо автоматизировать все, что можно автоматизировать. Какой у нас есть вариант?

Отдадим операционные процессы на откуп третьему лицу, а там уже будут заниматься нашими делами, за комиссию. В третьи лица мы заложили более дружелюбный подтекст и назвали их «кураторами» курьеров. Это были отдельные специалисты на аутсорсе, которые следили за исполнением доставки. В их распоряжении — админка, сделанная специально для них, в подчинении — курьеры с товарами. Мы провели обучение кураторов, подготовили видеоматериалы, рассказали, как работать с курьерами, находящимися в подчинении, как пользоваться админкой и назначать заказы на доставку. 

И принялись наблюдать.

POV: курьер доставляет букет

Девушка возвращается домой, идет по улице спального района. Ее догоняет машина. Водитель-курьер, включив эмпирический метод, протягивает ей букет на ходу через окно машины — держите, вам цветы! Девушка возмущена и тут же звонит своему другу, чтобы рассказать о ситуации. Друг тоже возмущен, так как эти цветы от него (таки да, водитель угадал). Девушка бежит за машиной по дворам, успевает на светофоре и отбирает букет у водителя, тоже на ходу.

Это история со счастливым концом, и все это забавно на бэке, но представьте, что этот букет — ваш сюрприз близкому человеку. 

Еще были недопонимания со стороны кураторов: после недели работы один из них заявил «А я думал надо только комиссию собирать с курьеров». Ну, возвращаемся снова к ручному контролю — на еженедельной основе созваниваемся с кураторами, объясняем, зачем они здесь и какие функции выполняют. После трех недель стало ясно, что со стороны очень сложно найти человека, который бы понимал весь бизнес-процесс доставки, и мы взяли специалиста по обучению кураторов. И еще добавили специалистов в техподдержку. А еще взяли нового менеджера. В общем, начали закрывать проблемы людьми. После трех месяцев мы поняли, что такой подход тоже не до конца рабочий.

К каким выводам пришли:

  • что плохо, когда кураторы — люди извне. Они не горят общим делом компании, не болеют за сервис и качество и назначают курьеров без какой-либо модерации;

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

Мы снова приостановили проект, поняв, что с этим надо что-то делать, что-то делать… 

Доставка 3.0. Или каждому курьеру по заказу

Проанализировав вышеописанные проблемы, мы решили реализовать сервис заново и сильно изменили подход к логике приема курьеров и выдачи заказов курьерам. 

Какая теперь логика? Пройдемся по пунктам: 

Найм курьеров

Курьер должен оформиться как самозанятый. На его счет мы будем производить автоматические выплаты за выбранный период работы. Такое изменение позволило автоматизировать процесс выплаты, включая управление штрафами и бонусами для конкретного курьера. 

Расписание работы

В старой системе не было никакого понимания, сколько людей будет завтра, в каких районах они могут начать работу и как правильно распределить нагрузку заказов по ним. В новой редакции мы добавили график работы курьера и закрепили уведомления о новых заказах только для пользователей, которые работают в этот день.

Поиск курьера 

Мы убрали возможность принимать заказ за 2-3 дня до его даты доставки. По статистике, 30% таких заказов либо не доставлялись вовсе, либо доставлялись другими курьерами после отказа на ранее назначенного. Это очень большой процент, который нервировал наших клиентов и создавал много операционной деятельности магазину и сервису.

Алгоритмы для заказов

Это отдельный сервис внутри сервиса, здесь мы учитываем множество факторов: 

Так вот, что внутри:

  • hotspot, или горячая точка. Это магазин, где потенциально может появиться заказ. Будь в хотспоте и ты получишь приоритет по заказу.

  • приоритетный заказ: Курьер может указать какой-либо район в качестве домашнего, с которого он начнет свою работу. Находясь в этом районе, курьер может увидеть заказ на 3 минуты раньше остальных и, соответственно, оперативнее всех принять его. 

  • начало поиска: обычно поиск начинается за 25 минут до времени прихода в магазин. Мы находим всех курьеров, которые не имеют заказов и находятся достаточно близко к нужному магазину. Далее в порядке увеличения расстояния уведомляем курьера, давая ему 20 секунд на принятие решения —  брать заявку в работу или нет. Если заявка не принята, идем к следующему свободному, и так далее, пока заказ не будет принят, либо пока не закончатся потенциальные кандидаты. А что тогда?

  • ищем после завершения поиска: после того, как работа по поиску завершилась, а заказ все еще не нашел своего курьера, мы запускаем поиск раз в минуту по всем имеющимся заказам. Минута и правда имеет значение, какие-то новые курьеры могли освободиться, а какие-то, возможно, подъехали к магазину поближе. Если найдены те, кому не приходили уведомления, то присылаем им инфу о новой заявке.

  • горящий заказ: если за 15 минут никто не принял заказ — его зона видимости расширяется, он будет отмечен иконкой горящего пламени. А если его принять и выполнить, то будут начислены бонусные очки для участия в топ-рейтинге курьеров.

  • дополнительный заказ: если курьер принимает заказ, алгоритм подскажет, когда можно взять смежный заказ — забрать из одного магазина и успеть доставить вовремя сразу несколько товаров.

  • расчетное время, тут учитываем все расстояния: пока курьер доберется до магазина, пока в магазине соберут букет и пока букет на доставке до клиента.

  • «карта предсказаний»: разработали алгоритм для курьеров, который показывает, где сейчас можно гарантировано получить заказ. Такая механика помогает доставщикам зарабатывать и сильно разгружает в пики, например, праздничные дни, вроде 14 февраля или Дня матери. Мы любим шутить, что у нас новый год начинается с 8 марта, свой flowwow-календарь для летоисчисления.

  • расчет пути на своей стороне: Известно, что дистанцию между двумя координатами можно рассчитать разными способами: можно использовать простые расчеты на координационной сетке, можно использовать реализации расчета по прямой с учетом эллипсоида земли, можно обращаться к внешним агрегаторам для расчета расстояния между двумя точками. Мы выбрали смежный алгоритм расчета. Там, где производительность важнее, считаем по прямой. Если нужен корректный маршрут по дорогам, то просчитываем маршрут посредством карт в открытом доступе. Для этого разворачиваем провайдеров расчета в непосредственной близости от физического расположения нашего серверного ПО. Мы выбрали провайдера graphhopper для поиска расстояний и подняли его на отдельной машине. В результате время ответа составляет около 10 мс, а система позволяет считать до 300 маршрутов одновременно. Это решение позволило сильно сократить время ответа нашего серверного ПО и значительно сократило расходы на расчет дистанции через гигантов сервиса Google.

К чему мы пришли:  

  • качество доставки заметно выросло — более 60% роста за полгода;

  • стало больше курьеров и заказов: симметрично растет количество заказов и курьеров, а главное — появились курьеры, постоянно работающие с нашим сервисом;

  • автоматизация процесса оповещения о новом заказе улучшила процесс доставки и для курьеров, и для клиентов.

 Но решили не останавливаться:

  • курьеры хотят больше заказов;

  • магазины и клиенты хотят более быструю доставку;

  • мы хотим, чтобы все были довольны друг другом.

 Поэтому новый шаг нашего пути — интеграция с партнерами.

Интеграция с другими партнерами

Долго ли, коротко ли, а мы уперлись в дилемму курицы и яйца. Количество курьеров не растет, потому что заказов не хватает для роста, а количество подключенных магазинов не удается увеличивать, потому что увеличение числа заказов потенциально увеличивает шанс, что он не будет доставлен сервисом по причине занятости всех курьеров. Как выбраться из порочного круга?

Здесь нам предстоял еще один интересный этап, где нужно подстроить существующий собственный сервис и алгоритмы под техническую реализацию других. Мы выбрали для себя партнеров — это Яндекс GO и Gett. 

Определили плюсы интеграции, как она поможет нам масштабироваться:

  • рост курьерской базы и больше возможностей зарабатывать;

  • увеличение числа магазинов на маркетплейсе;

  • безболезненный заход в новые города и регионы для бизнеса;

  • довольные клиенты: больше выбора и быстрее доставка :).

Первыми интегрировали Яндекс.Доставку. Срастили их статусы доставок с нашими и выявили некоторые сложности совместной работы:

  • Еще одно звено доставки с необходимостью коммуницировать с ней;

  • «Социальные маневры» курьеров от партнера начинают влиять на процесс доставки.

Курьеры партнера научились использовать особенности их системы и подстраиваться под алгоритмы. Например, если им надо пообедать, но неохота пропускать заказ. Что происходит: они назначают заявку доставки на себя, но не выдвигаются в магазин, а быстро перекусывают в ближайшем кафетерии. Таких людей хорошо видно по координатам. И сервис тоже заметит. В таком случае будет сформирован репорт в технический канал с дальнейшей отработкой заявки через поддержку.

  • Нет гарантии того, что заказ найдет курьера.

Например, в системе партнера заказ должен автоматически отменяться через полчаса. Только вот в случае отложенной заявки (заявки на определенное время) заказ отменяется через полчаса после указанного времени. Итак, забавная математика. Есть один курьер, дано время прибытия в магазин — 10:00. Через сколько мы узнаем, что заказ так никто и не доставит? ˙ɐɔɐҺvоu :ɯǝʚɯо

Это потеря времени для магазина и потенциальное опоздание по заявке для нас. Мы смогли обойти эту проблему, организовав на своей стороне проверку: если время прихода в магазин прошло, а курьер все еще не назначен на заявку, мы перезапускаем ее без указания времени прихода в магазин, т.е. на «как можно быстрее». 

Наша версия маховика времени :)

Если же время доставки окажется в прошлом, то система автоматически пересчитает время доставки на новое время и заново перезапустит заявку. Ведь лучше доставить заказ с опозданием, чем вообще его отменить.

Далее мы решили попробовать в качестве партнера еще одну доставку Gett.

Алгоритмы для доставки и статусы доставки прекрасно легли на новую интеграцию и все внедрение заняло менее месяца.

Алгоритм отправки на партнера был создан с учетом требований партнеров, и каждую из доставок мы оборачиваем в набор правил, пересоздания и перезапуска сценария доставки. 

Изначально циклическое исполнение заявки выглядит следующим образом:

  • Заявка создается в нашем доставке.

  • Если за 30 минут с момента начала поиска курьер не найден, то мы отправляем доставку на Gett.

  • Если за 5-10 минут для заявки на Gett не будет найден курьер, то мы передаем заявку на доставку Яндекса.

  • Заявка будет находиться на доставке Яндекса до момента доставки или до момента ее ручного перевода на другой тип доставки.

Конечно же, эти автоматизированные алгоритмы могут не учитывать фактические потребности бизнеса, и администратор нашего проекта может самостоятельно перезапускать заявки на того или иного партнера.

Но мы все же смогли достичь своей цели: 

  • курьеры стали брать больше заказов; 

  • магазины получили гарантии доставки заказа нашими силами или силами партнера;

  • мы смогли продолжить рост курьерской базы и объема подключаемых к нам магазинов.

И снова вопрос «что дальше?»

Мы прошли большой путь в три с половиной года — от ручного сервиса, в котором люди брали заказы в свободное время, до полноценного сервиса с гарантированной доставкой и курьерской работой.

 Итоги не обходятся без цифр:

  • средняя оценка доставки от клиентов 4,9, эта цифра радует нас в админке всего сервиса ;

  • среднее время обработки заказа – 46 минут по Москве;

  • доставка нашим сервисом составляет 80% от общего числа заказов;

  • более 100 курьеров работает каждый день.

Нам все еще хочется задавать вопрос «что дальше?». Здесь мы видим зоны роста для адаптации алгоритмов под новые регионы и для создания системы поощрения наших курьеров. Буду рад комментариям, идеям и обмену опытом!