226 lines
19 KiB
Markdown
226 lines
19 KiB
Markdown
# 📓 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, чтобы фактически загрузить файлы/метаданные.
|
||
|