Files
aiform_prod/SESSION_LOG_2025-11-14.md
2025-11-15 18:48:15 +03:00

226 lines
19 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 📓 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.
- **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`, pass `CRM_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. Верификация телефона
1. `Step1Phone.tsx` берёт 10 цифр, добавляет префикс `+7` только визуально, в API уходит `7XXXXXXXXXX`.
2. `/api/v1/sms/send``sms_service.py` сохраняет код в Redis по ключу `sms:code:{phone}` (rate-limit временно отключён).
3. `/api/v1/sms/verify` при успехе вызывает `/api/n8n/contact/create`, куда передаётся `phone` + `session_id`.
4. n8n вызывает CRM `CreateWebContact`. Либо возвращает существующий `contact_id`, либо создаёт новый и выставляет `is_new_contact=true`.
5. n8n также генерирует `claim_id` (UUID вида `CLM-2025-11-14-XXXX`) и начинает сессию в Redis `claim:{claim_id}` с TTL 48ч.
### Шаг 2. Полис
1. `Step2Policy.tsx` шлёт полис на `/api/n8n/policy/check`.
2. n8n проверяет валидность номера, ищет проект через `CreateWebProject`. Если проекта нет, создаёт в CRM:
- Название `ERV {policy} цифровой адвокат`
- `projectstatus = модерация`, `projecttype = ерв урегулирование`
- `linktoaccountscontacts = 12x{contact}`
3. Ответ сохраняет `project_id`, `is_new_project`, срок действия полиса, pdf-выписку и т.д., всё докладывается в Redis-сессию.
### Шаги 3-4. Тип события, документы, выплаты
1. В `ClaimForm.tsx` собраны все поля формы. Состояние хранится в `useState` и синхронизируется с Redis через вызовы n8n (при каждом шаге есть endpoint вида `/api/v1/claim/save-field`, который кладёт патчи в Redis).
2. Загрузка документов идёт через `/api/n8n/upload/file` (multipart). Backend пересылает файл в n8n, там:
- Файл кладётся в S3 `s3.twcstorage.ru/erv/{claim_id}/...`.
- В Redis фиксируется метаданные, генерится SSE-ивент про статус OCR/AI.
3. Платёжные реквизиты, email и прочие финальные данные отправляются так же через n8n, чтобы единообразно писать в Redis.
### Финал. Создание заявки
1. `/api/n8n/claim/create` собирает весь контекст из Redis, вызывает CRM `CreateWebClaim`.
2. `CreateWebClaim.php`:
- нормализует ID (поддержка форматов `12x123`/`123`),
- создаёт HelpDesk запись с `ticketstatus = рассмотрение`,
- проставляет поле `cf_2066 = 33x{project_id}` (связь на проект),
- с 14.11 добавляет запись в `vtiger_crmentityrel` (двусторонняя связь Project ↔ HelpDesk),
- логирует в `logs/CreateWebClaim.log`.
3. Ответ возвращает `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.log`
- `logs/CreateWebProject.log`
- `logs/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. Что уже починили / текущее состояние
1. **Связь HelpDesk ↔ Project** — теперь двусторонняя, см. `include/Webservices/CreateWebClaim.php` (патчи 14.11.2025).
2. **SMS** — нормализуется формат телефона, лимит отключён для тестов.
3. **Контакты/проекты** — операции CRM возвращают `is_new` флаги, не создают дубликатов. В `CreateWebProject` SQL теперь смотрит напрямую `p.linktoaccountscontacts`.
4. **n8n webhooks** — спрятаны за `/api/n8n/*`, пустые ответы обрабатываются, таймауты логируются.
5. **claim_id на фронте** — приходит из n8n, хранится в состоянии и Redis, при сбросе форма очищает поле.
6. **Документы** — upload не падает, даже если n8n ответил пустотой; backend возвращает заглушку `{success:true}`.
---
## 6. Как разворачивать / тестировать
```bash
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`.
- **Как добавить новое поле в заявку?**
1. Добавить state в `ClaimForm.tsx`.
2. Пробросить пропсы в нужный `Step*`.
3. На backend — endpoint `claim/save-field`.
4. В n8n — расширить Redis JSON / CRM payload.
- **Куда падут загруженные файлы?** Сначала `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 → новая платформа)
1. **Развёрнули отдельный стек `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`.
2. **Frontend:**
- Vite proxy теперь стучится на `host.docker.internal:8200`.
- Добавлен шаг `StepDescription` между телефоном и полисом — пользователь оставляет свободное описание кейса.
- Все `fetch` привязаны к относительным путям `/api/...`, чтобы прокси корректно отрабатывал и у фронта, и у прода.
- В `Step3Payment` debug-код SMS сохраняется в стейте и отображается отдельным блоком с кнопкой “Скопировать”, исчезает только после успешной проверки.
3. **Backend:**
- Новый endpoint `POST /api/v1/claims/description` принимает `session_id` + текст проблемы и публикует событие в Redis канал `ticket_form:description`. n8n слушает его и запускает AI-агента.
- Добавлено логирование всех операций публикации (см. `backend/app/api/claims.py`).
- Dockerfile backend и скрипты запуска переведены на порт 8200.
4. **Интеграции / инфраструктура:**
- Контейнеры пересобраны (`docker compose up -d --build`). Redis внутри compose отключился (порт занят боевым), но не нужен — ходим во внешний.
- n8n воркфлоу уже ловит новые события и может отправлять рекомендации (план: ИИ формирует список документов → сохраняем в Redis → фронт подхватывает перед шагом загрузок).
5. **Что дальше (ticket_form):**
- Договориться о формате ответа AI агента (JSON с `required_documents`, `summary`, `extra_questions`).
- На фронте научиться подтягивать рекомендации из Redis и строить динамические шаги загрузок.
- Определить конечный набор endpointов н8н для загрузки файлов/финала (аналог ERV, но под ticket_form сценарий).
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, чтобы фактически загрузить файлы/метаданные.