Files
aiform_dev/SESSION_LOG_2025-11-01.md
AI Assistant 6b1979c93f docs: Лог сессии 01 ноября - CreateWebProject + SMS валидация + n8n интеграция
- Создана операция CreateWebProject для vTiger CRM
- Исправлена валидация SMS кодов (нормализация телефона)
- Добавлен вызов n8n webhook после SMS верификации
- Backend подключён к внешнему Redis
- Frontend пересобран с интеграцией CRM
- Протестировано: создание/поиск проектов, SMS коды, n8n workflow
- Все изменения задокументированы
2025-11-01 13:39:16 +03:00

724 lines
24 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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.

# 📋 Лог сессии: CreateWebProject + Интеграция SMS → CRM
**Дата:** 01 ноября 2025 (10:00 - 13:30 MSK)
**Задачи:**
1. Создание операции CreateWebProject для vTiger CRM
2. Исправление валидации SMS кодов
3. Интеграция n8n webhook для создания контакта после SMS верификации
**Статус:** ✅ Успешно завершено
---
## 🎯 Основные задачи
### Задача 1: CreateWebProject
Создать операцию vTiger webservice для создания проекта по аналогии с CreateWebContact.
**Требования:**
- Обязательные поля: `policy_number` (cf_1885), `contact_id`
- Опциональные: `period_start` (cf_1887), `period_end` (cf_1889)
- Логика: если проект с таким полисом существует → возврат ID без обновления
- Если не существует → создание нового
- Возврат: `{"project_id": "123", "is_new": true/false}`
### Задача 2: SMS валидация
Исправить проблему с валидацией SMS кодов (формат телефона).
### Задача 3: n8n интеграция
Добавить вызов n8n webhook после SMS верификации для создания контакта в CRM.
---
## ✅ Выполненные задачи
### 1. CreateWebProject.php - Операция vTiger Webservice
**Файл:** `include/Webservices/CreateWebProject.php`
**Обязательные параметры:**
- `policy_number` - номер полиса ERV (cf_1885)
- `contact_id` - ID контакта для привязки
**Опциональные параметры:**
- `period_start` - дата начала страхования (cf_1887)
- `period_end` - дата окончания страхования (cf_1889)
**Логика работы:**
```php
1. Ищем проект по номеру полиса (cf_1885):
SELECT p.projectid FROM vtiger_project p
INNER JOIN vtiger_projectcf pcf ON p.projectid = pcf.projectid
WHERE e.deleted = 0 AND pcf.cf_1885 = 'E1000-123456789'
2. Если найден возвращаем ID БЕЗ обновления:
{"project_id": "396865", "is_new": false}
3. Если НЕ найден создаём новый:
- projectname: "ERV E1000-123456789 цифровой адвокат"
- projectstatus: "модерация"
- projecttype: "ерв урегулирование"
- linktoaccountscontacts: "12x{contact_id}"
- cf_1994: "11x67458" (Заявитель - контрагент)
- cf_1885: номер полиса
{"project_id": "396866", "is_new": true}
```
**Регистрация в БД:**
```sql
-- vtiger_ws_operation
INSERT INTO vtiger_ws_operation (
operationid, name, handler_path, handler_method, type, prelogin
) VALUES (
51,
'CreateWebProject',
'include/Webservices/CreateWebProject.php',
'vtws_createwebproject',
'POST',
0
);
-- vtiger_ws_operation_parameters
INSERT INTO vtiger_ws_operation_parameters (operationid, name, type, sequence)
VALUES
(51, 'policy_number', 'String', 1),
(51, 'contact_id', 'String', 2),
(51, 'period_start', 'String', 3),
(51, 'period_end', 'String', 4);
```
**Тестирование:**
```bash
# Тест 1: Создание нового проекта
Policy: E1000-TEST-1761990646
Contact: 396625
Result: {"project_id":"396865","is_new":true}
# Тест 2: Повторный вызов (поиск существующего)
Policy: E1000-TEST-1761990646
Contact: 396625
Result: {"project_id":"396865","is_new":false}
```
**Логи:** `logs/CreateWebProject.log`
---
### 2. Исправление валидации SMS кодов
**Проблема:**
```
При отправке: ключ в Redis = erv:sms_verify:+79262306381 (С ПЛЮСОМ)
При проверке: поиск ключа = sms_verify:79262306381 (БЕЗ ПЛЮСА)
Результат: "No verification code found" ❌
```
**Причина:** Несоответствие формата телефона между отправкой и проверкой.
**Решение:**
**Файл:** `backend/app/services/sms_service.py`
```python
async def send_verification_code(self, phone: str) -> Optional[str]:
# Нормализуем формат телефона (убираем + если есть)
phone = phone.replace("+", "").replace("-", "").replace(" ", "")
verification_key = f"sms_verify:{phone}" # → sms_verify:79262306381
await redis_service.set(verification_key, code, expire=600)
...
async def verify_code(self, phone: str, code: str) -> bool:
# Нормализуем формат телефона (убираем + если есть)
phone = phone.replace("+", "").replace("-", "").replace(" ", "")
verification_key = f"sms_verify:{phone}" # → sms_verify:79262306381
stored_code = await redis_service.get(verification_key)
...
```
**Дополнительно:**
- Отключен rate limiting (60 сек задержка) для тестирования
- Добавлено детальное логирование сравнения кодов
- Backend подключён к внешнему Redis: `crm.clientright.ru:6379`
**Проверка:**
```bash
# До исправления
redis-cli> GET "erv:sms_verify:+79262306381" # Ключ с +
"123456"
# Проверка ищет без + → не находит ❌
# После исправления
redis-cli> GET "erv:sms_verify:79262306381" # Ключ без +
"123456"
# Проверка ищет без + → находит ✅
```
---
### 3. Интеграция n8n webhook после SMS верификации
**Проблема:** После SMS верификации контакт не создавался в CRM автоматически.
**Решение:**
**Файл:** `frontend/src/components/form/Step1Phone.tsx`
```typescript
// После успешной SMS верификации
if (response.ok) {
addDebugEvent?.('sms', 'success', `✅ Телефон подтвержден успешно`);
message.success('Телефон подтвержден!');
setIsPhoneVerified(true);
// 🆕 Вызов n8n webhook для создания контакта
try {
addDebugEvent?.('crm', 'info', '📞 Создание контакта в CRM...');
const crmResponse = await fetch(
'https://n8n.clientright.pro/webhook/511fde97-88bb-4fb4-bea5-cafdc364be27',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ phone }) // 79001234567
}
);
const crmResult = await crmResponse.json();
if (crmResponse.ok) {
addDebugEvent?.('crm', 'success', `✅ Контакт создан/найден в CRM`, crmResult);
// Сохраняем данные из CRM в форму
updateFormData({
phone,
contact_id: crmResult.contact_id,
claim_id: crmResult.claim_id,
is_new_contact: crmResult.is_new_contact
});
message.success(crmResult.is_new_contact ? 'Контакт создан!' : 'Контакт найден!');
onNext();
} else {
addDebugEvent?.('crm', 'error', '❌ Ошибка создания контакта в CRM');
message.error('Ошибка создания контакта в CRM');
}
} catch (crmError) {
addDebugEvent?.('crm', 'error', '❌ Ошибка соединения с CRM');
message.error('Ошибка соединения с CRM');
}
}
```
**Workflow n8n (get_contact_CRM):**
```
Webhook: https://n8n.clientright.pro/webhook/511fde97-88bb-4fb4-bea5-cafdc364be27
Input: {"phone": "79001234567"}
Флоу:
1. Edit Fields (извлечение phone)
2. Get Challenge (vTiger webservice)
3. Execute a command (md5 hash)
4. Login to CRM
5. CreateWebContact (создание/поиск контакта)
6. Code in JavaScript (парсинг JSON + генерация claim_id)
7. Redis (сохранение session:claim:{claim_id})
8. Respond to Webhook
Output: {
"claim_id": "CLM-2025-11-01-XXXXX",
"contact_id": "396625",
"is_new_contact": false,
"phone": "79001234567"
}
```
**Redis Session:**
```
Ключ: claim:CLM-2025-11-01-IWR1U2
TTL: 604800 секунд (7 дней)
Значение: {
"claim_id": "CLM-2025-11-01-IWR1U2",
"contact_id": "396625",
"phone": "79001234567",
"is_new_contact": false,
"status": "draft",
"current_step": 1,
"created_at": "2025-11-01T10:15:32.123Z",
"updated_at": "2025-11-01T10:15:32.123Z",
"voucher": null,
"event_type": null,
"documents": {}
}
```
---
### 4. Обновлён FormData интерфейс
**Файл:** `frontend/src/pages/ClaimForm.tsx`
```typescript
interface FormData {
// 🆕 Шаг 1: Phone
phone?: string;
contact_id?: string;
is_new_contact?: boolean;
// Шаг 2: Policy
voucher: string;
claim_id?: string;
session_id?: string;
// Шаг 3: Event Type
eventType?: string;
// Шаги 4+: Documents
documents?: Record<string, {...}>;
// Последний шаг: Payment
fullName?: string;
email?: string;
paymentMethod?: string;
bankName?: string;
cardNumber?: string;
accountNumber?: string;
}
```
---
### 5. Исправлён docker-compose.yml
**Проблемы:**
1. Backend пытался подключиться к локальному Redis (localhost:6379)
2. Попытка запуска локальных контейнеров redis/postgres, которые не нужны
**Решение:**
```yaml
backend:
build: ./backend
ports:
- "8100:8100"
environment:
# 🆕 Подключение к внешнему Redis
- REDIS_HOST=crm.clientright.ru
- REDIS_PORT=6379
- REDIS_PASSWORD=CRM_Redis_Pass_2025_Secure!
- POSTGRES_URL=postgresql://erv_user:erv_password@postgres:5432/erv_db
- RABBITMQ_URL=amqp://admin:tyejvtej@185.197.75.249:5672
# 🆕 Убраны зависимости от локальных сервисов
# depends_on:
# - redis
# - postgres
networks:
- erv-network
restart: unless-stopped
```
**Статус сервисов:**
- ✅ Backend подключён к внешнему Redis (crm.clientright.ru:6379)
- ✅ Backend подключён к внешнему PostgreSQL (147.45.189.234:5432)
- ✅ RabbitMQ подключён (185.197.75.249:5672)
- ✅ S3 подключён (Timeweb Cloud Storage)
---
## 🐛 Исправленные проблемы
### Проблема 1: UNKNOWN_OPERATION для CreateWebProject
**Симптом:**
```json
{"success":false,"error":{"code":"UNKNOWN_OPERATION","message":"Unknown operation requested"}}
```
**Причина:** Неправильная структура регистрации в БД.
**Было:**
```sql
INSERT INTO vtiger_ws_operation
VALUES (51, 'CreateWebProject', 'include/Webservices/CreateWebProject.php', ...)
-- Поле 'handler' вместо 'handler_path' и 'handler_method'
```
**Стало:**
```sql
INSERT INTO vtiger_ws_operation (
operationid, name, handler_path, handler_method, type, prelogin
) VALUES (
51,
'CreateWebProject',
'include/Webservices/CreateWebProject.php',
'vtws_createwebproject', -- ⭐ Имя функции!
'POST',
0
);
```
**Решение:** Используем правильные поля `handler_path` и `handler_method`.
---
### Проблема 2: BOM символ в CreateWebProject.php
**Симптом:**
```json
{"success":true,"result":...}
```
**Причина:** Файл сохранён с UTF-8 BOM.
**Решение:**
```bash
sed -i '1s/^\xEF\xBB\xBF//' include/Webservices/CreateWebProject.php
```
---
### Проблема 3: SMS код не валидируется
**Симптом:**
```
Отправка: +79262306381
Redis key: erv:sms_verify:+79262306381
Проверка: 79262306381
Redis key: sms_verify:79262306381
Результат: "No verification code found"
```
**Решение:** Нормализация телефона в обоих методах (убираем `+`, `-`, пробелы).
---
### Проблема 4: Backend не подключается к Redis
**Симптом:**
```
❌ Redis connection error: Error connecting to localhost:6379
```
**Причина:**
- `docker-compose.yml` имел `REDIS_URL=redis://redis:6379`
- Backend пытался подключиться к локальному Redis
- Локальный Redis конфликтовал с внешним на порту 6379
**Решение:**
```yaml
environment:
- REDIS_HOST=crm.clientright.ru
- REDIS_PORT=6379
- REDIS_PASSWORD=CRM_Redis_Pass_2025_Secure!
```
---
### Проблема 5: Step1Phone не отображается на первом шаге
**Симптом:** Поле телефона пропало с первой страницы.
**Причина:** Забыл добавить импорт и регистрацию в `steps` массиве.
**Решение:**
```typescript
// ClaimForm.tsx
import Step1Phone from '../components/form/Step1Phone';
const steps = useMemo(() => {
const stepsArray: any[] = [];
// 🆕 Шаг 1: Phone
stepsArray.push({
title: 'Телефон',
description: 'Подтверждение по SMS',
content: <Step1Phone ... />
});
// Шаг 2: Policy
stepsArray.push({
title: 'Проверка полиса',
...
});
...
}, [...]);
```
---
### Проблема 6: n8n webhook не вызывается
**Симптом:** После SMS верификации контакт не создаётся в CRM.
**Причина:**
1. Код добавлен на хосте, но не попал в Docker контейнер
2. Frontend не был пересобран
**Решение:**
```bash
cd erv_platform
docker-compose down frontend
docker-compose up -d --build frontend
```
**Проверка:**
```bash
docker exec -i erv_platform_frontend_1 sh -c \
"grep -n 'n8n.clientright.pro/webhook' /app/src/components/form/Step1Phone.tsx"
# Результат:
94: const crmResponse = await fetch('https://n8n.clientright.pro/webhook/511fde97-88bb-4fb4-bea5-cafdc364be27', {
```
---
## 📊 Итоговая архитектура
### Флоу создания заявки:
```
┌─────────────────────────────────────────────────────────────┐
│ Шаг 1: Телефон + SMS │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 1. Пользователь вводит телефон: 9001234567 │ │
│ │ 2. Frontend → POST /api/v1/sms/send │ │
│ │ 3. Backend генерирует код → Redis │ │
│ │ 4. Пользователь вводит код из SMS │ │
│ │ 5. Frontend → POST /api/v1/sms/verify │ │
│ │ 6. Backend проверяет код в Redis │ │
│ │ 7. ✅ Код верный → вызов n8n webhook │ │
│ │ 8. n8n → CreateWebContact (CRM) │ │
│ │ 9. n8n генерирует claim_id │ │
│ │ 10. n8n сохраняет сессию в Redis │ │
│ │ 11. n8n → Response: {contact_id, claim_id, is_new} │ │
│ │ 12. Frontend сохраняет данные в formData │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Шаг 2: Полис │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 1. Пользователь вводит номер полиса │ │
│ │ 2. Frontend → n8n webhook (проверка полиса) │ │
│ │ 3. n8n → CreateWebProject (CRM) │ │
│ │ 4. n8n обновляет Redis session │ │
│ │ 5. Response: {project_id, is_new, period_start/end} │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Шаг 3: Тип события → Шаги 4+: Документы → Последний: Оплата│
└─────────────────────────────────────────────────────────────┘
```
---
## 📁 Структура файлов
### CRM (vTiger):
```
include/Webservices/
├── CreateWebContact.php (operation_id: 50) ✅
├── CreateWebProject.php (operation_id: 51) 🆕
└── CreateERVTicket.php (будущее)
logs/
├── CreateWebContact.log
└── CreateWebProject.log 🆕
CREATE_WEB_PROJECT_DOCS.md 🆕
```
### ERV Platform:
```
backend/app/services/
└── sms_service.py 🔧 Исправлена нормализация телефона
frontend/src/components/form/
├── Step1Phone.tsx 🔧 Добавлен вызов n8n webhook
├── Step1Policy.tsx
├── Step2EventType.tsx
├── StepDocumentUpload.tsx
└── Step3Payment.tsx
frontend/src/pages/
└── ClaimForm.tsx 🔧 Добавлен Step1Phone на первый шаг
docker-compose.yml 🔧 Redis подключён к внешнему серверу
```
---
## 🧪 Тестирование
### CreateWebProject:
**Тест 1: Создание нового проекта**
```bash
curl -X POST "https://crm.clientright.ru/webservice.php" \
-d "operation=CreateWebProject" \
-d "sessionName=xyz123" \
-d "policy_number=E1000-TEST-1761990646" \
-d "contact_id=396625" \
-d "period_start=01-01-2025" \
-d "period_end=31-12-2025"
Response: {"success":true,"result":"{\"project_id\":\"396865\",\"is_new\":true}"}
✅ Проект создан
```
**Тест 2: Повторный вызов (поиск существующего)**
```bash
curl -X POST "https://crm.clientright.ru/webservice.php" \
-d "operation=CreateWebProject" \
-d "sessionName=xyz123" \
-d "policy_number=E1000-TEST-1761990646" \
-d "contact_id=396625"
Response: {"success":true,"result":"{\"project_id\":\"396865\",\"is_new\":false}"}
✅ Проект найден (дубликат НЕ создан!)
```
### SMS Validation:
**До исправления:**
```
Отправка кода → ключ: erv:sms_verify:+79262306381
Проверка кода → ключ: sms_verify:79262306381
Результат: ❌ "No verification code found"
```
**После исправления:**
```
Отправка кода → ключ: erv:sms_verify:79262306381
Проверка кода → ключ: sms_verify:79262306381
Результат: ✅ "Code verified"
```
### n8n Integration:
**Frontend → n8n webhook:**
```
POST https://n8n.clientright.pro/webhook/511fde97-88bb-4fb4-bea5-cafdc364be27
Body: {"phone": "79001234567"}
Response: {
"claim_id": "CLM-2025-11-01-IWR1U2",
"contact_id": "396625",
"is_new_contact": false,
"phone": "79001234567"
}
```
**Redis Session (проверка):**
```bash
redis-cli -h crm.clientright.ru -a 'CRM_Redis_Pass_2025_Secure!' \
GET "claim:CLM-2025-11-01-IWR1U2"
{
"claim_id": "CLM-2025-11-01-IWR1U2",
"contact_id": "396625",
"phone": "79001234567",
"is_new_contact": false,
"status": "draft",
...
}
```
---
## 📝 Git История
### erv_platform (main):
```
89a182b - fix: Интеграция n8n webhook для создания контакта после SMS
8c21450 - docs: Лог сессии 30 октября - Телефон на шаг 1 + интеграция CRM
7b554c0 - feat: Полный флоу для создания контакта через CreateWebContact
```
### CRM (master):
```
f720c14e - chore: Обновлён submodule erv_platform
c34f7c9b - docs: Документация для CreateWebProject
af802149 - feat: Добавлена операция CreateWebProject для vTiger webservice
d7941ac8 - feat: CreateWebContact возвращает is_new флаг
09c1fbd1 - feat: Добавлена операция CreateWebContact для vTiger webservice
```
---
## 🔗 Важные URL
**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
---
## 🎯 Следующие шаги
1. **Тестирование полного флоу:**
- Телефон → SMS → CRM контакт → Полис → CRM проект → Документы → Тикет
2. **Доработка Step1Policy:**
- Вызов n8n webhook для проверки полиса
- Создание проекта через CreateWebProject
- Обновление Redis session
3. **Создание операции CreateERVTicket:**
- Финальный шаг создания тикета в HelpDesk
- Привязка к проекту и контакту
4. **Личный кабинет:**
- Вход по телефону + SMS
- Список незавершённых заявок
- Возможность продолжить заявку
---
## 📊 Метрики
**Время выполнения сессии:** ~3.5 часа
**Количество коммитов:**
- erv_platform: 3 коммита
- CRM: 3 коммита
**Созданных файлов:** 2
- `include/Webservices/CreateWebProject.php`
- `CREATE_WEB_PROJECT_DOCS.md`
**Изменённых файлов:** 4
- `backend/app/services/sms_service.py`
- `frontend/src/components/form/Step1Phone.tsx`
- `frontend/src/pages/ClaimForm.tsx`
- `docker-compose.yml`
**Строк добавлено:** ~350
**Строк удалено:** ~30
**Frontend rebuilds:** 4
**Backend rebuilds:** 3
**Тестовых запросов:** 15+
---
**Статус:** ✅ Успешно завершено
**Автор:** AI Assistant (Claude Sonnet 4.5)
**Дата:** 01 ноября 2025, 13:30 MSK