# Схема базы данных 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) ```