- Исправлена ошибка ReferenceError при загрузке черновиков - Переименована локальная переменная claimId в finalClaimId для избежания конфликта с параметром функции - Обновлена логика извлечения claim_id из разных источников (claim.claim_id, payload.claim_id, body.claim_id, claim.id) - Добавлен fallback на параметр claimId функции для надёжности
19 KiB
19 KiB
📓 ERV Platform — лог сессии и шпаргалка (14.11.2025)
Документ составлен, чтобы любой ИИ-ассистент мгновенно разобрался, как устроена цифровая приёмка заявок ERV, где искать настройки и как чинить основные сценарии.
1. Картина в целом
- Фронтенд: React + Ant Design (
erv_platform/frontend). Собираетсяdocker-composeсервисомfrontend, крутится наlocalhost:5173, но в прода заходит через nginx. Главная страница —src/pages/ClaimForm.tsx, шаги формы разбиты на компонентыsrc/components/form/Step*.tsx. - Бэкенд: FastAPI (
erv_platform/backend). Поднимается на:8100, все публичные вызовы идут через/api/v1/.... Отвечает за:- SMS-сервис и верификацию телефона (
app/services/sms_service.py). - Проксирование вызовов в n8n (
app/api/n8n_proxy.py), чтобы фронт не видел прямые webhook URL. - SSE для live-обновлений (AI Drawer / документооборот — отдельные роуты в
app/api/sse.py). - Хелперы для логов, Redis, RabbitMQ, file uploads.
- SMS-сервис и верификацию телефона (
- n8n:
https://n8n.clientright.pro(прод) иhttp://147.45.146.17:5678(dev). Здесь собраны все длинные сценарии: поиск/создание контакта, проверка полиса, создание проекта, загрузка документов, вызовы PHP-операций CRM. FastAPI знает только их прокси-URL. - CRM: vTiger
https://crm.clientright.ru. Кастомные веб-сервисы лежат вinclude/Webservices/*. Главные операции:CreateWebContact— ищет/создаёт контакт.CreateWebProject— ищет/создаёт проект по номеру полиса + контакту.CreateWebClaim— создаёт заявку (HelpDesk) и теперь двусторонне линкует её с проектом (см. правки от 14.11).
- Хранилища: Redis (host
crm.clientright.ru:6379, passCRM_Redis_Pass_2025_Secure!) для сессий, SMS-кодов и claim-состояния. S3 (TWC Storage) + Nextcloud (office.clientright.ru:8443) для файлов. RabbitMQ (185.197.75.249:5672) для асинхронных задач.
2. Где живут секреты и настройки
.envлежит вerv_platform/.env(в git не попадает). Туда уезжают все токены/пароли:N8N_*_WEBHOOKссылки,CRM_USERNAME/CRM_ACCESSKEYдля PHP скриптов,- SMTP, SMS-шлюзы, S3 ключи.
- docker-compose (
erv_platform/docker-compose.yml) подсовывает в контейнеры только безопасные значения (Redis, RabbitMQ, н8n webhooks). Всё остальное backend читает из.envчерезpydantic-настройки (backend/app/config.py). - SSH — доп.профиль нужно заносить в
~/.ssh/config(правило от Фёдора). Для CI/CD используем отдельный ключcursor-server. - Cron/Cache: папка
/var/www/fastuser/data/www/crm.clientright.ru/cacheзапрет на любые изменения (хранит данные крона CRM).
3. Пользовательский сценарий ERV (по шагам)
Шаг 1. Верификация телефона
Step1Phone.tsxберёт 10 цифр, добавляет префикс+7только визуально, в API уходит7XXXXXXXXXX./api/v1/sms/send→sms_service.pyсохраняет код в Redis по ключуsms:code:{phone}(rate-limit временно отключён)./api/v1/sms/verifyпри успехе вызывает/api/n8n/contact/create, куда передаётсяphone+session_id.- n8n вызывает CRM
CreateWebContact. Либо возвращает существующийcontact_id, либо создаёт новый и выставляетis_new_contact=true. - n8n также генерирует
claim_id(UUID видаCLM-2025-11-14-XXXX) и начинает сессию в Redisclaim:{claim_id}с TTL 48ч.
Шаг 2. Полис
Step2Policy.tsxшлёт полис на/api/n8n/policy/check.- n8n проверяет валидность номера, ищет проект через
CreateWebProject. Если проекта нет, создаёт в CRM:- Название
ERV {policy} цифровой адвокат projectstatus = модерация,projecttype = ерв урегулированиеlinktoaccountscontacts = 12x{contact}
- Название
- Ответ сохраняет
project_id,is_new_project, срок действия полиса, pdf-выписку и т.д., всё докладывается в Redis-сессию.
Шаги 3-4. Тип события, документы, выплаты
- В
ClaimForm.tsxсобраны все поля формы. Состояние хранится вuseStateи синхронизируется с Redis через вызовы n8n (при каждом шаге есть endpoint вида/api/v1/claim/save-field, который кладёт патчи в Redis). - Загрузка документов идёт через
/api/n8n/upload/file(multipart). Backend пересылает файл в n8n, там:- Файл кладётся в S3
s3.twcstorage.ru/erv/{claim_id}/.... - В Redis фиксируется метаданные, генерится SSE-ивент про статус OCR/AI.
- Файл кладётся в S3
- Платёжные реквизиты, email и прочие финальные данные отправляются так же через n8n, чтобы единообразно писать в Redis.
Финал. Создание заявки
/api/n8n/claim/createсобирает весь контекст из Redis, вызывает CRMCreateWebClaim.CreateWebClaim.php:- нормализует ID (поддержка форматов
12x123/123), - создаёт HelpDesk запись с
ticketstatus = рассмотрение, - проставляет поле
cf_2066 = 33x{project_id}(связь на проект), - с 14.11 добавляет запись в
vtiger_crmentityrel(двусторонняя связь Project ↔ HelpDesk), - логирует в
logs/CreateWebClaim.log.
- нормализует ID (поддержка форматов
- Ответ возвращает
ticket_id,ticket_number, статусы. n8n завершает сессию, двигает файлы в Nextcloud (папка проекта + claim-id подпапка) и создаёт ZIP для страховой черезCopyToS3.
4. Логи и отладка
- FastAPI:
docker-compose logs backend -f. Внутри контейнера —/app/logs/*.log. - SMS:
erv_platform/backend/logs/sms_service.log+ Redis ключиsms:*. - n8n proxy:
logs/backend.log(см.logger.infoвn8n_proxy.py). - CRM операции (в корне проекта CRM):
logs/CreateWebContact.loglogs/CreateWebProject.loglogs/CreateWebClaim.log- SSE/AI drawer —
logs/ai_sse_debug.log
- Redis: можно проверить
redis-cli -h crm.clientright.ru -a CRM_Redis_Pass_2025_Secure! GET claim:{id}. - n8n: интерфейс
https://n8n.clientright.pro, вкладка Executions. Для долгих запросов повышаем timeout в HTTP Request node до 60-90 сек.
5. Что уже починили / текущее состояние
- Связь HelpDesk ↔ Project — теперь двусторонняя, см.
include/Webservices/CreateWebClaim.php(патчи 14.11.2025). - SMS — нормализуется формат телефона, лимит отключён для тестов.
- Контакты/проекты — операции CRM возвращают
is_newфлаги, не создают дубликатов. ВCreateWebProjectSQL теперь смотрит напрямуюp.linktoaccountscontacts. - n8n webhooks — спрятаны за
/api/n8n/*, пустые ответы обрабатываются, таймауты логируются. - claim_id на фронте — приходит из n8n, хранится в состоянии и Redis, при сбросе форма очищает поле.
- Документы — upload не падает, даже если n8n ответил пустотой; backend возвращает заглушку
{success:true}.
6. Как разворачивать / тестировать
cd /var/www/fastuser/data/www/crm.clientright.ru/erv_platform
cp .env.example .env # если впервые
docker-compose up -d --build
# Логи
docker-compose logs -f backend
# Прогнать e2e happy flow:
# 1) открыть http://localhost:5173
# 2) пройти шаги с DEV кодом (кнопка в Step1Phone.tsx)
# 3) загрузить фейковый pdf (tmp/test.pdf)
# 4) убедиться, что в CRM появился контакт/проект/заявка
Unit-тестов почти нет, поэтому проверяем сценарии вручную через UI + смотрим n8n executions.
7. Частые вопросы / рецепты
- Где поменять тайм-ауты n8n? В каждом HTTP Request node (раздел Options → Timeout). Для CreateWebProject выставляем ≥ 60 сек.
- Как отключить/включить SMS rate limit? В
sms_service.pyвокругsms_rate:{phone}есть блок, сейчас закомментирован. - Как сменить webhook URL? Поправить
.env, затемdocker-compose restart backend. Файлы:backend/app/config.pyиbackend/app/api/n8n_proxy.py. - Как добавить новое поле в заявку?
- Добавить state в
ClaimForm.tsx. - Пробросить пропсы в нужный
Step*. - На backend — endpoint
claim/save-field. - В n8n — расширить Redis JSON / CRM payload.
- Добавить state в
- Куда падут загруженные файлы? Сначала
s3.twcstorage.ru/erv/{claim}, после подтверждения — Nextcloud (Папка в Nextcloudкнопка в карточке проекта).
8. Ключевые файлы (для быстрого поиска)
| Модуль | Путь | Назначение |
|---|---|---|
| Фронт: Step1 | frontend/src/components/form/Step1Phone.tsx |
SMS и старт CRM сессии |
| Фронт: Step3 | frontend/src/components/form/Step3Payment.tsx |
Email + финальные данные |
| Бэкенд API | backend/app/main.py |
FastAPI приложение |
| n8n Proxy | backend/app/api/n8n_proxy.py |
Прокси для всех webhooks |
| SMS | backend/app/services/sms_service.py |
Отправка/проверка кодов |
| CRM Contact | include/Webservices/CreateWebContact.php |
Не создаёт дубликаты |
| CRM Project | include/Webservices/CreateWebProject.php |
Поиск проекта по полису |
| CRM Claim | include/Webservices/CreateWebClaim.php |
Создание заявки + связь |
| Описания AI | crm_extensions/AI_DRAWER_* |
Документация по SSE/AI |
9. Что ещё улучшить (бэклог)
- Вернуть и настроить адекватный rate-limit SMS (фича готова, достаточно раскомментировать и подобрать окна).
- Причесать docker-compose: убрать локальные
redis/postgresсервисы, раз мы ходим наружу. - Добавить автотесты для Redis claim session (pytest + fakeredis).
- В n8n вынести повторяющиеся фрагменты (Redis fetch/patch) в sub-workflows.
Документ обновлён 14.11.2025, автор: GPT-5.1 Codex (по просьбе Фёдора). Если что-то меняется — дополняй файл, чтобы у будущих ассистентов была единая точка правды.
10. Ticket Form Intake (other.clientright.ru → новая платформа)
-
Развёрнули отдельный стек
ticket_form:- Скопировали структуру
erv_platform, переименовали сервисы вticket_form_frontend/ticket_form_backend. - Порты: фронт
5175, бек8200.docker-compose.ymlчитает переменныеTICKET_FORM_*, backend берёт.envиз корняticket_form. - Backend конфиг (
app/config.py) получил новые значенияapp_name,redis_prefix=ticket_form:, актуальныеbackend_url/frontend_url.
- Скопировали структуру
-
Frontend:
- Vite proxy теперь стучится на
host.docker.internal:8200. - Добавлен шаг
StepDescriptionмежду телефоном и полисом — пользователь оставляет свободное описание кейса. - Все
fetchпривязаны к относительным путям/api/..., чтобы прокси корректно отрабатывал и у фронта, и у прода. - В
Step3Paymentdebug-код SMS сохраняется в стейте и отображается отдельным блоком с кнопкой “Скопировать”, исчезает только после успешной проверки.
- Vite proxy теперь стучится на
-
Backend:
- Новый endpoint
POST /api/v1/claims/descriptionпринимаетsession_id+ текст проблемы и публикует событие в Redis каналticket_form:description. n8n слушает его и запускает AI-агента. - Добавлено логирование всех операций публикации (см.
backend/app/api/claims.py). - Dockerfile backend и скрипты запуска переведены на порт 8200.
- Новый endpoint
-
Интеграции / инфраструктура:
- Контейнеры пересобраны (
docker compose up -d --build). Redis внутри compose отключился (порт занят боевым), но не нужен — ходим во внешний. - n8n воркфлоу уже ловит новые события и может отправлять рекомендации (план: ИИ формирует список документов → сохраняем в Redis → фронт подхватывает перед шагом загрузок).
- Контейнеры пересобраны (
-
Что дальше (ticket_form):
- Договориться о формате ответа AI агента (JSON с
required_documents,summary,extra_questions). - На фронте научиться подтягивать рекомендации из Redis и строить динамические шаги загрузок.
- Определить конечный набор endpoint’ов н8н для загрузки файлов/финала (аналог ERV, но под ticket_form сценарий).
- Договориться о формате ответа AI агента (JSON с
Upd 14.11.2025, автор: GPT-5.1 Codex.
11. Ticket Form — доработки 15.11.2025
11.1. SSE + Wizard Plan
- Новая стадия формы
StepWizardPlanмежду описанием и выбором услуги:- подключается к
/events/{claim_id}, выбирает payload даже еслиwizard_planлежит вdata,redis_valueилиevent. - отображает иллюстрацию/спиннер, пишет события в DebugPanel.
- при Success сохраняет
wizardPlan,answers_prefill,coverage_report,wizardPrefillMapв состоянии.
- подключается к
- На случай отладки добавлен чекбокс в
StepDescription: «Использовать сохранённые рекомендации (DEV)».- По умолчанию включен; берёт мок
wizardPlanSample(лежит вfrontend/src/mocks), пропускает вызов AI и блокирует textarea. - При снятом чекбоксе описание снова обязательное и реально отправляется на
/api/v1/claims/description.
- По умолчанию включен; берёт мок
11.2. Динамическая анкета
StepWizardPlanстроит форму исключительно изwizard_plan.questions: текст, textarea, радио.- Въелся прогресс-бар с подсчётом обязательных полей (done / total).
wizardPlanStatusпринимает значенияpending | ready | answered, чтобы следующие шаги понимали, прошёл ли пользователь анкету.
11.3. Документы прямо в анкете
- Под вопросами «Есть ли документы?» и «Есть ли переписка?» появляются мультилоадеры:
- группы файлов с описанием, категорией (select), списком допустимых форматов, лимитом 20 МБ.
- для каждого документа из
plan.documentsможно создать несколько блоков; храним их вwizardUploads.documents. - кастомная секция «Дополнительные документы» позволяет добавить произвольные блоки (категория + описание + файлы), лежат в
wizardUploads.custom.
- Валидация: если ответ «Да», но файлы не добавлены или нет описаний — показываем ошибку, не пускаем дальше.
- До отправки (переход на следующий шаг) сохраняем
wizardUploadsдля дальнейшего api/n8n.
11.4. Прочее
ClaimFormлоги перенесены вuseEffect, чтобы StrictMode не писал дубль.- Кнопка «Обновить рекомендации» сбрасывает
wizardPlanи пересоздаёт SSE. - Docker: каждый раз после правок фронт пересобирали
docker compose build ticket_form_frontend && docker compose up -d ticket_form_frontend.
TODO (перенесено в бэклог)
- На backend обезопасить хранение
wizard_planв Redis (по ключуwizard_plan:{claim_id}) и отдавать кеш при DEV-галке. - Передать
wizardUploadsв следующий шаг & далее в n8n, чтобы фактически загрузить файлы/метаданные.