- Implement session management API (/api/v1/session/create, verify, logout) - Add session restoration from localStorage on page reload - Fix session_id priority when loading drafts (use current, not old from DB) - Add unified_id and claim_id to wizard payload sent to n8n - Add Docker volume for frontend HMR (Hot Module Replacement) - Add comprehensive session logging for debugging Components updated: - backend/app/api/session.py (NEW) - Session management endpoints - backend/app/main.py - Include session router - frontend/src/components/form/Step1Phone.tsx v2.0 - Create session after SMS - frontend/src/pages/ClaimForm.tsx v3.8 - Session restoration & priority fix - frontend/src/components/form/StepWizardPlan.tsx v1.4 - Add unified_id/claim_id - docker-compose.yml - Add frontend volume for live reload Session flow: 1. User verifies phone -> session created in Redis (24h TTL) 2. session_token saved to localStorage 3. Page reload -> session restored automatically 4. Draft selected -> current session_id used (not old from DB) 5. Wizard submit -> unified_id, claim_id, session_id sent to n8n 6. Logout -> session removed from Redis & localStorage Fixes: - Session token not persisting after page reload - unified_id missing in n8n webhook payload - Old session_id from draft overwriting current session - Frontend changes requiring container rebuild
115 lines
5.5 KiB
Markdown
115 lines
5.5 KiB
Markdown
# Лог сессии разработки - 20 ноября 2025
|
||
|
||
## Проблема (из предыдущей сессии)
|
||
После верификации телефона не отображался список черновиков, хотя в базе данных есть заявки с `unified_id`.
|
||
|
||
## Решение
|
||
|
||
### 1. Исправлен SQL запрос в backend (`claims.py`)
|
||
**Проблема:** Запрос строился через конкатенацию строк, что могло приводить к проблемам с параметрами.
|
||
|
||
**Решение:** Переписан SQL запрос - теперь используется прямой запрос для каждого случая:
|
||
- Для `unified_id`: прямой запрос `WHERE c.unified_id = $1`
|
||
- Для `phone`: подзапрос через `clpr_user_accounts` и `clpr_users`
|
||
- Для `session_id`: прямой запрос `WHERE c.session_token = $1`
|
||
|
||
```python
|
||
if unified_id:
|
||
query = """
|
||
SELECT
|
||
c.id,
|
||
c.payload->>'claim_id' as claim_id,
|
||
c.session_token,
|
||
c.status_code,
|
||
c.channel,
|
||
c.payload,
|
||
c.created_at,
|
||
c.updated_at
|
||
FROM clpr_claims c
|
||
WHERE c.unified_id = $1
|
||
ORDER BY c.updated_at DESC
|
||
LIMIT 20
|
||
"""
|
||
params = [unified_id]
|
||
```
|
||
|
||
### 2. Улучшена обработка черновиков в frontend (`ClaimForm.tsx`)
|
||
**Проблема:** Черновики из Telegram имеют другую структуру данных (данные в `payload.body`), а не напрямую в `payload`.
|
||
|
||
**Решение:** Добавлена поддержка обоих форматов:
|
||
- **Telegram формат:** данные в `payload.body.wizard_plan`, `payload.body.answers`
|
||
- **Web form формат:** данные напрямую в `payload.wizard_plan`, `payload.answers`
|
||
|
||
```typescript
|
||
// ✅ Для telegram черновиков данные могут быть в payload.body
|
||
const body = payload.body || {};
|
||
const isTelegramFormat = !!payload.body;
|
||
|
||
// ✅ Извлекаем данные из body (telegram) или напрямую из payload (web_form)
|
||
const wizardPlanRaw = body.wizard_plan || payload.wizard_plan;
|
||
const answersRaw = body.answers || payload.answers;
|
||
const problemDescription = body.problem_description || payload.problem_description || body.description || payload.description;
|
||
|
||
// ✅ Парсим wizard_plan и answers, если они строки (JSON)
|
||
let wizardPlan = wizardPlanRaw;
|
||
if (typeof wizardPlanRaw === 'string') {
|
||
try {
|
||
wizardPlan = JSON.parse(wizardPlanRaw);
|
||
} catch (e) {
|
||
console.warn('⚠️ Не удалось распарсить wizard_plan:', e);
|
||
}
|
||
}
|
||
```
|
||
|
||
### 3. Улучшена обработка `claim_id`
|
||
**Проблема:** `claim_id` может быть в разных местах в зависимости от формата данных.
|
||
|
||
**Решение:** Добавлен поиск `claim_id` в нескольких местах:
|
||
```typescript
|
||
const finalClaimId = claim.claim_id || payload.claim_id || body.claim_id || claim.id || formData.claim_id || claimId;
|
||
```
|
||
|
||
### 4. Добавлено детальное логирование
|
||
- В `loadDraft`: логирование всех этапов загрузки черновика
|
||
- В `get_draft` (backend): логирование найденных данных
|
||
- В `list_drafts` (backend): тестовые COUNT запросы для отладки
|
||
|
||
### 5. Исправлена обработка `claim_id` в backend
|
||
В `get_draft` теперь извлекается `claim_id` из `payload`, если его нет в `row`:
|
||
```python
|
||
claim_id_from_payload = payload.get('claim_id') if isinstance(payload, dict) else None
|
||
final_claim_id = row.get('claim_id') or claim_id_from_payload
|
||
```
|
||
|
||
## Результат
|
||
✅ **Черновики теперь возвращаются!** API корректно возвращает список черновиков для `unified_id`.
|
||
|
||
## Файлы изменены
|
||
|
||
1. `backend/app/api/claims.py`:
|
||
- Переписан SQL запрос для `list_drafts`
|
||
- Добавлено логирование и тестовые COUNT запросы
|
||
- Улучшена обработка `claim_id` в `get_draft`
|
||
|
||
2. `frontend/src/pages/ClaimForm.tsx`:
|
||
- Добавлена поддержка формата Telegram черновиков
|
||
- Улучшена обработка `claim_id` из разных источников
|
||
- Добавлено детальное логирование загрузки черновика
|
||
|
||
3. `frontend/src/components/form/Step1Phone.tsx`:
|
||
- (Возможно, были изменения для передачи unified_id)
|
||
|
||
4. `frontend/src/components/form/StepDraftSelection.tsx`:
|
||
- (Возможно, были изменения для отображения черновиков)
|
||
|
||
## Текущий статус
|
||
✅ **Работает:** API возвращает черновики
|
||
✅ **Работает:** Загрузка черновиков поддерживает оба формата (Telegram и web_form)
|
||
⚠️ **Требует проверки:** Отображение черновиков в UI (StepDraftSelection)
|
||
|
||
## Следующие шаги
|
||
1. Проверить отображение черновиков в UI
|
||
2. Протестировать загрузку черновика из Telegram формата
|
||
3. Убедиться, что все данные корректно восстанавливаются в форму
|
||
|