Files
aiform_dev/docs/N8N_USER_CREATION_INSTRUCTIONS.md
AI Assistant d6b17baa7d feat: Add PostgreSQL fields and workflow for form without files
Database changes:
- Add unified_id, contact_id, phone columns to clpr_claims table
- Create indexes for fast lookup by these fields
- Migrate existing data from payload to new columns
- SQL migration: docs/SQL_ALTER_CLPR_CLAIMS_ADD_FIELDS.sql

SQL improvements:
- Simplify claimsave query: remove complex claim_lookup logic
- Use UPSERT (INSERT ON CONFLICT) with known claim_id
- Always return claim (fix NULL issue)
- Store unified_id, contact_id, phone directly in table columns
- SQL: docs/SQL_CLAIMSAVE_UPSERT_SIMPLE.sql

Workflow enhancements:
- Add branch for form submissions WITHOUT files
- Create 6 new nodes: extract, prepare, save, redis, respond
- Separate flow for has_files=false in IF node
- Instructions: docs/N8N_FORM_GET_NO_FILES_INSTRUCTIONS.md
- Node config: docs/N8N_FORM_GET_NO_FILES_BRANCH.json

Migration stats:
- Total claims: 81
- With unified_id: 77
- Migrated from payload: 2

Next steps:
1. Add 6 nodes to n8n workflow form_get (ID: 8ZVMTsuH7Cmw7snw)
2. Connect TRUE branch of IF node to extract_webhook_data_no_files
3. Test form submission without files
4. Verify PostgreSQL save and Redis event
2025-11-21 15:57:18 +03:00

135 lines
3.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

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.

# Инструкция для n8n: Создание/поиск пользователя web_form
## Контекст
После создания контакта в CRM через `CreateWebContact`, нужно найти или создать пользователя в PostgreSQL и получить `unified_id` для связи с черновиками.
## Шаги в n8n workflow
### 1. После CreateWebContact
- Получен `contact_id` из CRM
- Есть `phone` из запроса
### 2. PostgreSQL Node: Find or Create User
**Настройки:**
- **Operation**: Execute Query
- **Query**: Использовать запрос из `SQL_FIND_OR_CREATE_USER_WEB_FORM.sql`
- **Parameters**:
- `$1` = `{{$json.phone}}` (или `{{$('CreateWebContact').item.json.phone}}`)
**Запрос:**
```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 = $1
LIMIT 1
),
create_user AS (
INSERT INTO clpr_users (unified_id, phone, created_at, updated_at)
SELECT
'usr_' || gen_random_uuid()::text,
$1,
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
),
update_unified AS (
UPDATE clpr_users
SET unified_id = COALESCE(
unified_id,
'usr_' || gen_random_uuid()::text
),
updated_at = now()
WHERE id = (SELECT user_id FROM final_user LIMIT 1)
AND unified_id IS NULL
RETURNING id AS user_id, unified_id
),
final_unified_id AS (
SELECT unified_id FROM update_unified
UNION ALL
SELECT unified_id FROM final_user
WHERE NOT EXISTS (SELECT 1 FROM update_unified)
LIMIT 1
),
create_account AS (
INSERT INTO clpr_user_accounts(user_id, channel, channel_user_id)
SELECT
(SELECT user_id FROM final_user LIMIT 1),
'web_form',
$1
ON CONFLICT (channel, channel_user_id) DO UPDATE
SET user_id = EXCLUDED.user_id
RETURNING user_id, channel, channel_user_id
)
SELECT
(SELECT unified_id FROM final_unified_id LIMIT 1) AS unified_id,
(SELECT user_id FROM final_user LIMIT 1) AS user_id;
```
**Результат:**
```json
{
"unified_id": "usr_b2fd7f73-c238-4fde-949b-c404cded12f3",
"user_id": 106
}
```
### 3. Сохранение unified_id в Redis
**Set Node (Redis)** или **Code Node**:
```javascript
const unified_id = $input.item.json.unified_id;
const claim_id = $('CreateWebContact').item.json.claim_id; // или откуда берете claim_id
// Сохранить в Redis
await redis.set(`claim:${claim_id}`, JSON.stringify({
...existing_data,
unified_id: unified_id
}));
```
### 4. Возврат unified_id в ответе frontend
**Response Node** или в **Code Node** перед возвратом:
```javascript
return {
success: true,
result: {
contact_id: $('CreateWebContact').item.json.contact_id,
claim_id: $('CreateWebContact').item.json.claim_id,
unified_id: $('PostgreSQL').item.json.unified_id, // ← ВАЖНО!
is_new_contact: $('CreateWebContact').item.json.is_new_contact
}
};
```
## Важно!
1. **unified_id должен быть в ответе** - frontend сохраняет его в `formData.unified_id`
2. **При создании/обновлении черновика** - заполнять `clpr_claims.unified_id = unified_id`
3. **Формат телефона**: `79991234567` (11 цифр, начинается с 7)
## Проверка работы
После выполнения запроса проверьте:
```sql
SELECT u.unified_id, u.phone, ua.channel, ua.channel_user_id
FROM clpr_users u
JOIN clpr_user_accounts ua ON u.id = ua.user_id
WHERE ua.channel = 'web_form'
AND ua.channel_user_id = '79991234567';
```
Должна быть запись с `unified_id` в формате `usr_...`.