"""Содержание презентации «Автодозвон: как это работает». Один источник правды: и PDF (how-it-works.py), и HTML (render-html.py) собираются отсюда, поэтому версии не разъезжаются при правках. Факты сверены с кодом: scripts/autocall_scheduler.py, docs/ats/ss-dialog.agi, supabase/functions/autocall-result/index.ts и настройками боевой системы. """ ACCENT, ACCENT2, WARN, DANGER = "accent", "accent2", "warn", "danger" TITLE_SLIDE = { "kind": "title", "kicker": "СУПЕР САМ · ДОСТАВКА И САМОВЫВОЗ", "title": "Автодозвон: как это работает", "sub": "Робот звонит клиенту, согласует день и половину дня — без участия оператора", "lines": [ "Что описано: правила звонка, паузы, поведение в нештатных случаях (не дозвонились,", "сбросили трубку, не нажали цифру), где что настраивается и что видит менеджер.", "", "Основано на текущем коде и настройках боевой системы, без обещаний и продажи.", ], } SLIDES = [ { "kind": "cards2full", "title": "Что делает робот", "sub": "Коротко: он не продаёт и не консультирует — только согласует день и половину дня", "cards": [ {"title": "Три задачи", "accent": ACCENT, "items": [ "Дозвониться, когда заказ готов и клиент не подтвердил день по ссылке из SMS", "Предложить конкретные дни голосом и получить выбор цифрой", "Записать выбор в заказ — дату, половину дня и признак «согласовано роботом»", ]}, {"title": "Чего он не делает", "accent": WARN, "items": [ "Не соединяет с живым менеджером — такой цифры в диалоге нет", "Не спорит и не уговаривает: нет ответа — повторит по расписанию", "Не предлагает нерабочие дни и не звонит вне рабочего времени", ]}, ], "full": {"title": "Как это выглядит для клиента", "accent": ACCENT2, "items": [ "Звонок с одного номера, голос один и тот же: «Ваш заказ готов. Выберите день и время»", "Клиент нажимает цифру дня и цифру половины дня — робот подтверждает выбор вслух", "После подтверждения даёт возможность изменить выбор (нажатием цифры 2)", ]}, }, { "kind": "steps", "title": "Путь заказа до звонка", "sub": "Когда именно звучит звонок", "steps": [ ("1. Заказ из 1С", "приходит готовым\nпо обмену"), ("2. Ссылка и SMS", "ссылка создаётся\nсама, SMS уходит"), ("3. Пауза 90 минут", "настройка админки:\nстолько ждём ответа"), ("4. Звонок робота", "если клиент не\nподтвердил по ссылке"), ("5. Результат в заказ", "дата и половина дня\nв самом заказе"), ], "full": {"title": "Важно", "accent": WARN, "items": [ "Готовность заказа приходит из 1С по обмену: заказ приходит уже готовым, вручную в системе её никто не отмечает", "Если клиент подтвердил день по ссылке сам — звонка не будет: заказ уже согласован", "Звонок идёт только в рабочее время и только в рабочие дни (настройки кампании)", ]}, }, { "kind": "cards2full", "title": "Откуда берутся дни и время", "sub": "Админка → Расписание → Рабочие дни: один источник правды", "cards": [ {"title": "Что настраивается", "accent": ACCENT, "items": [ "Рабочие дни склада (самовывоз) и рабочие дни доставки", "Часы: открытие и закрытие склада, часы доставки", "«Первая половина — до» — граница между половинами дня", "«Сегодня предлагаем до» — до какого времени предлагать сегодняшний день", ]}, {"title": "Как это работает в коде", "accent": ACCENT2, "items": [ "Окно звонка считается рабочими днями: выходные не сокращают окно, а пропускаются", "Робот называет реальные дни голосом: «сегодня», «в понедельник», «во вторник»", "Клиентская ссылка использует те же дни — расхождений между звонком и ссылкой нет", ]}, ], "full": {"title": "Текущие значения в системе", "accent": WARN, "items": [ "Склад: пн–пт, 09:00–17:30, половина дня до 13:00, «сегодня» предлагаем до 15:30", "Доставка: пн–пт (суббота — выходной) 09:00–21:00, половина дня — граница 13:00", "Граница половины дня — 13:00 для обоих каналов: звоним после 13:00 — говорим про вторую половину дня, первую уже не предлагаем", ]}, }, { "kind": "tablecard", "title": "Самовывоз: какие дни предлагает", "sub": "Окно — «день готовности + два рабочих дня», выходные пропускаются", "table": { "rows": [ ["Заказ готов", "Что предложит робот", "Почему так"], ["в понедельник", "пн, вт, ср", "три рабочих дня подряд"], ["в пятницу", "пт, пн, вт", "суббота и воскресенье — выходные склада"], ["в пятницу после 15:30", "пн, вт", "«сегодня» больше не предлагаем (настройка)"], ["в понедельник после 13:00", "пн, вт, ср", "половину дня не спрашиваем — сразу вторая"], ["заказ готов давно", "звонка нет", "окно самовывоза прошло — звонить не о чем"], ], "widths": [200, 240, 428], }, "full": {"title": "Две настройки, которые это двигают", "accent": ACCENT, "items": [ "«Сегодня предлагаем до» (сейчас 15:30) — позже этого времени сегодняшний день исчезает из звонка и из ссылки", "Граница половины дня (13:00): звоним после 13:00 — робот говорит про вторую половину дня, первую не предлагает", ]}, }, { "kind": "tablecard", "title": "Доставка: не в день готовности", "sub": "Нужен запас времени, чтобы собрать маршрут — поэтому начинаем со следующего дня", "table": { "rows": [ ["Заказ готов", "Что предложит робот"], ["в понедельник", "вторник и среда"], ["в пятницу", "понедельник и вторник (в субботу не возим)"], ["в четверг, звонок в пятницу", "пятница и понедельник"], ["в пятницу, звонок в понедельник", "понедельник и вторник"], ], "widths": [300, 568], }, "full": {"title": "Ключевое отличие от самовывоза", "accent": ACCENT2, "items": [ "В день готовности доставку не предлагаем никогда — только следующие рабочие дни", "Суббота и воскресенье в графике доставки — выходные, их робот не назовёт", "Половина дня — граница 13:00: звоним после 13:00, значит говорим про вторую половину дня", ]}, }, { "kind": "tablecard", "title": "Как проходит разговор", "sub": "Робот задаёт вопрос и ждёт цифру; молчание не считается согласием", "table": { "rows": [ ["Шаг", "Что говорит робот", "Что делает клиент", "Сколько ждёт"], ["Приветствие", "«Ваш заказ готов. Выберите день и время доставки»", "слушает", "—"], ["День", "«Нажмите один, чтобы доставить. В понедельник. Нажмите два…»", "нажимает 1 или 2", "9 секунд"], ["Половина дня", "«Первая половина дня или вторая?»", "нажимает 1 или 2", "9 секунд"], ["Подтверждение", "«Первая половина дня» — озвучивает выбор", "слушает", "—"], ["Изменить?", "подсказка про кнопку 2 — один раз", "нажимает 2, чтобы переделать", "6 секунд"], ], "widths": [130, 360, 200, 178], }, "full": {"title": "Что делает при ошибке ввода", "accent": WARN, "items": [ "Не понял цифру — повторяет тот же вопрос один раз", "Снова не понял или молчит — завершает: «Вы не выбрали время. С вами свяжется менеджер»", "Клиент нажимает 2 — диалог начинается заново («день и время»), прежний слот при этом не теряется", ]}, }, { "kind": "tablecard", "title": "Что можно нажать", "sub": "Всего несколько цифр — и одна из них «больше не звоните»", "table": { "rows": [ ["Цифра", "Значение", "Что происходит"], ["1", "первый предложенный день", "робот переходит к выбору половины дня"], ["2", "второй предложенный день", "робот переходит к выбору половины дня"], ["3", "третий день (только самовывоз)", "робот переходит к выбору половины дня"], ["1 / 2", "половина дня", "первая половина / вторая (после 13:00 — только вторая)"], ["2 после подтверждения", "изменить выбор", "робот спрашивает день и время заново — один раз"], ["любая другая цифра", "не принимается", "вопрос повторяется один раз; после двух таких звонков — менеджеру"], ], "widths": [176, 200, 492], }, "full": {"title": "Что происходит после подтверждения", "accent": ACCENT2, "items": [ "Робот называет выбранный день и половину дня вслух — клиент слышит, что именно записано", "Дальше один раз предлагает изменить выбор: нажатие 2 — и день со временем спрашивают заново", "Если клиент ничего не меняет, разговор завершается, а выбор уходит в заказ", ]}, }, { "kind": "cards2full", "title": "Если не дозвонились", "sub": "Робот различает «не взял трубку» и «вместо человека ответил автоответчик/оператор»", "cards": [ {"title": "Как понимает, что трубку не взяли", "accent": WARN, "items": [ "Никто не ответил за 45 секунд — попытка считается неудачной", "Трубку подняли, но гудки шли больше 20 секунд и ни одной цифры не нажали — это объявление оператора, а не человек: пишем «не взял трубку»", "Живой человек почти всегда берёт трубку раньше, поэтому правило надёжно отделяет автоответчик", ]}, {"title": "Что происходит дальше", "accent": ACCENT, "items": [ "Повторный звонок — не раньше чем через час (настройка)", "Всего не больше 5 попыток на заказ (настройка)", "Звонит только в рабочие часы кампании: 09:00–20:00, дни — по настройке", "Исчерпали попытки — заказ уходит менеджеру, автозвонок по нему останавливается", ]}, ], "full": {"title": "Для менеджера это видно в карточке", "accent": ACCENT2, "items": [ "Каждая попытка — отдельная строка истории: время, результат, длительность разговора", "Статус заказа меняется на «нужен менеджер» — с комментарием «не дозвонились / не нажал»", "Отдельно красным предупреждаем, если заявка «Позвонить сейчас» висит больше 15 минут", ]}, }, { "kind": "tablecard", "title": "Если сбросили трубку в середине разговора", "sub": "Робот запоминает то, что успел услышать, и не портит уже согласованный слот", "table": { "rows": [ ["Когда положили трубку", "Что запишет робот", "Что увидит менеджер"], ["до выбора дня", "ответил, ничего не нажал", "«взял, не нажал (день)» — попытка зачтена"], ["день выбрал, время не успел", "день выбран, время нет", "«взял, не нажал (время)»"], ["выбор подтвердил и сбросил", "слот согласован", "дата и половина дня в заказе, статус «согласовано»"], ["начал менять выбор и сбросил", "остаётся прежний слот", "«правка не доведена» — прежнее согласование в силе"], ], "widths": [250, 250, 368], }, "full": {"title": "Почему так", "accent": ACCENT2, "items": [ "Слот становится согласованным только после двух ответов: день и половина дня — это защита от «услышал половину фразы»", "Обрыв не считается согласием: если клиент не подтвердил, робот перезвонит по расписанию или отдаст заказ менеджеру", "Если клиент уже согласовал слот, а потом начал менять и бросил трубку — прежний выбор сохраняется, ничего не теряется", ]}, }, { "kind": "cards3full", "title": "Когда подключается менеджер", "sub": "Робот доводит дело до конца сам, но в трёх случаях передаёт человеку", "cards": [ {"title": "Не нажал цифру 2 раза", "accent": WARN, "items": [ "Робот писал «взял, но не нажал» дважды", "Заказ помечается «нужен менеджер», комментарий «не дозвонились / не нажал»", "Порог «не нажал × N» настраивается в админке автодозвона", ]}, {"title": "Исчерпаны 5 попыток", "accent": WARN, "items": [ "Каждый звонок — отдельная попытка", "Когда попытки закончились, автозвонок прекращается", "Заказ остаётся в списке у менеджера", ]}, {"title": "Неверный номер", "accent": DANGER, "items": [ "Если номер не существует или недоступен — задача менеджеру", "Менеджер может поставить «Не звонить» — тогда робот этого клиента не беспокоит", "Такая отметка видна в карточке заказа и учитывается при обзвоне", ]}, ], "full": {"title": "Что видит менеджер в карточке заказа", "accent": ACCENT, "items": [ "Единый статус автодозвона и история всех попыток с результатами и слотами", "Кнопка «Позвонить сейчас» — ручной звонок клиенту (не тестовый номер) и живое состояние: «в очереди», «звоним», «звонок сделан» с результатом", "Кнопка «Не звонить» — если робот не должен беспокоить этого клиента", ]}, }, { "kind": "cards2full", "title": "Когда робот не звонит вообще", "sub": "Список условий, при которых звонка не будет — проверяются до набора номера", "cards": [ {"title": "По клиенту и заказу", "accent": ACCENT, "items": [ "Клиент сам подтвердил день по ссылке — звонок не нужен", "Менеджер поставил «Не звонить» — робот этого клиента не беспокоит", "Номер в списке исключений — например, на МТС-диапазон звонки не идут", "Самовывоз: автообзвон по самовывозу включается отдельной галочкой (сейчас выключен)", ]}, {"title": "По времени и географии", "accent": WARN, "items": [ "Вне рабочих часов кампании (09:00–20:00) и вне рабочих дней", "Город исключён целиком или для города выключен канал", "В админке автодозвона выключены звонки по городу — например, Ялта: SMS идут, звонков нет", "Меньше 90 минут прошло после SMS со ссылкой", ]}, ], "full": {"title": "Админка автодозвона: где это переключается", "accent": ACCENT2, "items": [ "Панель «Автодозвон»: тестовый режим, часы и дни звонков, паузы, лимит попыток, порог «не нажал × N»", "Панель «Локации»: для каждого города — звонки включены или выключены (SMS не затрагивается)", "Панель исключений: номера и префиксы, на которые не звоним, с причиной", ]}, }, { "kind": "tablecard", "title": "Что записывается в заказ", "sub": "Результат звонка виден там же, где всё остальное", "table": { "rows": [ ["Поле", "Значение"], ["Дата", "конкретная дата, которую назвал робот (например, понедельник 21.09)"], ["Время", "«первая половина дня» или «вторая половина дня»"], ["Источник", "«согласовано роботом» — видно, что выбор сделал клиент в звонке"], ["Статус", "«согласовано» / «нужен менеджер» / «не звонить» (запрет ставит менеджер)"], ["Комментарий", "«Согласовано роботом: завтра, первая половина дня»"], ], "widths": [200, 668], }, "full": {"title": "Зачем это нужно", "accent": ACCENT, "items": [ "Менеджер видит причину и источник решения, а не просто «дата стоит»", "История звонков хранится отдельно: видно, сколько было попыток и чем они закончились", "Дата, названная роботом, используется дальше в работе склада и доставки", ]}, }, { "kind": "tablecard", "title": "Тестовый режим и текущее состояние", "sub": "Сейчас обзвон клиентов выключен — система в тестовом режиме", "table": { "rows": [ ["Параметр", "Значение сейчас", "Что будет при запуске"], ["Обзвон клиентов", "выключен", "включается отдельной командой"], ["Тестовый номер", "звонит только на него", "массовый обзвон идёт клиентам"], ["Кнопка «Позвонить сейчас»", "звонит клиенту сразу", "так же — звонок клиенту"], ["Звонки по самовывозу", "выключены галочкой", "включаются отдельно от доставки"], ], "widths": [230, 280, 358], }, "full": {"title": "Как проверяется перед запуском", "accent": ACCENT2, "items": [ "Тестовый звонок на свой номер: диалог, дни, половина дня, запись результата", "Прогон диалога без звонка: проверка всех веток (согласие, обрыв, молчание, отказ)", "Проверка окон: робот предлагает именно те дни, которые заданы в админке", ]}, }, { "kind": "cards2full", "title": "Что пока не учитывается", "sub": "Честный список: это важно знать до запуска", "cards": [ {"title": "График", "accent": WARN, "items": [ "Праздники: календаря нерабочих дат нет — если праздник попадёт в окно, робот его предложит", "Часы доставки используются частично: границу половины дня робот проговаривает словами, без конкретного времени", ]}, {"title": "Настройки, которые пока не влияют", "accent": DANGER, "items": [ "«Попыток в день» — поле есть, но расписание повторов задаётся интервалом между попытками", "«Попытки следующего дня (10:00, 14:00)» — пока не используются", "«Таймаут звонка, 30 секунд» — звонок ждёт ответа 45 секунд (значение в самом звонке)", ]}, ], "full": {"title": "Что предлагаем уточнить до боевого запуска", "accent": ACCENT2, "items": [ "Список праздников (или решение не учитывать их)", "Нужен ли жёсткий график повторов по времени, кроме паузы в час", "Кто и когда разбирает заказы, которые робот не согласовал за 5 попыток", ]}, }, { "kind": "cards2full", "title": "Коротко", "sub": "Одна страница вместо всей презентации", "cards": [ {"title": "Что делает система", "accent": ACCENT, "full": True, "dense": True, "items": [ "Ждёт 90 минут после SMS и звонит, если клиент не подтвердил день сам", "Предлагает только рабочие дни по графику: самовывоз — включая сегодня, доставка — со следующего дня", "Спрашивает день и половину дня, подтверждает вслух, даёт один раз переделать выбор", "Граница половины дня — 13:00: звоним после 13:00, значит говорим про вторую половину", "Повторяет попытки не чаще чем раз в час, максимум 5 раз, только 09:00–20:00 в рабочие дни", "После двух «взял, но не нажал» или исчерпания попыток передаёт заказ менеджеру", "Каждая попытка и результат видны в карточке заказа; ручной звонок идёт клиенту и показывает своё состояние", ]}, ], "full": {"title": "Что осталось решить", "accent": WARN, "items": [ "Праздники и точный график повторов — по вашим правилам", "Момент включения боевого обзвона клиентов и по самовывозу", ]}, }, ] ALL_SLIDES = [TITLE_SLIDE] + SLIDES