2025-11-19 18:46:48 +03:00
|
|
|
|
# Схема базы данных clpr_*
|
|
|
|
|
|
|
|
|
|
|
|
## Основные таблицы
|
|
|
|
|
|
|
|
|
|
|
|
### 1. `clpr_users` - Основная таблица пользователей
|
|
|
|
|
|
```
|
|
|
|
|
|
id (integer, PK)
|
|
|
|
|
|
universal_id (uuid)
|
|
|
|
|
|
unified_id (varchar) ← КЛЮЧЕВОЕ ПОЛЕ для связи
|
|
|
|
|
|
phone (varchar)
|
|
|
|
|
|
created_at, updated_at
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 2. `clpr_user_accounts` - Связь пользователей с каналами
|
|
|
|
|
|
```
|
|
|
|
|
|
id (integer, PK)
|
|
|
|
|
|
user_id (integer) → FK на clpr_users.id
|
|
|
|
|
|
channel (text) - 'telegram', 'web_form'
|
|
|
|
|
|
channel_user_id (text) - ID в канале (telegram_id для telegram, phone для web_form)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**Связь:**
|
|
|
|
|
|
- `clpr_user_accounts.user_id` → `clpr_users.id`
|
|
|
|
|
|
- Уникальность: `(channel, channel_user_id)` - один пользователь может быть в нескольких каналах
|
|
|
|
|
|
|
|
|
|
|
|
### 3. `clpr_claims` - Заявки/черновики
|
|
|
|
|
|
```
|
|
|
|
|
|
id (uuid, PK)
|
|
|
|
|
|
session_token (varchar)
|
|
|
|
|
|
unified_id (varchar) ← СВЯЗЬ С clpr_users.unified_id (должен заполняться n8n!)
|
|
|
|
|
|
telegram_id (bigint)
|
|
|
|
|
|
channel (text) - 'telegram', 'web_form'
|
|
|
|
|
|
user_id (integer) - возможно FK на clpr_users.id
|
|
|
|
|
|
type_code (text)
|
|
|
|
|
|
status_code (text) - 'draft', 'in_work', etc.
|
|
|
|
|
|
policy_number (text)
|
|
|
|
|
|
payload (jsonb) - содержит phone, claim_id, wizard_plan, answers, documents_meta и т.д.
|
|
|
|
|
|
is_confirmed (boolean)
|
|
|
|
|
|
created_at, updated_at, expires_at
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**Связь:**
|
|
|
|
|
|
- `clpr_claims.unified_id` → `clpr_users.unified_id` (логическая связь)
|
|
|
|
|
|
- `clpr_claims.user_id` → `clpr_users.id` (возможно, не всегда заполнено)
|
|
|
|
|
|
|
|
|
|
|
|
### 4. `clpr_users_tg` - Данные Telegram пользователей
|
|
|
|
|
|
```
|
|
|
|
|
|
telegram_id (bigint, PK)
|
|
|
|
|
|
unified_id (varchar) → clpr_users.unified_id
|
|
|
|
|
|
phone_number (varchar)
|
|
|
|
|
|
first_name_tg, last_name_tg, username, language_code, is_premium
|
|
|
|
|
|
first_name, last_name, middle_name, birth_date, etc.
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 5. `clpr_claim_documents` - Документы заявок
|
|
|
|
|
|
```
|
|
|
|
|
|
id (uuid, PK)
|
|
|
|
|
|
claim_id (varchar) → clpr_claims.id (логическая связь через payload->>'claim_id')
|
|
|
|
|
|
field_name (text)
|
|
|
|
|
|
file_id (text)
|
|
|
|
|
|
uploaded_at (timestamp)
|
|
|
|
|
|
file_name, original_file_name
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 6. `clpr_documents` - Хранилище документов
|
|
|
|
|
|
```
|
|
|
|
|
|
id (uuid, PK)
|
|
|
|
|
|
source (text)
|
|
|
|
|
|
content (text)
|
|
|
|
|
|
metadata (jsonb)
|
|
|
|
|
|
created_at
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## Логика работы с черновиками для web_form
|
|
|
|
|
|
|
|
|
|
|
|
### Шаг 1: Проверка пользователя в CRM
|
|
|
|
|
|
- n8n вызывает `CreateWebContact` с phone
|
|
|
|
|
|
- Получает `contact_id` из CRM
|
|
|
|
|
|
|
|
|
|
|
|
### Шаг 2: Поиск/создание пользователя в PostgreSQL
|
|
|
|
|
|
SQL запрос (аналогично Telegram):
|
|
|
|
|
|
```sql
|
|
|
|
|
|
WITH existing AS (
|
|
|
|
|
|
SELECT u.id AS user_id, u.unified_id
|
|
|
|
|
|
FROM clpr_user_accounts ua
|
|
|
|
|
|
JOIN clpr_users u ON u.id = ua.user_id
|
|
|
|
|
|
WHERE ua.channel = 'web_form'
|
|
|
|
|
|
AND ua.channel_user_id = '{phone}'
|
|
|
|
|
|
LIMIT 1
|
|
|
|
|
|
),
|
|
|
|
|
|
create_user AS (
|
|
|
|
|
|
INSERT INTO clpr_users (unified_id, phone, created_at, updated_at)
|
|
|
|
|
|
SELECT 'usr_' || gen_random_uuid()::text, '{phone}', now(), now()
|
|
|
|
|
|
WHERE NOT EXISTS (SELECT 1 FROM existing)
|
|
|
|
|
|
RETURNING id AS user_id, unified_id
|
|
|
|
|
|
),
|
|
|
|
|
|
final_user AS (
|
|
|
|
|
|
SELECT * FROM existing
|
|
|
|
|
|
UNION ALL
|
|
|
|
|
|
SELECT * FROM create_user
|
|
|
|
|
|
),
|
|
|
|
|
|
create_account AS (
|
|
|
|
|
|
INSERT INTO clpr_user_accounts(user_id, channel, channel_user_id)
|
|
|
|
|
|
SELECT
|
|
|
|
|
|
(SELECT user_id FROM final_user),
|
|
|
|
|
|
'web_form',
|
|
|
|
|
|
'{phone}'
|
|
|
|
|
|
ON CONFLICT (channel, channel_user_id) DO NOTHING
|
|
|
|
|
|
)
|
|
|
|
|
|
SELECT unified_id FROM final_user LIMIT 1;
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### Шаг 3: Создание/обновление заявки
|
|
|
|
|
|
- n8n создает/обновляет запись в `clpr_claims`
|
|
|
|
|
|
- **ВАЖНО:** заполняет `unified_id` из результата шага 2
|
|
|
|
|
|
- Сохраняет `phone` в `payload->>'phone'`
|
|
|
|
|
|
- `channel = 'web_form'`
|
|
|
|
|
|
- `status_code = 'draft'` для черновиков
|
|
|
|
|
|
|
|
|
|
|
|
### Шаг 4: Поиск черновиков
|
|
|
|
|
|
```sql
|
|
|
|
|
|
SELECT
|
|
|
|
|
|
c.id,
|
|
|
|
|
|
c.payload->>'claim_id' as claim_id,
|
|
|
|
|
|
c.session_token,
|
|
|
|
|
|
c.status_code,
|
|
|
|
|
|
c.payload,
|
|
|
|
|
|
c.created_at,
|
|
|
|
|
|
c.updated_at
|
|
|
|
|
|
FROM clpr_claims c
|
|
|
|
|
|
WHERE c.status_code = 'draft'
|
|
|
|
|
|
AND c.channel = 'web_form'
|
|
|
|
|
|
AND c.unified_id = '{unified_id}' -- ← ПОИСК ПО unified_id!
|
|
|
|
|
|
ORDER BY c.updated_at DESC
|
|
|
|
|
|
LIMIT 20;
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## Проблема в текущей реализации
|
|
|
|
|
|
|
|
|
|
|
|
**Текущее состояние:**
|
|
|
|
|
|
- В `clpr_claims` поле `unified_id` **ПУСТОЕ** для всех черновиков web_form
|
|
|
|
|
|
- Поиск идет по `payload->>'phone'` или `session_token`, что не надежно
|
|
|
|
|
|
|
|
|
|
|
|
**Решение:**
|
|
|
|
|
|
- n8n должен заполнять `unified_id` при создании/обновлении заявки
|
|
|
|
|
|
- Backend должен искать черновики по `unified_id`, а не по phone/session_id
|
|
|
|
|
|
|
|
|
|
|
|
## Связи между таблицами
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
clpr_users (unified_id)
|
|
|
|
|
|
↑
|
|
|
|
|
|
| (через unified_id)
|
|
|
|
|
|
|
|
|
|
|
|
|
clpr_claims (unified_id)
|
|
|
|
|
|
|
|
|
|
|
|
|
| (через user_id)
|
|
|
|
|
|
↓
|
|
|
|
|
|
clpr_user_accounts (user_id → clpr_users.id)
|
|
|
|
|
|
|
|
|
|
|
|
|
| (channel='web_form', channel_user_id=phone)
|
|
|
|
|
|
↓
|
|
|
|
|
|
clpr_claims (payload->>'phone')
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## Для Telegram (для сравнения)
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
clpr_users (unified_id)
|
|
|
|
|
|
↑
|
|
|
|
|
|
| (через unified_id)
|
|
|
|
|
|
|
|
|
|
|
|
|
clpr_users_tg (unified_id)
|
|
|
|
|
|
|
|
|
|
|
|
|
| (telegram_id)
|
|
|
|
|
|
↓
|
|
|
|
|
|
clpr_user_accounts (channel='telegram', channel_user_id=telegram_id)
|
|
|
|
|
|
|
|
|
|
|
|
|
| (user_id)
|
|
|
|
|
|
↓
|
|
|
|
|
|
clpr_users (id)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2025-11-21 15:57:18 +03:00
|
|
|
|
|
2025-11-24 13:36:14 +03:00
|
|
|
|
|