ВЫСОТА-СЕРВИС

Система оповещения и сбор обратной связи

Обучалка подсвечивает кнопки и поля текущего экрана. Её можно запускать снова.
{{ adminUsername || 'Администратор' }}
Роль: {{ adminRole === 'admin' ? 'Главный администратор' : (adminRole === 'editor' ? 'Редактор' : 'Только просмотр') }}
Кампании
Аккаунт
Связь
Голоса и ИИ
Справочники
Система
Подсветка полей входа. После входа обучалка пройдёт по всем экранам.
{{ toastMessage }}

Новый ответ!

Опрос: {{ notif.project_title }}

Нажмите, чтобы посмотреть →

Вход в панель

{{ loginError }}

Проекты

Загрузка проектов...

Пожалуйста, подождите

{{ p.title }}

{{ kindTitleOf(p.kind) }}

{{ p.description }}

{{ progressLabelDone(p) }}: {{ progressReached(p.progress, p.kind) }} Осталось: {{ (p.progress && p.progress.remaining) || 0 }} {{ (p.progress && p.progress.percent) || 0 }}%
Набрали: {{ (p.progress && p.progress.tried) || 0 }} · не звонили {{ (p.progress && p.progress.not_called) || 0 }} · {{ progressSkipHint(p.progress) }}
Оценок NPS: {{ (p.progress && p.progress.answered_nps) || 0 }} · полный опрос ({{ p.progress.questions_total }}): {{ (p.progress && p.progress.answered_all) || 0 }}
Ср. разговор: {{ (p.progress && p.progress.avg_talk_label) || '—' }} · очередь пуста · до конца ≈ {{ p.progress.eta_label }} × {{ p.progress.parallel }} лин. · ≈ {{ p.progress.avg_attempts }} попыток ср. (к {{ shortEtaAt(p.progress.eta_at) }}) · ETA: мало данных по разговорам
Идёт работа Пауза Завершён Всего {{ progressPeople(p.progress) }} закрыто {{ (p.progress && p.progress.percent) || 0 }}% · набрали {{ progressTriedPct(p.progress) }}% {{ (p.progress && p.progress.percent) || 0 }}%
Информирование Должники: {{ (p.progress && p.progress.total) || 0 }} E-mail рассылка Почта России Ответов: {{ p.responses_count }}

{{ projects.length ? 'Ничего не найдено' : 'У вас пока нет проектов' }}

{{ projects.length ? 'Сбросьте поиск или фильтр по типу.' : 'Создайте первый проект, чтобы начать собирать ответы.' }}

Заблокированные пользователи (Спам)

Список IP-адресов

Всего: {{ blockedUsers.length }}
IP-адрес Дата блокировки Регион / Страна Устройство Браузер / ОС Действия
{{ user.ip_address }} {{ fmtServerDt(user.created_at) }} {{ user.location || 'Неизвестно' }} Мобильное Десктоп {{ parseUserAgent(user.user_agent) }}
Список заблокированных пуст

Управление пользователями

Список администраторов

Всего: {{ users.length }}
Логин ФИО Роль Email / Телефон Действия
{{ user.username }} {{ user.full_name || '—' }} Администратор Редактор Только просмотр
{{ user.email }}
{{ user.phone }}
—
Список пользователей пуст
Режим просмотра: отчёты и записи видны, запуск обзвона и правки недоступны. «Поделиться» может только редактор.
Запуск кампании

{{ currentProject.project.title }}

{{ kindTitleOf(projectKind) }}

{{ currentProject.project.description }}

{{ progressLabelDone(currentProject.project) }}: {{ progressReached(currentProject.project.progress, projectKind) }} Осталось: {{ currentProject.project.progress.remaining || 0 }}
Набрали: {{ currentProject.project.progress.tried || 0 }} · не звонили {{ currentProject.project.progress.not_called || 0 }} · {{ progressSkipHint(currentProject.project.progress) }}
Оценок NPS: {{ currentProject.project.progress.answered_nps || 0 }} · полный опрос ({{ currentProject.project.progress.questions_total }}): {{ currentProject.project.progress.answered_all || 0 }}
Ср. разговор: {{ currentProject.project.progress.avg_talk_label || '—' }} · очередь пуста · до конца ≈ {{ currentProject.project.progress.eta_label }} × {{ currentProject.project.progress.parallel }} лин. · ≈ {{ currentProject.project.progress.avg_attempts }} попыток ср. (к {{ shortEtaAt(currentProject.project.progress.eta_at) }}) · ETA: мало данных по разговорам
закрыто {{ currentProject.project.progress.percent || 0 }}% · набрали {{ progressTriedPct(currentProject.project.progress) }}% · {{ currentProject.project.progress.percent || 0 }}% · всего {{ progressPeople(currentProject.project.progress) }} · {{ progressSkipHint(currentProject.project.progress) }} · без озвучки {{ currentProject.project.progress.no_audio }}
Публичная ссылка:
Внимание
Для этого проекта загружены здания. Общая ссылка отключена. Используйте ссылки из вкладки «Здания и Ссылки».
Сейчас на линии
{{ liveSummaryLine() }}
{{ liveHeaderLabel() }}
Идёт озвучка {{ currentProject.project.tts_done || 0 }} / {{ currentProject.project.tts_total || 0 }}. Набор начнётся сам, когда файлы будут готовы.
{{ n.text }}
{{ liveEmptyHint() }}
{{ c.full_name || 'Абонент' }} входящий пробный
{{ c.phone || '—' }} · {{ liveAddr(c) }} · {{ c.sip_login }}
{{ c.stage_label || kpiCallLabel(c.status) }}
{{ liveElapsed(c.elapsed_sec) }}
Стадия: {{ c.stage_detail || '—' }} NPS {{ c.nps_score }}
{{ c.current_question }}
идёт эфир после ответа
Ещё нет канала Asterisk: озвучка или исходящий вызов.
{{ c.status === 'ringing' ? 'Ждём ответа…' : 'Транскрипция появится, когда абонент заговорит' }}
{{ t.role === 'user' ? 'Абонент' : 'Робот' }}: {{ t.text }}

Конструктор информирования

Скачайте шаблон Excel, заполните список абонентов и загрузите файл обратно. Затем укажите колонку с телефоном и соберите текст из полей таблицы. Суммы вроде 110,55 озвучиваются как «сто десять рублей пятьдесят пять копеек».

Голос робота
Выберите движок и голос. Прослушать — кнопкой справа.
Нет голосов в этом движке

Яндекс — амплуа; Fish/Silero/Edge — темп и характер речи.

медленнеебыстрее

Загрузите Excel — здесь появятся названия колонок файла.

Параметры — названия колонок загруженного Excel. Подставляются при звонке. Приветствие звучит перед основным текстом.

Вставляйте параметры кнопками. Пример: Уважаемый [ФИО], Ваш долг [Долг].

Как будет сказано
{{ informPreviewText }}
Генерация {{ informTts.done }} / {{ informTts.total }}
Озвучка готова. Можно запускать обзвон — в звонке воспроизводится сохранённый файл.
{{ currentProject.project.tts_error }}
Превью Excel
{{ col }}
{{ row[col] }}

Конструктор e-mail письма

Загрузите Excel со списком получателей. Колонка «здание» обязательна. Параметры из таблицы можно вставить в тему и HTML-тело письма. Скрытая метка открытия подставляется автоматически при создании проекта и отправке — в шаблон её добавлять не нужно.

