Files
aiform_dev/SESSION_LOG_2025-10-30.md
AI Assistant 8c21450e4a docs: Лог сессии 30 октября - Телефон на шаг 1 + интеграция CRM
- Перенос телефона на первый шаг с SMS верификацией
- Создана операция CreateWebContact в vTiger CRM
- N8N workflow: контакт + claim_id + Redis session
- Docker-compose: убраны локальные postgres/redis
- Backend подключён к внешним сервисам
- Флаг is_new_contact для UX (новый vs существующий клиент)
- Исправлено 7 проблем (Postgres v16, Redis, N8N webhooks, Gitea)
- Готовность к черновикам и личному кабинету
2025-10-30 19:59:56 +03:00

598 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.

# 📋 Лог сессии: Телефон на шаг 1 + интеграция с CRM
**Дата:** 30 октября 2025 (07:00 - 20:00 MSK)
**Задача:** Перенос телефона на первый шаг и создание контакта в CRM
**Статус:** ✅ Успешно завершено
---
## 🎯 Основная задача
Переделать флоу формы:
1. **Шаг 1:** Подтверждение телефона по SMS (вместо полиса)
2. **Автоматическое создание контакта в CRM** сразу после SMS
3. **Сохранение сессии в Redis** для дальнейшей работы
4. Подготовка к черновикам заявок и личному кабинету
---
## ✅ Выполненные задачи
### 1. Создан Step1Phone.tsx
**Назначение:** Первый шаг формы - подтверждение телефона
**Функционал:**
- Ввод телефона: префикс `+7` зашит (addonBefore), пользователь вводит только 10 цифр
- Валидация: `/^\d{10}$/` (9001234567)
- Отправка SMS кода: POST `/api/v1/sms/send`
- Проверка кода: POST `/api/v1/sms/verify`
- Формат отправки в API: `79001234567` (без `+`)
- DEV MODE кнопка: автоподтверждение и переход на шаг 2
**Файл:** `frontend/src/components/form/Step1Phone.tsx`
---
### 2. Обновлён ClaimForm.tsx - новый порядок шагов
**Было:**
```
[1. Полис] → [2. Тип] → [3+. Документы] → [N. Оплата]
```
**Стало:**
```
[1. Телефон SMS] → [2. Полис] → [3. Тип] → [4+. Документы] → [N. Оплата]
```
**Изменения:**
- Импорт `Step1Phone`
- Первый шаг: подтверждение телефона с `setIsPhoneVerified`
- Email перенесён с шага 1 на последний шаг (Step3Payment)
- Все функции навигации обёрнуты в `useCallback` для стабильности
**Файл:** `frontend/src/pages/ClaimForm.tsx`
---
### 3. Упрощён Step3Payment.tsx
**Изменения:**
- Убран блок верификации телефона (перенесён на шаг 1)
- Добавлено поле Email на последнем шаге
- Плашка "✅ Телефон подтверждён" показывается если `isPhoneVerified=true`
- Сохранены DEV MODE кнопки
**Файл:** `frontend/src/components/form/Step3Payment.tsx`
---
### 4. Создана операция CreateWebContact в vTiger CRM
**Назначение:** Упрощённое создание/поиск контакта по телефону
**Особенности:**
- **Обязательное поле:** только `mobile` (79001234567 без `+`)
- **Опционально:** `firstname`, `lastname`, `email`
- **Логика:**
- Если контакт существует → возвращает ID **БЕЗ обновления**
- Если не существует → создаёт с дефолтами (`Клиент ERV_XXXX`)
- **Возврат:** `{"contact_id": "396625", "is_new": false}`
- `is_new = true` → контакт создан сейчас
- `is_new = false` → контакт уже существовал
**URL:** `https://crm.clientright.ru/webservice.php?operation=CreateWebContact`
**Параметры:**
```
operation: CreateWebContact
sessionName: {token от login}
mobile: 79001234567
firstname: (опционально)
lastname: (опционально)
email: (опционально)
```
**Пример запроса:**
```bash
curl -X POST "https://crm.clientright.ru/webservice.php" \
-d "operation=CreateWebContact" \
-d "sessionName=xyz123" \
-d "mobile=79001234567"
```
**Пример ответа (существующий):**
```json
{
"success": true,
"result": "{\"contact_id\":\"396625\",\"is_new\":false}"
}
```
**Пример ответа (новый):**
```json
{
"success": true,
"result": "{\"contact_id\":\"396636\",\"is_new\":true}"
}
```
**Файлы:**
- `include/Webservices/CreateWebContact.php`
- Зарегистрировано в БД:
- `vtiger_ws_operation` (operationid: 50)
- `vtiger_ws_operation_parameters` (mobile, firstname, lastname, email)
- Логи: `logs/CreateWebContact.log`
---
### 5. Обновлён docker-compose.yml
**Изменения:**
- Убраны неиспользуемые локальные контейнеры `postgres` и `redis`
- Backend подключается к внешнему PostgreSQL (`147.45.189.234:5432`)
- Backend подключается к внешнему Redis (`crm.clientright.ru:6379`)
- Добавлены переменные окружения для n8n webhooks:
- `N8N_POLICY_CHECK_WEBHOOK`
- `N8N_FILE_UPLOAD_WEBHOOK`
- Убрана зависимость `depends_on: postgres`
- Остались только 2 контейнера: `frontend` и `backend`
**Файл:** `docker-compose.yml`
---
### 6. Обновлён n8n workflow: get_contact_CRM
**Webhook URL:** `https://n8n.clientright.pro/webhook/511fde97-88bb-4fb4-bea5-cafdc364be27`
**Флоу:**
```
1. Webhook (получает phone)
2. Edit Fields (извлекает phone из body)
3. Get Challenge (vTiger webservice)
4. Execute a command (md5 хеш для accessKey)
5. Edit Fields3 (форматирование)
6. Login to CRM (авторизация)
7. CreateWebContact (создание/поиск контакта)
8. Code in JavaScript (парсинг JSON + генерация claim_id)
9. Redis (сохранение session:claim:{claim_id})
10. Respond to Webhook (ответ фронтенду)
```
**Input:**
```json
{
"phone": "79001234567"
}
```
**Output:**
```json
{
"claim_id": "CLM-2025-10-30-IWR1U2",
"contact_id": "396625",
"is_new_contact": false,
"phone": "79001234567"
}
```
**Redis:**
```
Ключ: claim:CLM-2025-10-30-IWR1U2
TTL: 604800 секунд (7 дней)
Значение: JSON с полной информацией о сессии
```
---
## 🐛 Исправленные проблемы
### Проблема 1: Backend не запускается (Postgres конфликт версий)
**Симптом:**
```
FATAL: database files are incompatible with server
DETAIL: The data directory was initialized by PostgreSQL version 16,
which is not compatible with this version 15.14.
```
**Причина:** В docker-compose.yml был образ `postgres:15-alpine`, но volume содержал данные от v16
**Решение:**
1. Обновил образ до `postgres:16-alpine`
2. Потом понял что контейнер вообще не нужен — используется внешний PostgreSQL
3. Удалил сервис `postgres` из docker-compose.yml
---
### Проблема 2: Backend не подключается к Redis
**Симптом:**
```
Redis connection error ... connecting to localhost:6379
Error 111 Connection refused
```
**Причина:**
- В docker-compose.yml была переменная `REDIS_URL`, но backend её игнорировал
- Backend читал из .env файл с `REDIS_HOST=localhost`
- Локальный redis контейнер конфликтовал (порт 6379 занят внешним)
**Решение:**
- Удалил локальный контейнер `redis` из docker-compose.yml
- Прописал в environment:
```yaml
- REDIS_HOST=crm.clientright.ru
- REDIS_PORT=6379
- REDIS_PASSWORD=CRM_Redis_Pass_2025_Secure!
```
- Backend подключился к внешнему Redis
---
### Проблема 3: N8N webhooks не настроены
**Симптом:**
```
500 Internal Server Error
N8N webhook не настроен
```
**Причина:** Backend `n8n_proxy.py` читал переменные из .env, но docker контейнер не видел хостовый .env файл
**Решение:** Добавил в docker-compose.yml:
```yaml
environment:
- N8N_POLICY_CHECK_WEBHOOK=https://n8n.clientright.pro/webhook/9eb7bc5b...
- N8N_FILE_UPLOAD_WEBHOOK=https://n8n.clientright.pro/webhook/7e2abc64...
```
**Проверка:** `curl http://127.0.0.1:8100/api/n8n/policy/check` → 200 OK
---
### Проблема 4: Формат телефона с + (несовместимо с CRM)
**Симптом:** vTiger хранит телефон как `79001234567`, а фронт отправлял `+79001234567`
**Решение:**
- Step1Phone.tsx: `const phone = 7${values.phone}` (БЕЗ `+`)
- Валидация: 10 цифр, плейсхолдер `9001234567`
- В API отправляется `79001234567`
- Поле `vtiger_contactdetails.mobile` совместимо
---
### Проблема 5: CreateWebContact возвращает только ID
**Требование:** Нужен флаг `is_new` для UX (новый vs существующий клиент)
**Решение:**
- Добавил переменную `$isNew` в CreateWebContact.php
- Возврат: `json_encode(["contact_id" => "123", "is_new" => true/false])`
- N8N парсит: `JSON.parse($node["CreateWebContact"].json.result)`
- Сохраняется в Redis session
---
### Проблема 6: Gitea не запущена (порт 3002 недоступен)
**Симптом:**
```
fatal: unable to connect to 147.45.146.17:3002
Connection refused
```
**Причина:** Контейнер `gitea-erv` был остановлен
**Решение:**
```bash
docker start gitea-erv
```
Контейнер поднялся, порты проброшены: `3000->3002`, `22->2222`
---
### Проблема 7: n8n зависает при деактивации workflow (504 timeout)
**Симптом:** При попытке деактивировать workflow → 504 Gateway Timeout (второй раз за день)
**Временное решение:** Перезапуск n8n
**Постоянное решение (рекомендации):**
- Установить Execution Timeout: 300 секунд (Settings → Workflows)
- Включить Execution Data Prune (автоочистка старых executions)
- Проверить тип БД: использовать PostgreSQL вместо SQLite
- NODE_OPTIONS=--max-old-space-size=2048 для n8n процесса
---
## 📊 Метрики
**Время выполнения сессии:** ~13 часов (с перекурами)
**Количество коммитов:**
- erv_platform: 9 коммитов
- CRM: 2 коммита
**Созданных файлов:** 1
- `include/Webservices/CreateWebContact.php`
**Изменённых файлов:** 5
- `frontend/src/components/form/Step1Phone.tsx` (создан)
- `frontend/src/pages/ClaimForm.tsx` (новый порядок шагов)
- `frontend/src/components/form/Step3Payment.tsx` (email перенесён)
- `docker-compose.yml` (очистка от локальных сервисов)
- `webservice.php` (require CreateWebContact)
**Строк добавлено:** ~400
**Строк удалено:** ~120
**Frontend rebuilds:** 8
**Backend rebuilds:** 3
**Тестовых запросов:** 20+
---
## 🔧 Технические детали
### Архитектура после SMS верификации
```
Frontend: Step1Phone
│ Пользователь вводит: 9001234567
│ SMS код: 123456 ✅
├─ POST /api/v1/sms/verify
│ {phone: "79001234567", code: "123456"}
Backend: /api/v1/sms/verify
│ (пока заглушка, позже интеграция)
├─ Планируется: POST → n8n webhook
│ https://n8n.clientright.pro/webhook/511fde97...
n8n workflow: get_contact_CRM
├─1. Get Challenge
│ GET https://crm.clientright.ru/webservice.php?operation=getchallenge
│ → token: "abc123..."
├─2. Execute a command (SSH md5)
│ md5(token + "4r9ANex8PT2IuRV") → accessKey
├─3. Login to CRM
│ POST https://crm.clientright.ru/webservice.php
│ {operation: "login", username: "api", accessKey}
│ → sessionName: "xyz789..."
├─4. CreateWebContact
│ POST https://crm.clientright.ru/webservice.php
│ {operation: "CreateWebContact", sessionName, mobile: "79001234567"}
│ → {"contact_id": "396625", "is_new": false}
├─5. Code in JavaScript (парсинг + генерация claim_id)
│ const contactData = JSON.parse(result);
│ const claim_id = "CLM-2025-10-30-" + random(6);
│ return {
│ claim_id,
│ contact_id: contactData.contact_id,
│ is_new_contact: contactData.is_new,
│ phone,
│ redis_key: `claim:${claim_id}`,
│ redis_value: JSON.stringify({
│ claim_id, contact_id, phone, is_new_contact,
│ status: "draft", current_step: 1,
│ voucher: null, event_type: null, documents: {},
│ created_at, updated_at
│ }),
│ ttl: 604800
│ }
├─6. Redis (сохранение сессии)
│ SET claim:CLM-2025-10-30-IWR1U2 = {...}
│ EXPIRE 604800 // 7 дней
└─7. Respond to Webhook
→ {claim_id, contact_id, is_new_contact, phone}
```
---
### Структура данных в Redis
**Ключ:** `claim:CLM-2025-10-30-IWR1U2`
**TTL:** 604800 секунд (7 дней)
**Формат:** JSON string
```json
{
"claim_id": "CLM-2025-10-30-IWR1U2",
"contact_id": "396625",
"phone": "79001234567",
"is_new_contact": false,
"status": "draft",
"current_step": 1,
"created_at": "2025-10-30T16:55:15.384Z",
"updated_at": "2025-10-30T16:55:15.384Z",
// Заполняется по мере прохождения шагов
"voucher": null,
"event_type": null,
"documents": {},
"email": null,
"bank_name": null
}
```
---
### vTiger CRM - Таблица контактов
**Поиск по телефону:**
```sql
SELECT c.contactid
FROM vtiger_contactdetails c
LEFT JOIN vtiger_crmentity e ON e.crmid = c.contactid
WHERE e.deleted = 0 AND c.mobile = '79001234567'
LIMIT 1
```
**Формат телефона:** `79001234567` (БЕЗ `+`, 11 цифр)
---
## 📦 Git История
### erv_platform (main):
```bash
7b554c0 - feat: Полный флоу для создания контакта через CreateWebContact
6708092 - fix: Формат телефона БЕЗ + (79001234567 вместо +79001234567)
fe5cbdd - ui: Добавлена DEV MODE кнопка на шаг 1 (телефон)
cc880d3 - refactor: Убраны неиспользуемые локальные контейнеры Postgres и Redis
350ce0c - fix: N8N webhook URLs переданы в backend через environment
5437253 - fix: Backend подключается к внешнему Redis на crm.clientright.ru:6379
c9ed114 - fix: API вызовы через относительные пути (proxy)
3caf855 - ui: Убран email со шага 1, перенесён на последний шаг
58a12a3 - feat: Телефон перенесен на шаг 1 (SMS верификация)
```
### CRM (master):
```bash
d7941ac8 - feat: CreateWebContact возвращает is_new флаг
09c1fbd1 - feat: Добавлена операция CreateWebContact для vTiger webservice
```
---
## 🔗 Ссылки
- **Frontend:** http://147.45.146.17:5173
- **Backend API:** http://147.45.146.17:8100
- **CRM:** https://crm.clientright.ru
- **CRM Webservice:** https://crm.clientright.ru/webservice.php
- **n8n Production:** https://n8n.clientright.pro
- **n8n Webhook (contact):** https://n8n.clientright.pro/webhook/511fde97-88bb-4fb4-bea5-cafdc364be27
- **Gitea ERV:** http://147.45.146.17:3002/negodiy/erv-platform
---
## 📝 Важные заметки
### Redis Configuration
```
Host: crm.clientright.ru
Port: 6379
Password: CRM_Redis_Pass_2025_Secure!
Ключи: claim:{claim_id}
TTL: 604800 секунд (7 дней)
```
### vTiger CRM API User
```
Username: api
Access Key: 4r9ANex8PT2IuRV
Challenge timeout: 5 минут
Session timeout: стандартный vTiger
```
### Формат телефона
```
Input (пользователь): 9001234567 (10 цифр)
UI показывает: +7 | 9001234567
Отправка в API: 79001234567 (11 цифр без +)
CRM хранит: 79001234567
```
---
## 🎯 Следующие шаги (обсуждено)
### 1. После подтверждения полиса (шаг 2):
- Создать Project в vTiger CRM
- Привязать к контакту через `linktoaccountscontacts`
- Сохранить `project_id` в Redis session
### 2. После выбора типа события (шаг 3):
- Обновить Redis: добавить `event_type`
### 3. После загрузки документов (шаги 4+):
- Обновить Redis: добавить в `documents`
- OCR данные уже сохраняются через существующий workflow
### 4. Финальный submit:
- Создать HelpDesk заявку (Ticket) в CRM
- Привязать к Project и Contact
- Статус заявки: `draft` → `submitted`
### 5. Личный кабинет (этап 2):
- Вход по телефону + SMS
- Индекс в Redis: `user:{phone}:claims` = список claim_id
- Список незавершённых заявок
- Возможность продолжить или создать новую
---
## 📈 Тестовые данные
### Созданные контакты в CRM:
- **396625** - 79001234567 (Клиент ERV_4567) - существовал
- **396636** - 79194927999 (Клиент ERV_7999) - создан при тесте
- **350462** - 79111111111 (существовал)
### Сгенерированные claim_id:
- CLM-2025-10-30-IWR1U2
- CLM-2025-10-30-XWXCTS
- CLM-2025-10-30-Y0L1DI
### Redis сессии (проверено):
```bash
redis-cli -h crm.clientright.ru -a 'CRM_Redis_Pass_2025_Secure!' \
GET "claim:CLM-2025-10-30-IWR1U2"
→ {"claim_id": "...", "contact_id": "396625", "is_new_contact": false, ...}
```
---
## ✅ Итоговый результат
### Что работает:
1. ✅ Шаг 1: Ввод телефона (без +7) + SMS верификация
2. ✅ Backend поднят и работает (8100)
3. ✅ Postgres 16 поднят и доступен
4. ✅ Redis внешний подключён
5. ✅ N8N webhooks проксируются через backend
6. ✅ Операция CreateWebContact создана и протестирована
7. ✅ N8N workflow создаёт/находит контакт → генерирует claim_id → сохраняет в Redis
8. ✅ Флаг is_new_contact работает (новый vs существующий)
9. ✅ DEV MODE кнопки на всех шагах
10. ✅ Gitea поднята и работает
### Архитектура сессий:
```
Один claim_id = одна заявка = одна сессия в Redis
Ключ: claim:{claim_id}
TTL: 7 дней
```
### Следующий этап:
- Интегрировать `/api/v1/sms/verify` → n8n webhook
- Фронт получает `{claim_id, contact_id, is_new_contact}` и продолжает работу
- На шаге 2 (полис) → создаётся Project в CRM
---
**Статус:** ✅ Успешно завершено
**Автор:** AI Assistant (Claude Sonnet 4.5)
**Дата:** 30 октября 2025, 20:00 MSK