-- 20261002_confirmation_honesty.sql -- -- 1. Закрытие заказа без согласования больше не записывается как «Согласовано». -- Триггер clear_manual_required_on_action ставил notification_status='confirmed' -- на любой уход заказа с ручной работы — включая доставку, закрытую в 1С без даты -- и без ответа клиента. Из-за этого: -- • в реестре и карточке такие заказы читались как «Согласовано»; -- • в аналитике стадия «Согласовано» (~42% групп) и блок «Чем подтвердили» -- показывали эти заказы, причём канал подставлялся как «Ссылка из SMS». -- Теперь «Согласовано» ставится только когда у заказа есть дата (её поставил логист -- или выбрал клиент), иначе — новый статус 'closed_without_confirmation' («Без согласования»). -- 2. Разово переводим уже испорченные строки (только те, где нет ни источника даты, -- ни даты, ни подтверждённого приглашения — то есть подтверждения не было). -- -- Применять от supabase_admin (владелец таблицы и функций): -- docker cp 20261002_confirmation_honesty.sql supabase-db:/tmp/ && \ -- docker exec supabase-db psql -U supabase_admin -d postgres -f /tmp/20261002_confirmation_honesty.sql -- -- ⚠️ На order_groups висит http-триггер "Delivered" (AFTER UPDATE, n8n-вебхук) — он -- срабатывает на ЛЮБОЕ обновление. На время backfill он выключается в той же -- транзакции (ACCESS EXCLUSIVE), чтобы не слать в n8n 128 событий «доставлено» -- по заказам, которые на самом деле не менялись. begin; -- ── 1. Разрешаем новый статус ─────────────────────────────────────────────── alter table public.order_groups drop constraint if exists order_groups_notification_status_check; alter table public.order_groups add constraint order_groups_notification_status_check check (notification_status = any (array[ 'link_ready', 'sms_sending', 'first_sms_sent', 'second_sms_sending', 'second_sms_sent', 'send_failed', 'manual_required', 'paid_storage_sending', 'paid_storage_sent', 'draft', 'not_started', 'confirmed', 'address_required', 'completed', 'closed_without_confirmation' ]::text[])); -- ── 2. Триггер больше не подменяет «закрыт» на «согласовано» ──────────────── create or replace function public.clear_manual_required_on_action() returns trigger language plpgsql security definer set search_path = public as $$ begin if old.delivery_status in ('pending_confirmation', 'manual_confirmation_required') and new.delivery_status not in ('pending_confirmation', 'manual_confirmation_required') and old.notification_status = 'manual_required' then -- Дата есть → согласование действительно было (логист проставил дату или клиент выбрал слот). -- Даты нет → заказ закрыли без согласования: «Согласовано» писать нельзя. if coalesce(new.delivery_date, new.pickup_date) is not null then new.notification_status := 'confirmed'; else new.notification_status := 'closed_without_confirmation'; end if; end if; return new; end; $$; -- ── 3. Backfill: строки, где «Согласовано» не подтверждено ничем ──────────── alter table public.order_groups disable trigger "Delivered"; update public.order_groups og set notification_status = 'closed_without_confirmation' where og.notification_status = 'confirmed' and og.delivery_date_source is null and og.delivery_date is null and og.pickup_date is null and og.delivery_status not in ('pending_confirmation', 'manual_confirmation_required'); alter table public.order_groups enable trigger "Delivered"; commit; -- Контроль после применения: -- select notification_status, count(*) from order_groups group by 1 order by 2 desc; -- select count(*) from order_groups where notification_status='closed_without_confirmation'; -- ожидали 128