From 7e719e6b436426374698e4143953c1bbe1153a00 Mon Sep 17 00:00:00 2001 From: Hermes Date: Fri, 25 Sep 2026 16:56:21 +0200 Subject: [PATCH] =?UTF-8?q?fix(autocall):=20=D0=B4=D0=B5=D0=BD=D1=8C=20?= =?UTF-8?q?=D1=80=D0=BE=D0=B1=D0=BE=D1=82=D0=B0=20=E2=86=92=20=D0=B4=D0=B0?= =?UTF-8?q?=D1=82=D0=B0=20=D0=B1=D0=B5=D0=B7=20=D1=81=D0=B4=D0=B2=D0=B8?= =?UTF-8?q?=D0=B3=D0=B0;=20=D0=BE=D0=BA=D0=BD=D0=BE=20=D0=BD=D0=B5=20?= =?UTF-8?q?=D1=81=D1=87=D0=B8=D1=82=D0=B0=D0=B5=D0=BC=20=D0=BF=D1=80=D0=B8?= =?UTF-8?q?=20=D0=BF=D1=83=D1=81=D1=82=D0=BE=D0=BC=20=D0=B3=D1=80=D0=B0?= =?UTF-8?q?=D1=84=D0=B8=D0=BA=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Проверка цепочки «варианты в меню → цифра → дата в заказе» нашла два дефекта: 1. edge-функция: если дата в call-файл не попала (старый файл/сбой), дата считалась как «сегодня + цифра − 1» для ОБОИХ типов. Для доставки это сдвигало день на сутки назад: абонент нажимает «день 1» (робот говорит «завтра»), а в заказ уезжает сегодня. Теперь fallback повторяет ОЗВУЧЕННУЮ семантику: самовывоз день 1 = сегодня (сегодня/завтра/послезавтра), доставка день 1 = завтра, день 2 = послезавтра. Проверено живыми POST на функцию (5 случаев, включая приоритет chosen_date) — временная группа создана и удалена. 2. планировщик: при пустом «Графике работы» окна подменяют пустой список дефолтом Пн–Пт, то есть робот предлагал бы дни, когда компания не работает. Теперь при пустом графике звонок пропускается с понятным предупреждением. Цепочка «варианты → цифра → дата» проверена на живых окнах: пятница 17:41 → доставка пн/вт, самовывоз после отсечки 15:30 — только пн (2 варианта), при готовности сегодня до 15:30 — 3 варианта (пт/пн/вт), цифры 1/2/3 → PICKUP_DAY1/2/3 и DELIVERY_DAY1/2 уходят в диалог и возвращаются как chosen_date. --- scripts/autocall_scheduler.py | 22 +++++++++++++++++++++ supabase/functions/autocall-result/index.ts | 12 ++++++++--- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/scripts/autocall_scheduler.py b/scripts/autocall_scheduler.py index 836bba6..68fe725 100644 --- a/scripts/autocall_scheduler.py +++ b/scripts/autocall_scheduler.py @@ -511,6 +511,23 @@ def build_call_file(group, settings, attempt_no, is_test_call=False, manual=Fals scenario = group.get("scenario") or resolve_scenario(group.get("created_at")) call_type = resolve_call_type(group) + # График работы (админка) — источник рабочих дней. Если нужный список ПУСТ + # (все дни сняты или настройка не заполнена), окно считать нечем: сами функции + # окна подменяют пустой список дефолтом «Пн–Пт», и робот начал бы предлагать + # дни, когда компания не работает. Такой звонок лучше пропустить и сказать в логе. + if call_type == "pkp" and not settings.get("pickup_work_days"): + log.warning( + "Skip group %s: в «Графике работы» не заполнены дни самовывоза — окно не посчитать", + group.get("id"), + ) + return None + if call_type == "dlv" and not settings.get("delivery_work_days"): + log.warning( + "Skip group %s: в «Графике работы» не заполнены дни доставки — окно не посчитать", + group.get("id"), + ) + return None + # Самовывоз: конкретные даты передаём в диалог явно — робот называет их # голосом и возвращает выбранную дату, а не абстрактный «день 1/2». pickup_days = [] @@ -532,6 +549,11 @@ def build_call_file(group, settings, attempt_no, is_test_call=False, manual=Fals group.get("sms_sent_at") or group.get("created_at"), settings.get("delivery_work_days"), ) + if not delivery_days: + log.warning( + "Skip group %s: пустой график доставки — окно не посчитать", group.get("id") + ) + return None lines = [ f"Channel: {trunk_channel(settings, dial)}", diff --git a/supabase/functions/autocall-result/index.ts b/supabase/functions/autocall-result/index.ts index ba8aad0..5e376f1 100644 --- a/supabase/functions/autocall-result/index.ts +++ b/supabase/functions/autocall-result/index.ts @@ -171,12 +171,18 @@ Deno.serve(async (request) => { // ── confirmed*: записываем слот ── if (["confirmed", "confirmed_kept_previous", "confirmed_silent"].includes(body.outcome)) { // День называет сам диалог (chosen_date) — робот перечисляет конкретные - // дни окна самовывоза, поэтому «1/2/3» само по себе дату не задаёт. - // Если дата не пришла (старые call-файлы) — считаем по цифре дня. + // дни окна, поэтому «1/2/3» само по себе дату не задаёт. + // Если дата не пришла (старый call-файл, пустой график) — восстанавливаем + // по цифре ТАК, КАК РОБОТ ЕЁ ОЗВУЧИЛ: самовывоз «день 1» = сегодня + // (сегодня/завтра/послезавтра), доставка «день 1» = завтра, «день 2» = + // послезавтра (доставка в день готовности не бывает). Раньше для обоих + // типов бралось «сегодня+цифра-1» — доставке это сдвигало день на сутки назад. const chosenDate = /^\d{4}-\d{2}-\d{2}$/.test(body.chosen_date || "") ? (body.chosen_date as string) : null; - const dayOffset = body.dtmf_day === 3 ? 2 : body.dtmf_day === 2 ? 1 : 0; + const dayOffset = callType === "pkp" + ? (body.dtmf_day === 3 ? 2 : body.dtmf_day === 2 ? 1 : 0) + : (body.dtmf_day === 2 ? 2 : 1); const deliveryDate = chosenDate || addDays(new Date(), body.dtmf_day ? dayOffset : 1); const timeSlot = body.dtmf_half ? HALF_LABEL[body.dtmf_half] : null; const dayLabel = chosenDate