ИИ подберёт цвета под тему, фото, шрифты, кнопку перехода и ссылки. Макет можно править и сохранить. Если в тексте есть http-ссылка — она станет кнопкой.

Загрузите готовый файл .html — вёрстка, стили и плейсхолдеры вида [здание], [ФИО] сохранятся. Затем нажмите «Сохранить шаблон».

Загружен файл: {{ emailHtmlFileName }}

Тема: {{ emailPreview.subject }}
Превью Excel
{{ col }}
{{ row[col] }}

Конструктор писем Почты России

Короткий путь: организация → Excel → PDF → подпись КриптоПро → сохранить. Сервер только отправляет в ИС ЭПС.

· {{ epsSettings.url || 'http://eps:8010' }}
Код отправителя (из ID орг.)
{{ pochtaForm.sender_code || '—' }}
Название
{{ pochtaForm.sender_name || '—' }}
Страниц по договору ИС ЭПС (п. 7.5)
по умолчанию из карточки организации

Справочник пуст. .

По памятке ИС ЭПС: PDF/A-1, ≤5 МБ, A4 книжная, шрифты встроены, страниц {{ pochtaForm.min_pages || 1 }}–{{ pochtaForm.max_pages || 40 }} (договор). Оригинальный размер листов — не склеиваем мелко. Если сканов >10 — уберите лишние. Выписку уплотняем только при нехватке страниц.

Собрано из: {{ pochtaForm.pdf_sources.join(', ') }}

До отправки в Почту

Останутся крупными: {{ pochtaForm.pdf_size_plan.keep_full.map(x => x.name).join(', ') }}

Ужмём: {{ pochtaForm.pdf_size_plan.will_compress.map(x => x.name + (x.reason ? ' — ' + x.reason : '')).join('; ') }}

Могут измениться при лимите: {{ pochtaForm.pdf_size_plan.may_compact.map(x => x.name).join(', ') }}

На сервере сейчас: {{ pochtaForm.pdf_pages || '?' }} стр., {{ pochtaForm.pdf_images == null ? '?' : pochtaForm.pdf_images }} картинок, {{ pochtaForm.pdf_fonts == null ? '?' : pochtaForm.pdf_fonts }} стр. со шрифтами , {{ Math.round(pochtaForm.pdf_bytes / 1024) }} КБ, код {{ pochtaForm.pdf_sha }} — Почта отклонит (лимит 10 вложений)

Что сделала сборка ({{ pochtaForm.pdf_pack_notes.length }})
  • {{ n }}
{{ pochtaForm.has_sig ? '✓ Подпись сохранена' : 'Подпишите PDF' }}

