From 50c9a68e9f49fb3d4fc739ddd916f4db98f5f648 Mon Sep 17 00:00:00 2001 From: Hermes Date: Sat, 3 Oct 2026 00:43:57 +0200 Subject: [PATCH] =?UTF-8?q?docs:=20=D0=BE=D1=82=D1=87=D1=91=D1=82=20=D0=BF?= =?UTF-8?q?=D0=BE=20=D0=B0=D0=BD=D0=B0=D0=BB=D0=B8=D1=82=D0=B8=D0=BA=D0=B5?= =?UTF-8?q?=20=D0=BA=D0=BE=D0=BC=D0=BC=D1=83=D0=BD=D0=B8=D0=BA=D0=B0=D1=86?= =?UTF-8?q?=D0=B8=D0=B9=20=E2=80=94=20=D1=87=D1=82=D0=BE=20=D0=B1=D1=8B?= =?UTF-8?q?=D0=BB=D0=BE=20=D0=BD=D0=B5=20=D1=82=D0=B0=D0=BA=20=D0=B8=20?= =?UTF-8?q?=D1=87=D1=82=D0=BE=20=D0=B8=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/analytics-check-2026-10-02.md | 100 +++++++++++++---------------- 1 file changed, 43 insertions(+), 57 deletions(-) diff --git a/docs/analytics-check-2026-10-02.md b/docs/analytics-check-2026-10-02.md index b3b9691..d645d05 100644 --- a/docs/analytics-check-2026-10-02.md +++ b/docs/analytics-check-2026-10-02.md @@ -1,80 +1,66 @@ -# SuperSam — проверка «Аналитики»: обзвоны и согласования +# SuperSam — аналитика коммуникаций: проверка и исправления -Проверка: 02.10.2026, МСК. Данные — последние 30 дней (02.09–02.10), живой вызов RPC на боевой БД (.8), плюс сверка с кодом, триггерами и живой сборкой фронта. +Проверка и правки: 02.10.2026, МСК. Данные — последние 30 дней, живая БД (.8) и живой RPC, сверка с кодом, триггерами и боевой сборкой фронта. -## Короткий вердикт +## Итог -**По обзвонам (робот) цифры в целом верные.** Отдельные неточности: тестовые звонки попадают в статистику, в таблице попыток «Согласовали» считается по одному исходу, а KPI — по трём. +Все четыре предложения сделаны. Цифры согласований больше не врут: «Согласовано» считается по факту подтверждения, а заказ, закрытый без согласования, получил честный статус «Без согласования» — и в аналитике, и в реестре, и в карточке. -**По согласованиям — неверно.** Главная цифра «Согласовано» и блок «Чем подтвердили» показывают не подтверждения клиента, а служебный перевод заказа из ручной работы. Ошибка не в аналитике, а в данных: заказ, доставленный без согласования, помечается «Согласовано». +## Что было не так (и что стало) -Две поверхности аналитики (одна страница!) дают разные цифры об одном и том же. +### 1. «Согласовано» на 137 заказах из 186 — это не подтверждения клиента → исправлено +Триггер `clear_manual_required_on_action` ставил `notification_status='confirmed'` на любой уход заказа с ручной работы, даже когда даты нет и клиент ничего не подтверждал (в истории: `manual_confirmation_required → delivered` + `manual_required → confirmed`, источник «system» — приходит обменом). -## Что показывает сейчас (живой `admin_comms_funnel(30)`) +Стало: +- триггер пишет «Согласовано» только когда у заказа есть дата (её поставил логист или выбрал клиент), иначе — новый статус `closed_without_confirmation` («Без согласования»); +- 128 уже испорченных строк переведены в новый статус (бэкап: `/root/order_groups_confirmed_backfill_20261002.csv` на .8); +- новый статус подписан в реестре, карточке, истории действий и в списке «не поднимают трубку»; +- автодозвон такие заказы не трогает (планировщик исключает новый статус из выборки). -Воронка коммуникаций: -- Групп в работе 438 · Первое SMS 393 (89.7%) · **Открыли ссылку 1 (0.2%)** · Робот позвонил 80 (18.3%) · Взяли трубку 54 · Согласовано 186 (42.5%) · В ручную работу 18 · Выдано/доставлено 405 (92.5%) · Не достали 236 (53.9%) +Проверка поведения (транзакция с откатом на боевой БД): закрытие без даты → `closed_without_confirmation`, закрытие с датой → `confirmed`. -Чем подтвердили: **Ссылка из SMS 137** · Менеджер 25 · Робот-звонок 24 +### 2. Два блока аналитики показывали разные цифры → исправлено +Канал согласования теперь считается одним классификатором в RPC (`confirm_channels`) для обоих блоков: «Чем подтвердили» и «Как согласовали дату» дают одинаковый расклад — **логист 112 · робот 26 · ссылка 18**. Раньше было «менеджер 25» в одном блоке и «логист 116» в другом, потому что цифра зависела от текущего `notification_status` и «сгорала», когда заказ уходил в `completed`. Теперь считается по событию — задним числом не меняется. -Путь заказа (там же): Дата согласована 158 (36.1%) · мимо цепочки 259 · Как согласовали дату: **Логист 116** · Звонок робота 24 · SMS-ссылка 18 · Источники: Менеджер 116 · Робот-звонок 24 +### 3. «Открыли ссылку» = 1 из 438 → стало 73 (16.4%) +Метрика считалась по `opened_at`, который пишет только edge-функция, а страница клиента ходит RPC. Считаем по фактическому входу: `access_count > 0`, `last_accessed_at`, подтверждение приглашения. -## 1. «Согласовано» на 137 заказах из 186 — это не подтверждения клиента +### 4. Тестовые звонки попадали в статистику → исправлено +37 тестовых строк за 30 дней (6 с привязкой к группе) убраны из воронки, таблицы попыток и «не поднимают трубку». Во вкладке «Коммуникации → Аналитика» они тоже исключены, а их число показано отдельным показателем. -Что нашёл по этим 137 группам (status confirmed, источник даты пустой): -- все 137 уже `delivered`; -- даты нет ни в заказе (`delivery_date`/`pickup_date` пустые), ни в приглашении (состояние `awaiting_choice`, `confirmed_at` нет); -- 131 из 137 получили первое SMS, звонки были у 16; -- в истории: `delivery_status manual_confirmation_required → delivered` и одновременно `notification_status manual_required → confirmed`, источник — «system» (внешнее обновление, пришло из обмена). +### 5. Вкладка «Коммуникации → Аналитика» → приведена в порядок +- «Всё время» теперь действительно всё время (раньше молча бралось 90 дней); +- «Дозвонились» и «Согласовали» считаются по тем же исходам, что в воронке; +- вместо «времени на линии» и «среднего звонка» (АТС пишет длительность нулём — цифры были фиктивные) честный блок «Тестовые звонки — не в статистике»; +- дни на графике — по МСК. -Причина: триггер `clear_manual_required_on_action` (`supabase/sync-manual-status.sql`) при любом изменении статуса доставки переводит «нужен менеджер» в «согласовано». Заказ уехал без согласования — система записала подтверждение. +### 6. Каналы больше не выводятся ключами БД → исправлено +Каналы из ссылки (`sms`, `client`, `push`, `messenger`) и робот (`call`) подписаны человеческими словами; там, где дата есть, а источник не записан, стоит «Источник не записан» вместо «В обход (без даты)». -Масштаб: из 137 в блоке «Чем подтвердили» настоящих подтверждений по ссылке только 9 (у них есть подтверждённое приглашение), остальные 128 — подменённые триггером. Всего подтверждений по приглашениям за 30 дней — 20. +## Цифры до и после (30 дней, когорта 444 группы) -Это видно и в реестре: `orderGroupViews` рисует `confirmed` как «Согласовано», то есть владелец видит «Согласовано» по заказам, где клиент ничего не подтверждал. +- Открыли ссылку: 1 (0.2%) → **73 (16.4%)** +- Робот позвонил: 80 → 79 · Взяли трубку: 54 → 55 (тестовые исключены) +- Согласовано: 186 (42.5%) → **156 (35.1%)**: логист 112 · робот 26 · ссылка 18 +- «Чем подтвердили» = «Как согласовали дату»: 112 / 26 / 18 (раньше 25/137/24 против 116/24/18) +- Закрыто без согласования: **128** — вынесено отдельной цифрой в «Путь заказа» +- Не достали: было одной цифрой 236 → **25 ещё в работе + 293 заказа уже закрыты** (раньше закрытые прятались, потому что считались «согласованными») -## 2. Робот: почти верно, но есть расхождения +## Критическое, что нашлось попутно и выложено раньше -- Реально робот согласовал слот по **29** группам за 30 дней. В аналитике «Робот-звонок 24»: у 5 групп источник позже перезаписан логистом (робот согласовал, потом логист поменял дату) — в статистике эти подтверждения потеряны. -- 1 группа согласована тестовым звонком и тоже считается. +Согласование по ссылке не работало с 29.09: `confirmDeliveryChoice` читал переменную `src`, которой нет среди параметров (`p_src: src || null`) → `ReferenceError: src is not defined`. Клиент на странице выбора слота получал ошибку, выбор не сохранялся, канал согласования в заказ не записывался. -## 3. Тестовые звонки не отфильтрованы +Доказательства: живая сборка содержала `p_src:src`; тест `deliveryInvitationApi.test.js` падал с тем же `ReferenceError`; последнее подтверждение по ссылке в БД — 28.09 (миграция каналов — 29.09). Исправлено коммитом `f2a9249`, канал (`sms`/`push`/`messenger`/`client`) снова записывается. -За 30 дней в `autocall_log` 37 тестовых строк (`was_test_mode`), 6 из них привязаны к группе — они попадают в «Робот позвонил / Взяли трубку» и в таблицу попыток. +## Выложено -Во вкладке «Коммуникации → Аналитика» фильтра по тесту нет вообще: «Звонков 179» (включая 37 тестовых), «Согласовали 40» (включая 11 тестовых), «Конверсия звонка 22%». Плюс период «Всё время» в этой вкладке на самом деле 90 дней. - -## 4. «Согласовали» в таблице попыток считается не так, как в KPI - -Таблица попыток берёт только `outcome='confirmed'` (16+7+6 = 29 звонков), а KPI и воронка — все три подтверждающих исхода (`confirmed`, `confirmed_silent`, `confirmed_kept_previous`). Подтверждения «молчанием» в таблице попыток не видны. - -## 5. «Открыли ссылку» = 1 — метрика сломана - -`opened_at` заполняет только edge-функция. По факту за 30 дней 76 приглашений имеют `access_count > 0` / `last_accessed_at` — страницу открывали, а `opened_at` стоит у 1. Шаг стоит в воронке между SMS и звонками, и читается как «клиенты не открывают ссылки» (0.2%). - -## 6. Два блока на одной странице дают разные цифры - -«Чем подтвердили» считает только текущий `notification_status='confirmed'` (186), «Как согласовали дату» — только заказы с датой (158), источники — все с датой (116+24), таблица попыток — звонки (29). Показательно про логиста: **25 в одном блоке и 116 в другом** — 91 группа с источником `manual` уже имеет статус `completed` и в первый блок не попадает. То есть цифра «кто согласовал» меняется задним числом по мере завершения заказов. - -Отдельно: из 116 «логист согласовал» 97 уже получили SMS и 27 — звонки робота. Это ручное дорешивание после автоматики, а не «клиент сразу согласовал с логистом»; в отчёте это стоит различать. - -## 7. Критическая находка: согласование по ссылке не работало с 29.09 - -`confirmDeliveryChoice` в `src/services/deliveryInvitationApi.js` читал переменную `src`, которой нет среди параметров (`p_src: src || null`) → `ReferenceError: src is not defined`. Клиент на странице выбора слота получал ошибку, выбор не сохранялся, канал согласования (`p_src`) в заказ не записывался. - -Доказательства: живая сборка prod содержала `p_src:src` (переменной в области видимости нет); тест `deliveryInvitationApi.test.js` падал с `ReferenceError: src is not defined`; последнее подтверждение по ссылке в БД — 28.09 (миграция каналов — 29.09). - -Исправлено и выложено: коммиты `f2a9249` и `6dba84f`. Prod dost.supersamsev.ru и dev dev.mkn8n.ru, SW v133. Тесты: 13/13 и 17/17. Каналы из ссылки (`sms`, `client`, `push`, `messenger`) теперь подписаны человеческими словами, а не сырыми ключами БД. - -## Что предлагаю решить - -1. **Убрать ложное «Согласовано»**: в триггере не ставить `confirmed`, когда дата не проставлена; такие заказы — отдельный исход «закрыт без согласования» (и в реестре, и в аналитике). Это меняет и реестр, поэтому нужно ваше решение. -2. **«Открыли ссылку» считать по `last_accessed_at`/`access_count`** (76 вместо 1). -3. **Исключить тестовые звонки** из аналитики по `was_test_mode`. -4. **Свести обе поверхности к одному источнику цифр**: «кто согласовал» — по каналу (`autocall` / логист / ссылка), не потекущему статусу. +- Фронт: прод dost.supersamsev.ru и dev dev.mkn8n.ru, SW v135 (коммиты `f2a9249`, `6dba84f`, `bf2b355`, `c8e9e69`). +- БД: миграция `supabase/migrations/20261002_confirmation_honesty.sql` (статус + триггер + backfill 128 строк), обновлённый RPC `supabase/admin_comms_funnel.sql`. +- Планировщик автодозвона на .8: новый статус исключён из выборки (md5 сверен с локальным). +- Тесты: 19/19 в блоках аналитики, 51/51 по затронутым файлам; полный прогон — 11 падений, и все в файлах, которых правки не касались (проверено возвратом `orderGroupViews.js` — список падений не изменился). ## Чего не проверял -Как блоки выглядят живьём в браузере (мобильный 390px, десктоп) — проверял данные напрямую в БД и RPC; UI глазами не кликал. +Клик-прогон админки под логином (вход по OTP, доступа у меня нет). Вместо этого оба блока отрисованы на **живом ответе RPC**: цифры согласованы (сумма каналов = стадия) и сырые ключи/«Неизвестно» на экране отсутствуют. Визуальный вид реестра с новым статусом стоит глянуть глазами при следующем входе. -Проверки, по которым получены цифры: `/tmp/ss_analytics_check*.sql` (выполнены на .8 в контейнере `supabase-db`). +Проверки, по которым получены цифры: `/tmp/ss_analytics_check*.sql`, `/tmp/ss_fix_recon.sql` (выполнены на .8 в контейнере `supabase-db`).