Интеграция Айко. Как сделать быстрый отчет по группам клиентов.
Как разделить всю клиентскую базу на группы "0-90 дней", "90-180 дней", ">180 дней" по дате последнего заказа и выгрузить контакты клиентов для рассылки индивидуальных предложений.
Постановка задачи
Выделяем 3 группы клиентов:
- Группа "0-90". Клиенты, последний заказ у которых был в течение последних 90 дней. Наиболее активные.
- Группа "90-180". Клиенты, у которых последний заказ был от 3 до 6 месяцев назад. Отдел маркетинга предлагает для этой группы активно включать механизмы повышения повторных продаж.
- Группа ">180". Клиенты, которые за последние полгода не сделали ни одного заказа.
Нужно по всей клиентской базе доставки сделать анализ: отследить эти три группы за каждый день и показать динамику изменения. С возможностью выгрузки клиентов из каждой группы (для адресных рассылок) и отслеживания переходов клиентов из одной группы в другую (и обратно).
Первая версия решения. 30 секунд.
Семён Фудов кэширует все доставочные отчеты за день. Первый подход к решению состоял в том, чтобы из кэша взять всю историю, собрать всю клиентскую базу и выполнить анализ.
На базе Заказчика за год размером около 100 Мб анализ занимал больше 30 секунд. Слишком долго, даже учитывая нечастые обращения к отчету.
Если строить отчет на периоде последних 180 дней, то в iikoDelivery API (iikoTransport API) не хватает поля "Дата регистрации клиента" — мы видим только текущие заказы, без истории. Т.е. в первой неделе отчета все клиенты будут новыми и попадут в группу "0-90" дней. Плохо.
Вторая версия. 3 секунды.
Меняем архитектуру. Чтобы добавить интерактивности, передаем всю обработку и рендеринг HTML на сторону клиента (да, на дворе 2021 год, уже как лет 5 пора делать client-side рендеринг 💪).
Чтобы быстро собирать всю клиентскую базу, пробуем строить OLAP с минимумом полей. Несколько часов экспериментов и решение найдено:
{ "reportType": "SALES", "buildSummary": "false", "groupByRowFields": [ "Delivery.Number", "OpenDate.Typed", "Delivery.CustomerPhone", "Delivery.CustomerName", "Delivery.CustomerCreatedDateTyped" ], "groupByColFields": [ ], "aggregateFields": [ ], "filters": { "OpenDate.Typed": { "filterType": "DateRange", "periodType": "CUSTOM", "from": "", "to": "", "includeLow": "true", "includeHigh": "true" } } }
На сервере проходим авторизацию Айко, выгружаем OLAP отчет и в сыром виде передаем клиенту (браузеру). Дальше на javascript выполняем всю обработку и рендерим HTML. Теперь в истории хранятся все заказы всех клиентов.
В финальной версии поле "Delivery.CustomerCreatedDateTyped" исключаем из запроса — если вместо этого взять дату первого заказа, не сильно потеряем в точности.
Во второй версии в цикле по всем дням истории открывали цикл по всем клиентам. И для каждого клиента на выбранную дату определяли, в какую группу он попадает с учетом истории всех заказов. При тех же условиях теперь анализ выполняется за 3 секунды.
Третья версия. 1,5 секунды.
Как ускорить отчет? В финальной версии сделали 2 ускорения:
- Отказались полностью от работы с датами и moment.js. Перевели все даты в метки времени timestamp, сравнения дат теперь — как сравнения двух больших чисел. Почти в полтора раза ускорили анализ.
- Поменяли логику вложенных циклов. Быстрее открыть цикл по всем клиентам и, зная историю заказов очередного клиента, заполнить массивы групп 0-90-180 дней.
Общее ускорение — на периоде в один год почти вдвое. Когда период будет 2, 3 года, 5 лет, ускорение будет еще заметнее.
Итоги
У Семёна Фудова появился новый отчет "0-90-180 дней": теперь можно подключиться к серверу Айко, выгрузить всех клиентов, "разбить" по группам, отследить динамику и главное — экспортировать контакты клиентов для рассылки индивидуальных предложений.
Клондайк для отдела маркетинга.
Если заинтересовались в таком отчете для своей службы доставки — пишите на почту hello@fudov.ru, подключим.
Находки
Когда замеряли время выполнения клиентского javascript, обнаружили изящный вариант:
console.time('function1'); ... console.timeEnd('function1'); // function1: 1748.093994140625 ms