282 lines
10 KiB
Markdown
282 lines
10 KiB
Markdown
|
|
# Session Log 2025-12-01
|
|||
|
|
|
|||
|
|
## Сессия: UI/UX улучшения + CRM интеграция + Исправление дубликатов
|
|||
|
|
|
|||
|
|
### Участники
|
|||
|
|
- Пользователь: Фёдор
|
|||
|
|
- AI: Claude (Cursor)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 1. UI/UX Улучшения формы заявки
|
|||
|
|
|
|||
|
|
### 1.1 Изменение заголовков
|
|||
|
|
- **Главный заголовок формы**: "Подать заявку на выплату" → "Подать обращение о защите прав потребителя"
|
|||
|
|
- **Заголовок вкладки браузера**: "ERV Insurance Platform" → "Clientright — защита прав потребителей"
|
|||
|
|
|
|||
|
|
**Файлы:**
|
|||
|
|
- `ticket_form/frontend/src/pages/ClaimForm.tsx`
|
|||
|
|
- `ticket_form/frontend/index.html`
|
|||
|
|
- `ticket_form/frontend/public/index.html`
|
|||
|
|
|
|||
|
|
### 1.2 Улучшение отображения черновиков
|
|||
|
|
**Файлы:**
|
|||
|
|
- `ticket_form/frontend/src/components/form/StepDraftSelection.tsx`
|
|||
|
|
- `ticket_form/backend/app/api/claims.py`
|
|||
|
|
|
|||
|
|
**Изменения:**
|
|||
|
|
- Описание проблемы: увеличено до 250 символов, многострочное отображение
|
|||
|
|
- Добавлен заголовок проблемы (`problem_title` из `ai_analysis.problem`)
|
|||
|
|
- Добавлена категория (`category`) как фиолетовый тег
|
|||
|
|
- Прогресс-бар документов: `X / Y` с иконками статуса (✓ зелёный / ○ красный/серый)
|
|||
|
|
- Удалены избыточные теги "✓ Описание", "✓ План", "✓ Документы"
|
|||
|
|
- Убран дублирующий "++" из кнопки "Создать новую заявку"
|
|||
|
|
|
|||
|
|
### 1.3 Исправление навигации
|
|||
|
|
- Кнопка "Назад" теперь всегда возвращает к списку черновиков (Step 0)
|
|||
|
|
- Пропуск шагов "Проверка полиса" и "Тип события" для нового флоу (`documents_required` present)
|
|||
|
|
|
|||
|
|
**Файлы:**
|
|||
|
|
- `ticket_form/frontend/src/pages/ClaimForm.tsx`
|
|||
|
|
- `ticket_form/frontend/src/components/form/StepWizardPlan.tsx`
|
|||
|
|
|
|||
|
|
### 1.4 Переименование шагов
|
|||
|
|
```
|
|||
|
|
'Телефон' → 'Вход'
|
|||
|
|
'Описание' → 'Обращение'
|
|||
|
|
'Рекомендации' → 'Документы'
|
|||
|
|
'Оплата' → 'Заявление'
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 2. Backend улучшения
|
|||
|
|
|
|||
|
|
### 2.1 Исправление IP клиента
|
|||
|
|
**Проблема:** Отображался Docker IP `192.168.0.1`
|
|||
|
|
|
|||
|
|
**Решение:** Добавлена функция `_get_client_ip()` с проверкой заголовков:
|
|||
|
|
```python
|
|||
|
|
def _get_client_ip(request: Request) -> str:
|
|||
|
|
# 1. X-Forwarded-For
|
|||
|
|
# 2. X-Real-IP
|
|||
|
|
# 3. request.client.host (fallback)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Файл:** `ticket_form/backend/app/api/documents.py`
|
|||
|
|
|
|||
|
|
### 2.2 Расширение API списка черновиков
|
|||
|
|
**Добавлены поля:**
|
|||
|
|
- `problem_title` - заголовок проблемы
|
|||
|
|
- `category` - категория
|
|||
|
|
- `documents_total` - всего документов
|
|||
|
|
- `documents_uploaded` - загружено (уникальных типов)
|
|||
|
|
- `documents_skipped` - пропущено
|
|||
|
|
- `documents_required_list` - детальный список с статусами
|
|||
|
|
|
|||
|
|
**Файл:** `ticket_form/backend/app/api/claims.py`
|
|||
|
|
|
|||
|
|
### 2.3 SSE для OCR статуса
|
|||
|
|
Добавлено подключение SSE для получения статуса OCR обработки после загрузки документов.
|
|||
|
|
|
|||
|
|
**Файл:** `ticket_form/frontend/src/components/form/StepWizardPlan.tsx`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 3. CRM Webservices (PHP)
|
|||
|
|
|
|||
|
|
### 3.1 UpsertContact.php
|
|||
|
|
**Назначение:** Создание/обновление контакта с поддержкой `tgid`
|
|||
|
|
|
|||
|
|
**Приоритет поиска:**
|
|||
|
|
1. `contact_id` - если передан
|
|||
|
|
2. `mobile` - поиск по телефону
|
|||
|
|
3. `tgid` - поиск по Telegram ID
|
|||
|
|
|
|||
|
|
**Параметры:** `contact_json` (JSON строка)
|
|||
|
|
|
|||
|
|
**Регистрация в БД:**
|
|||
|
|
```sql
|
|||
|
|
INSERT INTO vtiger_ws_operation (operationid, name, handler_path, handler_method, type, prelogin)
|
|||
|
|
VALUES (57, 'UpsertContact', 'include/Webservices/UpsertContact.php', 'vtws_upsertcontact', 'POST', 0);
|
|||
|
|
|
|||
|
|
INSERT INTO vtiger_ws_operation_parameters (operationid, name, type, sequence)
|
|||
|
|
VALUES (57, 'contact_json', 'string', 1);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3.2 UpsertAccounts.php
|
|||
|
|
**Назначение:** Пакетное создание/поиск контрагентов (offenders) по ИНН
|
|||
|
|
|
|||
|
|
**Логика:**
|
|||
|
|
- Поиск по ИНН
|
|||
|
|
- Если найден - возвращает ID без обновления
|
|||
|
|
- Если не найден - создаёт новый
|
|||
|
|
|
|||
|
|
**Параметры:** `offenders_json` (JSON массив)
|
|||
|
|
|
|||
|
|
**Регистрация в БД:**
|
|||
|
|
```sql
|
|||
|
|
INSERT INTO vtiger_ws_operation (operationid, name, handler_path, handler_method, type, prelogin)
|
|||
|
|
VALUES (58, 'UpsertAccounts', 'include/Webservices/UpsertAccounts.php', 'vtws_upsertaccounts', 'POST', 0);
|
|||
|
|
|
|||
|
|
INSERT INTO vtiger_ws_operation_parameters (operationid, name, type, sequence)
|
|||
|
|
VALUES (58, 'offenders_json', 'string', 1);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3.3 UpsertProject.php
|
|||
|
|
**Назначение:** Создание/обновление проекта с маппингом ответчиков
|
|||
|
|
|
|||
|
|
**Параметры:** `project_json` (JSON объект содержит):
|
|||
|
|
- `project_id` - ID проекта для обновления
|
|||
|
|
- `claim_id` - ID заявки
|
|||
|
|
- `contact_id` - ID контакта
|
|||
|
|
- `result` - JSON строка с `offender_ids`
|
|||
|
|
- `projectdata` - данные проекта
|
|||
|
|
|
|||
|
|
**Маппинг ответчиков:**
|
|||
|
|
- Первый ответчик → `cf_2274` (основной)
|
|||
|
|
- Второй ответчик → `cf_2276` (агент)
|
|||
|
|
|
|||
|
|
**Регистрация в БД:**
|
|||
|
|
```sql
|
|||
|
|
INSERT INTO vtiger_ws_operation (operationid, name, handler_path, handler_method, type, prelogin)
|
|||
|
|
VALUES (59, 'UpsertProject', 'include/Webservices/UpsertProject.php', 'vtws_upsertproject', 'POST', 0);
|
|||
|
|
|
|||
|
|
INSERT INTO vtiger_ws_operation_parameters (operationid, name, type, sequence)
|
|||
|
|
VALUES (59, 'project_json', 'string', 1);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 4. Исправление дубликатов documents_meta
|
|||
|
|
|
|||
|
|
### 4.1 Проблема
|
|||
|
|
В `documents_meta` накапливались дубликаты при каждой загрузке документа.
|
|||
|
|
|
|||
|
|
**Причина:** SQL-запрос использовал простую конкатенацию `||` без дедупликации:
|
|||
|
|
```sql
|
|||
|
|
'{documents_meta}',
|
|||
|
|
COALESCE(...новые...) || COALESCE(...старые...)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 4.2 Найденные дубликаты
|
|||
|
|
| claim_id | Было записей | Уникальных |
|
|||
|
|
|----------|--------------|------------|
|
|||
|
|
| `bddb6815-8e17-4d54-a721-5e94382942c7` | 11 | 5 |
|
|||
|
|
| `226564ce-d7cf-48ee-a820-690e8f5ec8e5` | 3 | 2 |
|
|||
|
|
| `509872e2-9666-4c5e-8ab7-2304dd6a5d18` | 4 | 3 |
|
|||
|
|
| `ef853bac-f54b-46aa-adf8-f0c9c0cd76bc` | 4 | 3 |
|
|||
|
|
|
|||
|
|
### 4.3 SQL для исправления
|
|||
|
|
```sql
|
|||
|
|
-- Дедупликация по field_name (оставляем последний файл)
|
|||
|
|
UPDATE clpr_claims
|
|||
|
|
SET payload = jsonb_set(
|
|||
|
|
payload,
|
|||
|
|
'{documents_meta}',
|
|||
|
|
(
|
|||
|
|
SELECT COALESCE(
|
|||
|
|
jsonb_agg(doc ORDER BY (doc->>'uploaded_at') DESC NULLS LAST),
|
|||
|
|
'[]'::jsonb
|
|||
|
|
)
|
|||
|
|
FROM (
|
|||
|
|
SELECT DISTINCT ON (doc->>'field_name') doc
|
|||
|
|
FROM jsonb_array_elements(payload->'documents_meta') doc
|
|||
|
|
ORDER BY doc->>'field_name', (doc->>'uploaded_at') DESC NULLS LAST
|
|||
|
|
) unique_docs
|
|||
|
|
),
|
|||
|
|
true
|
|||
|
|
),
|
|||
|
|
updated_at = now()
|
|||
|
|
WHERE id IN (...);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 4.4 Исправленный SQL для загрузки документов
|
|||
|
|
Добавлен CTE `documents_meta_dedup`:
|
|||
|
|
```sql
|
|||
|
|
documents_meta_dedup AS (
|
|||
|
|
SELECT COALESCE(
|
|||
|
|
(
|
|||
|
|
SELECT jsonb_agg(doc ORDER BY (doc->>'uploaded_at') DESC NULLS LAST)
|
|||
|
|
FROM (
|
|||
|
|
SELECT DISTINCT ON (doc->>'field_name', doc->>'file_id') doc
|
|||
|
|
FROM (
|
|||
|
|
-- Новые записи (приоритет 1)
|
|||
|
|
SELECT jsonb_array_elements(...) AS doc, 1 AS priority
|
|||
|
|
UNION ALL
|
|||
|
|
-- Существующие записи (приоритет 2)
|
|||
|
|
SELECT jsonb_array_elements(...) AS doc, 2 AS priority
|
|||
|
|
) all_docs
|
|||
|
|
ORDER BY doc->>'field_name', doc->>'file_id', priority
|
|||
|
|
) unique_docs
|
|||
|
|
),
|
|||
|
|
'[]'::jsonb
|
|||
|
|
) AS documents_meta
|
|||
|
|
)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 5. n8n Workflows
|
|||
|
|
|
|||
|
|
### 5.1 Проблема с Redis каналами
|
|||
|
|
**Бэкенд публикует:** `clpr:check:ocr_status`
|
|||
|
|
|
|||
|
|
**n8n слушает:**
|
|||
|
|
- `fnSo3FTTbQcMjwt3` → `clpr:ocr:clime_file`
|
|||
|
|
- `1IKe2PccqXLkD2KR` → `clpr:ocr:jobs`
|
|||
|
|
|
|||
|
|
**Нужно:** Либо создать новый workflow для `clpr:check:ocr_status`, либо изменить канал в бэкенде.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 6. Файлы изменены
|
|||
|
|
|
|||
|
|
### Frontend
|
|||
|
|
- `ticket_form/frontend/index.html`
|
|||
|
|
- `ticket_form/frontend/public/index.html`
|
|||
|
|
- `ticket_form/frontend/src/pages/ClaimForm.tsx`
|
|||
|
|
- `ticket_form/frontend/src/components/form/StepDraftSelection.tsx`
|
|||
|
|
- `ticket_form/frontend/src/components/form/StepWizardPlan.tsx`
|
|||
|
|
- `ticket_form/frontend/src/components/form/generateConfirmationFormHTML.ts`
|
|||
|
|
|
|||
|
|
### Backend
|
|||
|
|
- `ticket_form/backend/app/api/claims.py`
|
|||
|
|
- `ticket_form/backend/app/api/documents.py`
|
|||
|
|
- `ticket_form/backend/app/api/events.py`
|
|||
|
|
|
|||
|
|
### CRM
|
|||
|
|
- `include/Webservices/UpsertContact.php` (NEW)
|
|||
|
|
- `include/Webservices/UpsertAccounts.php` (NEW)
|
|||
|
|
- `include/Webservices/UpsertProject.php` (NEW)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 7. Коммит
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
git commit -m "feat: UI/UX improvements + CRM integration methods + documents_meta deduplication"
|
|||
|
|
Commit: da82100b
|
|||
|
|
12 files changed, 1531 insertions(+), 145 deletions(-)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 8. Нерешённые задачи
|
|||
|
|
|
|||
|
|
1. **n8n workflow для `clpr:check:ocr_status`** - нужно либо создать новый, либо изменить канал
|
|||
|
|
2. **Обновить SQL в бэкенде** - заменить SQL загрузки документов на версию с дедупликацией
|
|||
|
|
3. **Обновить n8n ноды** для использования новых CRM методов:
|
|||
|
|
- `Create Contact` → `UpsertContact`
|
|||
|
|
- `Create Account` → `UpsertAccounts`
|
|||
|
|
- `Create Project` → `UpsertProject`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Метаданные сессии
|
|||
|
|
|
|||
|
|
- **Дата:** 2025-12-01
|
|||
|
|
- **Продолжительность:** ~2 часа
|
|||
|
|
- **Основной фокус:** UI/UX, CRM интеграция, исправление дубликатов
|
|||
|
|
|