Для ИС ЭПС подпись — отдельный файл .sig (отсоединённая PKCS#7). PDF со штампом можно скачать и просмотреть.

Тот же PFX организации (канал ГОСТ-TLS) — на сервере, либо плагин КриптоПро на этом ПК.

Переподписать заново
ЭУВ (для теста включите)

Адрес получателя перед отправкой чистит DaData. Ключи — в разделе {{ epsSettings.has_dadata ? ' (ключи есть)' : ' (ключей пока нет)' }}.

Дополнительно (адрес, тип, разряд, МЧД, штраф, XML)

Можно подставить из комментария организации. Без адреса поле не отправляется.

Реквизиты штрафа (charge)
Превью Excel
{{ col }}
{{ row[col] }}

Добавить новый вопрос

{{ index + 1 }}

Например: от 10 до 1, вместо от 1 до 10.

{{ newQuestion.settings.size_percent || 100 }}%

Пока абонент говорит, ответ не обрываем — ждём паузу ~2.5 сек. «Ожидание» — сколько ждать начала речи.

Готовые дорожки для обзвона

После сохранения вопросы, приветствие, прощание и фраза «не расслышал, повторите» озвучиваются заранее. В звонке ИИ синтезирует только новую реплику.

{{ currentProject.project.tts_status==='generating' ? ('Идёт озвучка ' + (currentProject.project.tts_done||0) + ' / ' + (currentProject.project.tts_total||0)) : (currentProject.project.tts_status==='ready' ? 'Озвучка сохранена' : 'Нажмите «Озвучить сценарий» после вопросов') }}

{{ currentProject.project.tts_error }}

Структура анкеты

Всего вопросов: {{ currentProject.questions.length }}

Анкета пуста

Добавьте свой первый вопрос, используя форму выше.

{{ index + 1 }}

{{ q.text }} {{ q.audio_path ? 'дорожка готова' : 'нет дорожки' }}

✍️ Текст 🔘 Выбор ⭐ Рейтинг
Варианты:
  • {{ opt }}
Шкала: {{ q.settings.reverse_scale ? q.settings.max + ' — ' + q.settings.min : q.settings.min + ' — ' + q.settings.max }} Обратная Кнопка "{{ q.settings.na_text }}"
Свободное текстовое поле

Индивидуальные ссылки по зданиям

Добавить здание вручную

«+» сохраняет здание в общий справочник. «Добавить в проект» привязывает его к этому голосованию и тоже пишет в справочник.

Массовая загрузка (CSV)

Скачать шаблон
В этом проекте пока нет привязанных зданий. Вы можете использовать общую ссылку проекта.
ЖК (Комплекс) Здание Действие
{{ b.responses_count }} отв.
0 отв.
Ничего не найдено по запросу "{{ searchBuildingQuery }}"

Настройки дизайна опроса

Глобальное отображение оценок (Рейтинг)

{{ currentProject.project.theme_settings.global_rating_size || 100 }}%
Применяется ко всем вопросам типа "Рейтинг" в этом проекте.

Настройте интервалы и текст, который будет отображаться под шкалой оценок.

-

Превью (Пример)

Насколько вы довольны чистотой в холле?

Пожалуйста, уточните ваш ответ:

Далее
Загрузка статистики...
Выгрузить Excel
Совпадений не найдено
Выбрано: {{ selectedStatsComplexes.length ? selectedStatsComplexes.length : 'все ЖК' }}
Совпадений не найдено
Выбрано: {{ selectedStatsBuildings.length ? selectedStatsBuildings.length : 'все здания' }}
Показано ответов: {{ statsSampleCount }} из {{ statsRegistryWithAnswers }}

{{ currentProject.project.title }}

{{ currentProject.project.description }}

Всего ответов: {{ statsSampleCount }}

{{ projectKind === 'inform' ? 'Где ролик не доходит' : 'Проблема по каждому дому' }}

Дома, где больше всего людей не дослушали сообщение или ещё стоят в очереди. Оценок в этом обзвоне нет — смотрим доставку, не индекс.

По каждому дому — одна тема высокого приоритета, которая сильнее тянет NPS вниз за всю кампанию. Цитата — самый свежий такой ответ.

Считаем брифинг по домам — цифры справа уже из дозвона, темы появятся следом. Пока нет домов, где ролик массово не доходит. Либо все дослушали, либо в доме меньше пяти контактов. Пока нет домов с жалобой высокого приоритета.
{{ i + 1 }} {{ priorityLabel(a.urgency) || 'Средний' }}
{{ a.headline }}
«{{ a.quote }}»
{{ a.full_name }}
Для директора

Цифры по выбранным домам: люди, не попытки набора.

Попытки — это звонки. Один человек может быть в нескольких попытках.

NPS
{{ fmtNps(directorBrief.nps) }}
{{ directorBrief.trust }}
Сторонники 9–10{{ directorBrief.promoters || 0 }} · {{ directorBrief.promoters_pct || 0 }}%
Нейтральные 7–8{{ directorBrief.passives || 0 }} · {{ directorBrief.passives_pct || 0 }}%
Критики 0–6{{ directorBrief.detractors || 0 }} · {{ directorBrief.detractors_pct || 0 }}%
Закрыты разговором
{{ directorBrief.closed || 0 }}
из {{ directorBrief.people || 0 }}. Сюда входят полный ролик, обрыв и отказ. Сколько дослушали до конца — без фильтра, по всей кампании.
Дослушали до конца
{{ directorBrief.heard_pct || 0 }}%
{{ directorBrief.heard || 0 }} до конца · {{ directorBrief.cut || 0 }} бросили на середине
Людей в базе
{{ directorBrief.people || 0 }}
попыток набора {{ directorBrief.calls }}
ещё не звонили {{ directorBrief.not_called || 0 }}
Не взяли трубку{{ directorBrief.no_answer || 0 }}
Занято{{ directorBrief.busy || 0 }}
Автоответчик{{ directorBrief.machine || 0 }}
Ошибка линии{{ directorBrief.failed || 0 }}
Отказались говорить{{ directorBrief.refused || 0 }}
Не дозвонились{{ directorBrief.failed || 0 }}
Горящих в очереди
{{ (analyticsDesk.briefing && analyticsDesk.briefing.hot) || 0 }}
высокий приоритет

Средний разговор

{{ talkTimeLabel }}

Шкала оценок 0–10

Сколько человек поставило каждую цифру.

Красный — 0–6, серый — 7–8, зелёный — 9–10. Сумма столбцов: {{ npsScaleTotal }}. Нажмите столбец — ответы и дома.

Тишина на уточнении: {{ campaignReport.followup_silent_pct }}% — человек дошёл до свободного вопроса и ничего не сказал.

Воронка сценария

Фильтр домов не режет попытки набора, поэтому воронка звонков здесь скрыта. Иначе «набрали» по всей кампании стояло бы рядом с оценками одного дома.

Первая цифра — попытки набора, не уникальные люди. Дальше: ответил человек → начал слушать → дослушал ролик. Разница последних двух — бросили на середине. Нажмите карточку — отчёт по этой цифре.

Первая цифра — попытки набора, не уникальные люди. Дальше: ответил человек → поставил оценку → договорил уточнение. Падение на шаге — где ломается сценарий. Нажмите карточку — отчёт по этой цифре.

Не поставили оценку: {{ shownScriptFunnel.hung_before_score || 0 }} — минус на шаге «Поставили оценку» Не договорили уточнение: {{ shownScriptFunnel.hung_on_followup || 0 }} — минус на шаге «Договорили уточнение»
Бросили на середине ролика: {{ analyticsDesk.script_funnel.cut || (directorBrief.cut || 0) }}
Из этих двух разностей
до оценки · уточнение · {{ q.text }} {{ q.count }}
Отправлено
{{ stats.outreach.totals.sent }}
Прочитано
{{ stats.outreach.totals.opened }}
Открываемость
{{ stats.outreach.totals.open_pct }}%
Охват зданий
{{ stats.outreach.totals.buildings_reached }} / {{ stats.outreach.totals.buildings }}
Статистика по зданиям

Дозвон — взяли трубку. Ответ — есть оценка или слова жителя. Охват — ответы от всех жителей дома. Нажмите строку — аналитика этого дома.

Здание Всего Отправлено Прочитано Дозвон Ответ Охват
{{ row.building }} {{ row.total }} {{ row.sent }} {{ row.opened }} {{ row.reached || 0 }} {{ row.responses || 0 }} {{ row.coverage_pct }}%

Линия, попытки звонков. Дослушали ролик и NPS — на брифинге, здесь их нет второй раз.

Динамика голосования

{{ activityGrain === 'hour' ? 'Час суток, сумма по всем дням. ' : (activityGrain === 'weekday' ? 'День недели, сумма по всей выборке. ' : '') }}{{ projectKind === 'inform' ? 'Три столбца: прозвонили, ответили, дослушали.' : 'Три столбца: прозвонили, ответили, проголосовали.' }}

Каждый столбец — один час суток, с 00 до 23. Сумма по всем дням выборки.

Каждый столбец — день недели, с понедельника по воскресенье. Сумма по всем дням выборки.

Недостаточно данных для графика

Устройства аудитории

Недостаточно данных для графика

Детальная аналитика по вопросам

Считаем, сколько ответов…
Ответы проверены — собираем категории
Ответов {{ themeJob.done || 0 }} из {{ themeJob.total }} · звонков с ответом {{ themeJob.calls_done || 0 }} из {{ themeJob.calls_total || 0 }}
Лояльность {{ themeJob.loyalty_done || 0 }} из {{ themeJob.loyalty_total }}
{{ themeJobNote }}
Вопросов в анкете: {{ aggregatedQuestions.length }}

{{ idx + 1 }}. {{ q.text }}

{{ q.type === 'rating' ? 'Рейтинг' : (q.type === 'choice' ? 'Выбор' : 'Свободный ответ') }}
Категории ответов
Всего: {{ themeAnswersCount(q) }}

Нажмите категорию — откроются ответы жителей и записи.

Ещё разбирается ответов: {{ q.text_themes_pending }}. Похожие формулировки («лифт не работает» и «лифт в плохом состоянии») сходятся в одну категорию.
Последние ответы:
Последние: {{ q.recent_texts ? q.recent_texts.length : 0 }}
{{ ans.theme }} "{{ ans.answer_value }}"
Пока нет текстовых ответов
Средняя оценка:
{{ getAverageRating(q.distribution) }} / {{ q.settings.max }}
Недостаточно данных для графика

Нет вопросов с рейтингом или ответов для расчета NPS

Общий NPS по всем вопросам

Всего оценок NPS: {{ overallNPS.total }}
{{ overallNPS.nps > 0 ? '+' : '' }}{{ overallNPS.nps }}
Индекс NPS
ПРОМОУТЕРЫ (9-10)
НЕЙТРАЛЫ (7-8)
КРИТИКИ (0-6)

Что съело NPS

Три темы, которые сильнее всего опускают общий индекс: на столько пунктов вырос бы NPS кампании, если бы эти жильцы оценивали как в среднем.

Динамика NPS по дням

Индекс и число оценок по дням — видно, сдвинулся ли результат после выезда или накопления.

Нужны оценки минимум за два дня

Драйверы NPS

Насколько тема тянет индекс относительно среднего кампании, а не доля упоминаний. Полоска — те же доли, что у общего NPS. Клик открывает карточки жильцов.

Промоутеры (9-10)
Нейтралы (7-8)
Критики (0-6)
Нет тем, связанных с оценкой

Дома по NPS

Цвет — индекс дома. Рядом честность выборки: недозвон по этому адресу не подменяет NPS.

Нет оценок по домам

NPS по ЖК (общий)

Сравнение итогового NPS по каждому ЖК

Недостаточно данных для сравнения по ЖК

NPS по каждому вопросу

{{ q.text }}

Всего ответов: {{ q.total }}
{{ q.nps > 0 ? '+' : '' }}{{ q.nps }} NPS
NPS по ЖК
Недостаточно данных для сравнения по ЖК

Инсайты по свободным ответам

{{ insightLead }}

Индекс операционного риска
{{ complaintInsights.kpis.risk_score }}
0–100 · критичность × доля аварий
Пока нет размеченных текстовых ответов. Подождите немного — категории считаются автоматически, пока проект не завершён.

Анкеты с содержанием: {{ loyaltyView.respondents }}. Тон ИИ есть у {{ loyaltyView.analyzed }}, ещё без тона {{ loyaltyView.pending }}.

Разобрано ИИ
{{ loyaltyView.analyzed }}
из {{ loyaltyView.respondents }} ответивших

· · · · прочее {{ loyaltyView.by.other }}. Вместе с «без тона» это все {{ loyaltyView.respondents }} ответивших.

9–10, а голос злой

Социальная желательность: оценка высокая, тон негативный. {{ (analyticsDesk.loyalty_gaps && analyticsDesk.loyalty_gaps.fake_promoters_n) || 0 }} чел.

Расхождений нет — либо мало разобранных звонков
{{ g.full_name || 'Жилец' }} · {{ g.building }} NPS {{ g.nps }}
«{{ g.quote }}»

0–6, а тон спокойный

Конструктивный критик: низкая оценка без злости. {{ (analyticsDesk.loyalty_gaps && analyticsDesk.loyalty_gaps.calm_critics_n) || 0 }} чел.

Пока нет спокойных критиков с оценкой и тоном ИИ
{{ g.full_name || 'Жилец' }} · {{ g.building }} NPS {{ g.nps }}
«{{ g.quote }}»

{{ col.title }}

{{ col.hint }} {{ col.cards.length }} чел.

В этом тоне никого нет
{{ g.full_name || 'Жилец' }} · {{ g.building }} NPS {{ g.nps }}
«{{ g.quote }}»

Дома по лояльности

Сумма по домам — те же разобранные, что на карточках: негатив {{ loyaltyView.by.negative }} · лояльные {{ loyaltyView.by.loyal }} · нейтрально {{ loyaltyView.by.neutral }} · смешанно {{ loyaltyView.by.mixed }}.

Нет домов с тоном ИИ
{{ b.avg == null ? '—' : b.avg }}
{{ b.total }} с тоном

Темы в разговорах

{{ t.name }} · {{ t.count }}
Примеры оценок ИИ
АбонентОценкаБаллКомментарий
{{ ex.full_name || ex.phone || '—' }} {{ {loyal:'Лоялен', negative:'Негатив', mixed:'Смешанно', neutral:'Нейтрально'}[ex.sentiment] || ex.sentiment }} {{ ex.score }} {{ ex.summary }}
Пока нет разобранных звонков — ИИ анализирует записи в фоне
Загрузка реестра...

Детализация ответов

Записей: {{ filteredRegistry.length }} Выгрузить в Excel (CSV)
Совпадений не найдено
Выбрано: {{ selectedStatsComplexes.length ? selectedStatsComplexes.length : 'все ЖК' }}
Совпадений не найдено
Выбрано: {{ selectedStatsBuildings.length ? selectedStatsBuildings.length : 'все здания' }}
Показано ответов: {{ filteredRegistry.length }} из {{ (stats.registry || []).length }}
ЖК Здание Канал Дата и время IP и Регион Браузер / ОС Вопросы NPS Ответы
{{ row.complex_name || '—' }} {{ row.building_name || '—' }}
{{ row.full_name }} кв. {{ row.apartment }}
{{ row.channel==='phone' ? 'телефон' : 'веб' }} {{ fmtServerDt(row.created_at) }}
{{ row.ip_address || 'Неизвестно' }}
{{ row.location || '' }}
{{ deviceLabel(row.user_agent) }} {{ callAnswerProgress(row).n }} из {{ callAnswerProgress(row).total }} не NPS NPS {{ rowNpsScore(row) }} —
{{ stats && (stats.lite || stats.full_pending) ? 'Считаем реестр ответов…' : 'Пока нет ни одного голоса' }}
Состояние кампании
Статус
{{ dialerStatusLabel(currentProject.project.dialer_status) }}
{{ successRuleLabel() }}
SIP
{{ globalKpi && globalKpi.sip_busy != null ? (globalKpi.sip_busy + ' / ' + globalKpi.sip_total) : '—' }}
{{ globalKpi.sip_reserve }} под входящие
Очередь
{{ (currentProject.project.progress && currentProject.project.progress.remaining) || 0 }}
Без номера
{{ (currentProject.project.progress && currentProject.project.progress.invalid_phone) || 0 }}
Неуспешные
{{ (currentProject.project.progress && currentProject.project.progress.unsuccessful) || 0 }}
{{ projectKind === 'inform' ? 'Без озвучки' : (projectKind === 'debt_call' ? 'Оплатили до звонка' : 'NPS') }}
{{ (currentProject.project.progress && currentProject.project.progress.paid) || 0 }}
{{ (currentProject.project.progress && currentProject.project.progress.no_audio) || 0 }}
Оценок NPS
{{ (currentProject.project.progress && currentProject.project.progress.answered_nps) || 0 }}
Полный опрос
{{ (currentProject.project.progress && currentProject.project.progress.answered_all) || 0 }}
из {{ currentProject.project.progress.questions_total }} вопр.
Ср. разговор
{{ (currentProject.project.progress && currentProject.project.progress.avg_talk_label) || '—' }}
До конца ≈
готово
{{ currentProject.project.progress.eta_label }}
—
к {{ shortEtaAt(currentProject.project.progress.eta_at) }} · ×{{ currentProject.project.progress.parallel }} лин. · ≈{{ currentProject.project.progress.avg_attempts }} попыток ср. · {{ progressHoursHint(currentProject.project.progress) }}
мало данных
Ждём озвучку {{ currentProject.project.tts_done || 0 }}/{{ currentProject.project.tts_total || 0 }} — набор начнётся сам.
{{ (preflight.blockers||[]).join(' · ') }}
Готово к запуску

Должники из 1С

Отметьте базы и дома. Дома и должники загружаются из каждой выбранной базы и остаются привязаны к ней. Перед звонком долг сверяется в той же базе: оплатил — не звоним.

{{ onecBuildingsError }}
Базы 1С

Баз 1С ещё нет.

Выключены и не участвуют: {{ debtSkippedBases.map(b => b.title || 'База 1С').join(', ') }}. Включите их в интеграции или сохраните проект без них.

{{ onecBuildingsLoading ? 'Загружаем дома из 1С…' : (debtForm.onec_base_ids.length ? 'Домов нет. Проверьте интеграцию с 1С или фильтр.' : 'Сначала отметьте базы 1С.') }}
Выбрано домов: {{ debtForm.building_ids.length }} · ЖК: {{ debtSelectedComplexes }}

«До» = 0 — без верхней границы. Если к моменту звонка долг упал ниже «от», человеку не звоним.

Открытый — счёт действует. Закрытый — уже не действует. Список обновится после «Загрузить должников».

Человек называет дом и квартиру или лицевой счёт. Дом ищется по всем домам подключённых баз 1С, не только по отмеченным для обзвона. Робот называет долг и пени и спрашивает, нужна ли квитанция.

Последняя загрузка: {{ shortEtaAt(debtForm.last_sync.at) }}
Должников: {{ debtForm.last_sync.total }} на {{ rub(debtForm.last_sync.total_debt) }}
новых {{ debtForm.last_sync.added }} · обновлено {{ debtForm.last_sync.updated }} · оплатили {{ debtForm.last_sync.paid }} · без телефона {{ debtForm.last_sync.no_phone }}

Список абонентов (Excel)

Скачайте шаблон, заполните его в Excel и загрузите обратно. Номер телефона обязателен. Для информирования шаблон содержит все поля, которые можно вставить в текст озвучки.

{{ excelUpload.stageLabel }} · {{ excelUpload.message }} {{ excelUpload.current }}/{{ excelUpload.total }}

{{ projectKind === 'inform' ? 'Запуск информирования' : 'Сценарий звонка' }}

Текст, голос и Excel задаются во вкладке «Конструктор». Здесь только запуск, попытки и пробный звонок.

Ролик дослушан до конца. Если трубку положили раньше — можно засчитать разговор длиннее указанного числа секунд. 0 — только полный ролик.

Сценарий по сумме долга

Робот выбирает текст по долгу на момент звонка. В текст можно вставить поля: сумма проговаривается словами.

без границы
Долг: {{ debtSegmentRange(i) }}
Озвучиваем {{ currentProject.project.tts_done || 0 }}/{{ currentProject.project.tts_total || 0 }}

Сценарий

Загрузите Excel — здесь появятся названия колонок файла.

Сценарий NPS (оценка 0–10)

Приветствие → оценка 0–10 голосом (5 сек) → уточнение (10 сек, тишина 5 сек → дальше) → прощание A (9–10) или B (0–8).

Робот говорит это, когда ответ записан, перед следующим вопросом. Для NPS можно оставить пустым — в шаблоне подтверждения отключены.

По умолчанию 9: оценка 9–10 → вариант A, 0–8 → вариант B.

Если в сценарии есть оценка 0–10, без цифры звонок успешным не считаем — даже при длинном разговоре.

Голос и попытки

Нет голосов в этом движке

{{ projectKind === 'debt_call' ? 'Трубку положили раньше, но разговор не короче этого — повторно не звоним. 0 — только дослушанное сообщение.' : 'Разговор не короче этого — дозвон, без повтора. 0 — только полный опрос или NPS.' }}

Сколько вопросов успели ответить — номер больше не перезваниваем. 1 — достаточно любой оценки или свободного ответа.

Профиль телефонии

Эти учётки проект использует и для исходящих, и для входящих. Ничего не отмечено — любая свободная линия. Профили создаются в меню «SIP-учётные записи».

SIP-учёток пока нет.
{{ projectSipIds.length ? ('Исходящие и входящие через: ' + projectSipTitles) : 'Проект звонит через любую свободную линию' }}

Запуск

Автотест линии: {{ mediaSelftest.verdict || '—' }}
{{ mediaSelftest.summary }}
RTP-пакеты: принято от АТС {{ mediaSelftest.last_call.rtp_qos.rxcount }} · отправлено {{ mediaSelftest.last_call.rtp_qos.txcount }} · медиа АТС: {{ mediaSelftest.last_call.rtp_qos.rtpdest }}
{{ c.ok ? '✓' : '✗' }} {{ c.id }} — {{ c.detail }}

После звонка: Звонки → Расшифровка → «Скачать диагностику» — JSON можно прислать для разбора. Или нажмите «Автотест линии».

Запуск

Старт / пауза / стоп и живые линии

{{ dialerStatusLabel(currentProject.project.dialer_status) }}

Запуск загружает свежий список должников из 1С. Перед каждым набором долг сверяется ещё раз.

Параллельность: рекомендуемо по ядрам CPU, автоснижение при перегрузе, потолок — слоты выбранных профилей. Если входящие включены, одна линия под них не занята набором.

Рекомендуемо: {{ globalKpi.parallel.recommended }} из {{ globalKpi.parallel.sip_total }} SIP · по ядрам {{ globalKpi.parallel.by_cpu }} ({{ globalKpi.parallel.cpu_count }} ядер) · занято {{ globalKpi.parallel.sip_busy }} · можно ещё {{ globalKpi.parallel.room }}
{{ globalKpi.parallel.reason_label }}
• {{ b }}
• {{ w }}
Готово к запуску
В разговоре: {{ liveTalkingCount }} · готовим набор {{ liveDialingCount }} · подробно справа от названия проекта
SIP выбранных профилей: {{ liveSip.busy || 0 }}/{{ liveSip.total || 0 }} · {{ liveSip.reserve }} под входящие — занято не этой кампанией или залипший слот
{{ n.text }}
{{ c.full_name || c.phone }}входящий
{{ c.stage_label || c.status }} · {{ liveElapsed(c.elapsed_sec) }} · SIP {{ c.sip_login }}
{{ c.stage_detail }} — {{ c.current_question }}
Ответ: {{ c.last_transcript }}
NPS {{ c.nps_score }}
{{ liveEmptyHint() }}
Загружаем аналитику…

{{ projectKind === 'pochta' ? 'Запуск рассылки Почты России' : 'Запуск рассылки' }}

Каждому получателю уходит тот же PDF, подписанный КриптоПро. После отправки ИС ЭПС может принять, отклонить или сменить статус (вручение / возврат) — фон пишет это в контакт и журнал; таблица обновляется сама. «Запросить статусы» / кнопка «Статус» у контакта — ручной опрос с полным ответом Почты. «Обновить ШПИ» / «Получить ЭУВ» — принудительно. Ниже — п. 61 и ф. 103.

Письма уходят через SMTP из раздела «Почтовый клиент». Скрытая метка открытия вставляется в каждое письмо автоматически.

Ожидают
{{ projectKind === 'pochta' ? pochtaStatus.pending : emailStatus.pending }}
Отправлено
{{ projectKind === 'pochta' ? pochtaStatus.sent : emailStatus.sent }}
Прочитано
{{ emailStatus.opened }}
В обработке
{{ pochtaStatus.in_progress || 0 }}
Вручено
{{ pochtaStatus.delivered || 0 }}
Со ШПИ
{{ pochtaStatus.mail_ids }}
ЭУВ получено
{{ pochtaStatus.edn_ready || 0 }}
{{ projectKind === 'pochta' ? 'Ошибки / возврат' : 'Ошибки' }}
{{ projectKind === 'pochta' ? pochtaStatus.failed : emailStatus.failed }}
Статус: {{ dialerStatusLabel(currentProject.project.dialer_status) }}
Реестр ф. 103

Zip за день отправки (не старше 30 дней). Если Почта ещё не сформировала реестр — будет «не найден», обычно появляется на следующий рабочий день.

Уведомления п. 61 ПОУПС

По всем ШПИ проекта, не больше 1000 за запрос.

Скачать zip
id: {{ pochtaForm.p61_id }} · {{ pochtaP61Status }}

{{ projectKind === 'email' ? 'Список получателей' : (projectKind === 'pochta' ? 'Получатели писем' : 'Список для обзвона') }}

{{ contactBuildingOptions.length ? 'Совпадений нет — нажмите + чтобы добавить' : 'Список пуст — введите название и нажмите +' }}

Поле «здание» обязательно. {{ projectKind === 'email' ? 'Укажите e-mail получателя.' : (projectKind === 'pochta' ? 'Для юрлица укажите организацию и ИНН, для физлица — ФИО и адрес.' : 'Номер очищается до цифр, 8XXXXXXXXXX → 7XXXXXXXXXX') }}

Выбрано {{ contactSelectionSize() }}
{{ progressPeople(currentProject && currentProject.project && currentProject.project.progress) || contactsTotal || contacts.length }} контактов · дубли {{ currentProject.project.progress.duplicate_rows }}
ЗданиеКв.ФИО {{ projectKind==='email' ? 'E-mail' : (projectKind==='pochta' ? 'Адрес / ШПИ' : 'Телефон') }} Лицевой счёт Основной долг Пени Общий долг Оплатили Остаток долга Действует ИНН {{ (projectKind==='pochta' || projectKind==='email') ? 'Статус отправки' : 'Статус звонка' }} Озвучка Прочитано ЭУВ Код / п. 61
{{ c.building }} {{ c.apartment }} {{ c.full_name }}
сегмент {{ c.extra_data._segment }}
дозвонились на {{ c.extra_data._numbers_reached || 0 }} из {{ c.extra_data._phones.length }}
{{ p }} — {{ debtNumberLabel(c, p) }}
{{ contactOrgName(c) }}
{{ (c.extra_data && c.extra_data['ЛС']) || '—' }} {{ debtAmount(c, 'principal') }} {{ debtAmount(c, 'penalties') }} {{ debtAmount(c, 'total') }} {{ debtCheckedAmount(c, 'paid') }} {{ debtCheckedAmount(c, 'remain') }} {{ (c.extra_data && c.extra_data['Действует']) || '—' }} {{ contactInn(c) || '—' }}
{{ projectKind === 'pochta' ? contactSendStatusLabel(c) : kpiContactLabel(c.status) }} Отследить на Почте
{{ contactLetterDesc(c) }}
{{ c.audio_path ? 'файл готов' : 'нет файла' }} {{ c.email_opened_at ? 'да' : 'нет' }}
{{ contactHasEdn(c) ? 'Готово' : (contactCanFetchEdn(c) ? 'Ещё нет' : '—') }}
Код {{ contactAccessCode(c) }}
Кода пока нет
п. 61 для суда
{{ contactP61Status(c) || 'запрошено' }}
Скачать zip
Нужен ШПИ
Список пуст — загрузите Excel
{{ contactsOffset + 1 }}–{{ Math.min(contactsOffset + contacts.length, contactsTotal) }} из {{ contactsTotal }}

Журнал звонков

само
ВремяАбонентТелефон ЖК Здание Квартира Лицевой счёт Долг Направление ИсходЛояльностьСек.
— {{ c.started_at || c.created_at }} {{ c.full_name || '—' }}
{{ debtOutcomeLabel(c.meta.outcome) }}
{{ c.building }} кв. {{ c.apartment }}
{{ c.phone || '—' }} {{ c.complex || '—' }} {{ c.building || '—' }} {{ c.apartment || '—' }} {{ c.account || '—' }} {{ c.debt != null && c.debt !== '' ? rub(c.debt) : '—' }} Входящий Исходящий
{{ c.outcome_label || kpiCallLabel(c.status) }}
{{ c.hangup_label }}
{{ c.reached ? ({loyal:'Лоялен', negative:'Негатив', mixed:'Смешанно', neutral:'Нейтрально'}[c.sentiment] || c.sentiment || 'анализ…') : '—' }} {{ c.duration_sec || 0 }}
Звонков пока нет
{{ callsOffset + 1 }}–{{ Math.min(callsOffset + calls.length, callsTotal) }} из {{ callsTotal }}

Журнал проекта

Отправка писем через ИС ЭПС: старт, каждое письмо (requestCode / ШПИ), ошибки и закрытие рассылки.

Отправка e-mail: старт, каждому получателю, ошибки и закрытие рассылки.

Исход попытки: дозвонились, не ответили, занято или набор не начался. В строке — что случилось, сколько ждали и что дальше с номером.

само
Время Исход Уровень Источник Что случилось
{{ row.created_at }} {{ logOutcome(row) }} — {{ {error:'Ошибка', warning:'Внимание', info:'Инфо'}[row.level] || row.level }} {{ row.source }} {{ logDetail(row) }}
Записей нет

Интеграция 1С

Баз может быть несколько. Проект «Обзвон должников» выбирает, из каких забирать дома и должников. В каждой 1С должно быть подключено расширение «АвтоОбзвон».

Путь сервиса /hs/obzvon дописывается сам. Запросы идут на: {{ onecServiceUrl(b) }}

{{ onecTestById[b.id].message }}
Конфигурация: {{ onecTestById[b.id].configuration }} {{ onecTestById[b.id].configuration_version }} · сервис {{ onecTestById[b.id].service_version }}

Авторизация Basic: в каждом запросе уходит заголовок Authorization: Basic base64(логин:пароль). Пользователю 1С нужна роль «Автообзвон: использование HTTP-сервиса должников».

Менять настройки может только администратор.

Журнал проверок связи

За сегодня. Под каждой строкой — технический лог: с какого адреса ушёл запрос, куда, код ответа и текст ошибки. Пароль в лог не пишется. Записи за прошлые дни удаляются.

Когда База Итог Что ответила 1С
{{ shortEtaAt(row.at) }} {{ row.title || 'База 1С' }} {{ row.ok ? 'Связь есть' : 'Нет связи' }} {{ row.message }}{{ row.configuration }} {{ row.configuration_version }}
{{ row.log }}
Проверок за сегодня ещё не было

SIP-учётные записи

Каждая запись — профиль телефонии: его выбирают в настройках проекта. Можно добавить SIP-учётку (одна линия) или транк со слотами (несколько параллельных звонков). Выключите запись — она не пойдёт в обзвон, связь с АТС сохранится. Статус обновляется каждые 8 секунд.

Шаблон Excel

У номера из 11 цифр при звонке первая цифра заменяется на выбранную. Короткие внутренние не меняются. У Дом.ру обычно 8. Входящий ищется и по 7, и по 8.

Ожидание набора

Сколько секунд ждать, пока исходящий станет живым звонком. Если канал Asterisk так и не появился — слот сбрасывается, номер снова в очереди. Это не недозвон: трубку ещё не звонили.

Сейчас: {{ sipDialer.orphan_wait_sec || 20 }} с. Журнал проекта пишет, дозвонились или нет и сколько ждали.

ЛогинТипХостПорт АОН Регистрация Активна Занятость
{{ s.login }}
{{ s.title }}
{{ s.kind === 'trunk' ? 'Транк' : 'Учётка' }}
{{ s.auth_mode === 'ip' ? 'по IP' : 'REGISTER' }}, слотов: {{ s.slots || 1 }}
набор через {{ s.dial_prefix === '8' ? '8' : '7' }}
{{ s.host }} {{ s.port }} {{ s.caller_id }} {{ s.kind === 'trunk' && s.auth_mode === 'ip' ? 'Доступен' : 'Зарегистрирована' }} Нет Проверка…
{{ s.reg_status || 'ожидание проверки' }}
{{ s.reg_reason || s.last_error }}
{{ s.enabled ? 'Да' : 'Нет' }} Не активна {{ s.used_slots || 0 }} / {{ s.slots || 1 }}
{{ sipRegDiag.login }}@{{ sipRegDiag.host }}:{{ sipRegDiag.port }} — {{ sipRegDiag.reg_status || '—' }}
{{ sipRegDiag.summary }}
{{ c.ok ? '✓' : '✗' }} {{ c.id }} — {{ c.detail }}
Снимок этой попытки REGISTER
{{ sipRegDiag.exchange.text || sipRegDiag.exchange.note }}

Почтовый клиент

Эти настройки используются для всех e-mail рассылок. Публичный адрес нужен, чтобы считать открытия писем.

Учёт открытий включён автоматически. Адрес сайта берётся из текущего входа в панель {{ mailSettings.public_url }} и скрытая метка вставляется в каждое письмо при отправке — поле указывать не нужно.

Fish Audio

API-ключ для живых голосов Алина и Максим. После сохранения обзвон подхватывает ключ сам, без правки Environment в Dokploy (обычно до 30 секунд).

{{ fishSettings.has_key ? 'Ключ сохранён' : 'Ключ не задан' }}
Без ключа система уходит на локальный голос (Silero / Edge).
Можно оставить поле ключа пустым, чтобы не менять сохранённый.

Кабинет Fish Audio → API. Ключ в git и в переписку не кладите.

Яндекс SpeechKit

API-ключ для голосов Яндекса. После сохранения обзвон подхватывает ключ сам, без правки Environment в Dokploy (обычно до 30 секунд).

{{ yandexSettings.has_key ? 'Ключ сохранён' : 'Ключ не задан' }}
Без ключа голоса Яндекса уходят на локальный Silero.
Можно оставить поле ключа пустым, чтобы не менять сохранённый.
Баланс Yandex Cloud
{{ formatYandexBalance(yandexBalance.balance) }} {{ yandexBalance.currency || 'RUB' }}
Запрашиваем баланс…
{{ yandexBalance.error }}
Нажмите «Обновить баланс»
{{ yandexBalance.billing_account_name || 'Аккаунт' }} · {{ yandexBalance.billing_account_id }} · неактивен

Нужна роль billing.accounts.viewer у сервисного аккаунта на платёжном аккаунте. Ключ только со scope SpeechKit баланс не покажет.

Yandex Cloud → сервисный аккаунт → API-ключ. Для баланса лучше ключ без узкого scope или с доступом к Billing.

Переопределяет API-имя для карточек «Алёна» / «Филипп». Остальные голоса (Джейн, Омаж, Марина, Ермил, Захар) вызываются своим кодом SpeechKit.

Для Алёны: good/neutral. Джейн: +evil. Марина: +whisper/friendly. Неподдерживаемое амплуа подставится автоматически.

Голос Эвереста

Нейронный русский мужской голос для карточки «Эверест» в конструкторе. Тон не занижается. Обычный системный голос включается только если нейронного нет.

В звонке звучит Microsoft Neural: Дмитрий или Павел, высота +0 Гц, темп не медленнее обычного. Google русский — это голос браузера Chrome, в трубку он не идёт. Настольный голос Windows не используется.

Если Павла нет на сервере синтеза, звонок идёт голосом Дмитрия — тоже нейронным, без занижения тона.

Почта России — шлюз ИС ЭПС

Шлюз eps и X-API-Key. Сертификат ГОСТ-TLS — свой у каждой организации (PFX привязанной подписи из ). Проверка канала всегда идёт от конкретной организации.

{{ epsSettings.error }}

ID/токен и PFX — в карточке организации. Этот блок только про контейнер eps.

ГОСТ-TLS:

Боевой сервер ИС ЭПС: api.zakaznoe.pochta.ru:3080 (ГОСТ-TLS). Шлюз ходит в gost-stunnel:13000+org_id, API /api/v2.6.

org {{ g.org_id }} → :{{ g.port || '—' }}

Загрузите PFX в карточку организации и нажмите «Использовать PFX этой организации для канала ГОСТ-TLS».

Туннель ещё не на КриптоПро CSP

OpenSSL не открывает PFX КриптоПро. Скачайте linux-amd64_deb.tgz (КриптоПро CSP для Linux, регистрация на cryptopro.ru), загрузите архив сюда и сделайте Restart gost-stunnel. Перед первой загрузкой нужен Rebuild nginx, backend и gost-stunnel.

Архив уже на диске. Осталось Restart gost-stunnel.

{{ epsSettings.gost_tls.csp_error }}

Туннель на КриптоПро CSP: PFX открывается через certmgr, без OpenSSL.

В Docker не меняйте: http://eps:8010.

Ключ контейнера eps, не путать с токеном организации в справочнике.

DaData — стандартизация адреса

Перед отправкой в ИС ЭПС адрес чистится через clean/address (индекс, регион, пункт, дом, квартира). ФИАС/КЛАДР пишем в JSON диагностики; в тело письма Почты поле ФИАС не входит — иначе ИС ЭПС может отклонить заявку. 20 коп. за адрес, ключ общий на все рассылки.

{{ epsSettings.has_dadata ? 'Ключи сохранены' : 'Ключей нет — пока разбор своей регуляркой' }}

Запрос к ИС ЭПС идёт с ID/токеном выбранной организации из справочника.

Справочник зданий

Общий список для обзвона, голосования, информирования, e-mail и Почты России. Новое название и прежние имена сразу переносятся в статистику: контакты, звонки и ответы считаются по карточке справочника. Если дом уже пропал из справочника, откройте нужную карточку и впишите старое имя в «Прежние названия».

Здание ЖК
{{ b.name }}
также: {{ b.former_names.join(', ') }}
{{ b.complex || '—' }}
{{ directoryBuildings.length ? 'Ничего не найдено' : 'Справочник пуст — добавьте здание здесь или кнопкой + в проекте' }}

Справочник организаций

Для модуля Почты России: ИНН, договор, БЗ, ID и токен ИС ЭПС, сертификат. Проверка канала ГОСТ-TLS — по каждой организации (кнопка «Канал»).

Скачать шаблон Excel

Экспортируйте контейнер из КриптоПро CSP в PFX/P12 с паролем. Отпечаток и туннель ГОСТ-TLS для этой организации подставим сами. Подпись PDF в проекте — отдельно плагином КриптоПро на компьютере оператора.

Отпечаток: {{ orgForm.cert_thumbprint || '—' }}{{ orgForm.cert_name ? ' · ' + orgForm.cert_name : '' }}

Наименование ИНН Договор БЗ ID Токен Сертификат
{{ o.name }} {{ o.inn || '—' }} {{ o.contract_number || '—' }} {{ o.bz_number || '—' }} {{ o.login || '—' }} {{ o.has_token ? 'задан' : 'нет' }} {{ o.cert_name || o.cert_thumbprint || (o.has_cert ? 'сохранён' : '—') }} CSP :{{ o.gost_tls_port }} PFX ждёт Restart {{ o.gost_tls_error }}
{{ directoryOrgs.length ? 'Ничего не найдено' : 'Справочник пуст — загрузите Excel или добавьте организацию вручную' }}

Расписание работы

У каждого дня своё окно по часам сервера. Выключенный день — выходной. Праздники подгружаются из производственного календаря РФ (isdayoff.ru).

{{ hoursSettings.tz_label || hoursSettings.tz || 'сервер' }}

Окно и все даты в журнале считаются по серверу, не по часам браузера.

Окно по дням недели
—

Например, понедельник 08:00–20:00, суббота 10:00–16:00. Выключенный день не набираем, кроме рабочей субботы из календаря.

Производственный календарь РФ

Праздники и переносы (рабочие субботы) с isdayoff.ru

Окно праздничных дней
—

Это окно на все даты из производственного календаря. Выключено — в праздники не звоним. «До конца» считает праздник этим окном, если оно включено.

Загружено: {{ hoursSettings.calendar_fetched_at }} · {{ hoursSettings.calendar_source }}
Годы: {{ (hoursSettings.calendar_years || []).join(', ') }}
Праздников: {{ hoursSettings.holidays_count || (hoursSettings.holidays || []).length || 0 }} · рабочих переносов: {{ hoursSettings.workdays_extra_count || (hoursSettings.workdays_extra || []).length || 0 }} · предпраздничных: {{ hoursSettings.preholidays_count || (hoursSettings.preholidays || []).length || 0 }}
{{ hoursSettings.calendar_error }}

Сейчас {{ hoursSettings.now || '—' }} · {{ hoursSettings.day_kind_label }} · сегодня {{ hoursSettings.today_from }}–{{ hoursSettings.today_to }} — {{ hoursSettings.within ? 'окно открыто, можно звонить и писать' : 'окно закрыто, задания ждут начала' }}

Бэкап и записи

Ночью сохраняется архив базы. Записи звонков старше указанного срока удаляются, транскрипты остаются.

Последний бэкап: {{ opsSettings.last_backup_at }} · {{ opsSettings.last_backup_file }}

Очистка записей: {{ opsSettings.last_purge_at }} ({{ opsSettings.last_purge_count || 0 }} файлов)

Состояние ИИ

Локальный Qwen (Ollama) или удалённый API на другом сервере. Рядом — распознавание речи (Яндекс, запасной Whisper) и нагрузка сервера.

{{ aiStatusError }}

ИИ
{{ (aiStatus && aiStatus.ai && aiStatus.ai.label) || 'Загрузка…' }}
Модель: {{ (aiStatus && aiStatus.ai && aiStatus.ai.model) || '—' }}
Отклик: {{ aiStatus && aiStatus.ai && aiStatus.ai.latency_ms != null ? (aiStatus.ai.latency_ms + ' мс') : (aiStatus && aiStatus.ai && aiStatus.ai.state === 'ok' ? 'есть' : 'нет связи') }}
{{ aiStatus.ai.error }}
Whisper
{{ (aiStatus && aiStatus.whisper && aiStatus.whisper.label) || 'Загрузка…' }}
Модель: {{ (aiStatus && aiStatus.whisper && aiStatus.whisper.model) || '—' }} · загружена
Сейчас: {{ aiStatus && aiStatus.whisper ? (aiStatus.whisper.inflight || 0) : '…' }} из {{ aiStatus.whisper.slots }} · {{ aiStatus.whisper.cpu_threads === 1 ? '1 ядро' : (aiStatus.whisper.cpu_threads + ' ядер') }} на распознавание · CPU {{ aiStatus.whisper.cpu_percent }}%
За минуту: {{ aiStatus && aiStatus.whisper ? (aiStatus.whisper.minute_total || 0) : '…' }} · Яндекс {{ aiStatus.whisper.minute_yandex || 0 }} · Whisper {{ aiStatus.whisper.minute_whisper || 0 }}
Память процесса {{ aiStatus.whisper.rss_mb }} МБ
Последний отклик {{ aiStatus.whisper.last_ms }} мс · {{ aiStatus.whisper.last_engine === 'yandex' ? 'Яндекс' : 'Whisper' }}
Яндекс недоступен ({{ aiStatus.whisper.yandex_off_reason }}), проверка через {{ aiStatus.whisper.yandex_retry_sec }} с — пока Whisper
{{ aiStatus.whisper.error }}
Сервер
{{ serverClockDate(aiStatus && aiStatus.clock) }} {{ (aiStatus && aiStatus.clock && aiStatus.clock.now_time) || hoursSettings.now_time || '' }}
{{ (aiStatus && aiStatus.clock && (aiStatus.clock.tz_label || aiStatus.clock.tz)) || hoursSettings.tz_label || hoursSettings.tz || '' }}
CPU {{ (aiStatus && aiStatus.host && aiStatus.host.cpu_percent != null) ? aiStatus.host.cpu_percent : '…' }}%
Память {{ aiStatus && aiStatus.host ? aiStatus.host.mem_percent : '…' }}% · {{ aiStatus && aiStatus.host ? aiStatus.host.mem_used_mb : '…' }} / {{ aiStatus && aiStatus.host ? aiStatus.host.mem_total_mb : '…' }} МБ
Нагрузка {{ aiStatus && aiStatus.host ? aiStatus.host.load_1 : '…' }} / {{ aiStatus && aiStatus.host ? aiStatus.host.cpu_count : '…' }} ядер
Диск {{ aiStatus && aiStatus.host ? aiStatus.host.disk_percent : '…' }}% · {{ aiStatus && aiStatus.host ? aiStatus.host.disk_used_gb : '…' }} / {{ aiStatus && aiStatus.host ? aiStatus.host.disk_total_gb : '…' }} ГБ · свободно {{ aiStatus && aiStatus.host ? aiStatus.host.disk_free_gb : '…' }} ГБ
Иноды {{ aiStatus && aiStatus.host && aiStatus.host.inode_percent != null ? (aiStatus.host.inode_percent + '%') : '—' }} · ожидание {{ aiStatus && aiStatus.host && aiStatus.host.disk_iowait_percent != null ? (aiStatus.host.disk_iowait_percent + '%') : '—' }} · чтение {{ aiStatus && aiStatus.host && aiStatus.host.disk_read_mb_s != null ? aiStatus.host.disk_read_mb_s : '—' }} / запись {{ aiStatus && aiStatus.host && aiStatus.host.disk_write_mb_s != null ? aiStatus.host.disk_write_mb_s : '—' }} МБ/с · занят {{ aiStatus.host.disk_busy_percent }}%
{{ vi ? ' · ' : '' }}{{ vol.name }} {{ vol.percent }}% (своб. {{ vol.free_gb }} ГБ)
{{ aiStatus.host.disk_alerts.join(', ') }}
{{ aiStatus.recordings.line }}
Обзвон: до {{ aiStatus.parallel.recommended }} паралл. (SIP {{ aiStatus.parallel.sip_busy }}/{{ aiStatus.parallel.sip_total }}, {{ aiStatus.parallel.reason_label }})
Автоперезапуск
{{ !aiStatus ? 'Загрузка…' : (aiStatus.overloaded ? 'Перегруз' : 'Норма') }}
Docker: {{ aiStatus.docker ? 'сокет есть' : 'сокет не подключён' }}{{ aiStatus.docker_control ? ', перезапуск разрешён' : ', DOCKER_CONTROL=0' }}
Последний перезапуск: {{ aiStatus.watchdog.last_restart_at }}
{{ aiStatus.reasons.join(', ') }}

Источник Qwen

Локальный контейнер ollama останавливается в режиме API и не поднимается при перезапуске служб, пока снова не включите локальный режим.

{{ llmForm.mode === 'remote' ? 'Qwen по API' : 'Локальный Qwen' }}
{{ llmForm.mode === 'remote' ? 'Запросы идут на URL ниже' : 'Запросы идут в контейнер ollama на этом сервере' }}
Локальный API

Локально обычно qwen2.5:1.5b (не путать с моделью remote API).

URL: {{ llmForm.local_url || 'http://ollama:11434' }}

Для URL вида …/v1 выбирайте OpenAI. Ollama — если база без /v1 (порт 11434).

В базе: {{ aiStatus.llm.mode === 'remote' ? 'API' : 'локальный' }} · {{ aiStatus.llm.remote_url }} · на экране не сохранено

{{ llmSaveError }}

Службы проекта
Служба Состояние Статус
{{ c.service }} {{ c.state }} {{ c.status }}

KPI обзвона

Загрузка…
{{ kpiCallLabel(key) }}
{{ val }}
Средняя длительность: {{ globalKpi.avg_duration }} сек
SIP занято / всего: {{ globalKpi.sip_busy }} / {{ globalKpi.sip_total }}
Рекомендуемый параллелизм: {{ globalKpi.parallel.recommended }} (по ядрам {{ globalKpi.parallel.by_cpu }}, {{ globalKpi.parallel.reason_label }})
{{ kpiContactLabel(key) }}
{{ val }}
Без номера
{{ globalKpi.invalid_phone }}
Без озвучки
{{ globalKpi.no_audio }}