Интеграция Айко. Как сделать быстрый отчет по группам клиентов.
Как разделить всю клиентскую базу на группы "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