-- ============================================================================ -- SQL запрос для n8n: Сохранение первичного черновика заявки -- ============================================================================ -- Назначение: Сохранить первичный черновик сразу после генерации wizard_plan -- Использует session_token для связи (claim_id генерируется позже) -- -- Параметры: -- $1 = payload_json (jsonb) - полный payload с wizard_plan, problem_description, -- AI Agent1, AI Agent13 и т.д. -- $2 = session_token (text) - сессия пользователя -- $3 = unified_id (text, опционально) - unified_id пользователя -- -- Возвращает: -- claim - объект с claim_id (UUID), session_token, status_code, payload -- -- Использование в n8n: -- 1. PostgreSQL node -- 2. Query Type: Execute Query -- 3. Parameters: -- $1 = {{ JSON.stringify({...}) }} -- $2 = {{ $('Edit Fields11').first().json.session_token }} -- $3 = {{ $('Edit Fields10').first().json.unified_id || null }} -- ============================================================================ WITH partial AS ( SELECT $1::jsonb AS p, $2::text AS session_token_str, NULLIF($3::text, '') AS unified_id_str ), -- Находим существующую запись по session_token или создаем новую claim_lookup AS ( SELECT COALESCE( (SELECT id FROM clpr_claims WHERE session_token = partial.session_token_str LIMIT 1), gen_random_uuid() ) AS claim_uuid FROM partial ), -- Если записи нет, создаем её claim_created AS ( INSERT INTO clpr_claims ( id, session_token, unified_id, channel, type_code, status_code, payload, created_at, updated_at, expires_at ) SELECT claim_lookup.claim_uuid, partial.session_token_str, partial.unified_id_str, 'web_form', COALESCE(partial.p->>'type_code', 'consumer'), 'draft', jsonb_build_object( -- claim_id будет сгенерирован позже, пока NULL 'claim_id', NULL, 'problem_description', partial.p->>'problem_description', 'wizard_plan', CASE WHEN partial.p->>'wizard_plan' IS NOT NULL THEN (partial.p->>'wizard_plan')::jsonb WHEN partial.p->'wizard_plan' IS NOT NULL AND jsonb_typeof(partial.p->'wizard_plan') = 'object' THEN partial.p->'wizard_plan' ELSE NULL END, 'answers_prefill', CASE WHEN partial.p->>'answers_prefill' IS NOT NULL THEN (partial.p->>'answers_prefill')::jsonb WHEN partial.p->'answers_prefill' IS NOT NULL AND jsonb_typeof(partial.p->'answers_prefill') = 'array' THEN partial.p->'answers_prefill' ELSE '[]'::jsonb END, 'coverage_report', CASE WHEN partial.p->>'coverage_report' IS NOT NULL THEN (partial.p->>'coverage_report')::jsonb WHEN partial.p->'coverage_report' IS NOT NULL AND jsonb_typeof(partial.p->'coverage_report') = 'object' THEN partial.p->'coverage_report' ELSE NULL END, -- Данные из AI Agent1 (факты) 'ai_agent1_facts', CASE WHEN partial.p->'ai_agent1_facts' IS NOT NULL AND jsonb_typeof(partial.p->'ai_agent1_facts') = 'object' THEN partial.p->'ai_agent1_facts' ELSE NULL END, -- Данные из AI Agent13 (RAG ответ) 'ai_agent13_rag', CASE WHEN partial.p->>'ai_agent13_rag' IS NOT NULL THEN (partial.p->>'ai_agent13_rag')::jsonb WHEN partial.p->'ai_agent13_rag' IS NOT NULL AND jsonb_typeof(partial.p->'ai_agent13_rag') = 'object' THEN partial.p->'ai_agent13_rag' ELSE NULL END, 'phone', partial.p->>'phone', 'email', partial.p->>'email' ), now(), now(), now() + interval '14 days' FROM partial, claim_lookup WHERE NOT EXISTS ( SELECT 1 FROM clpr_claims WHERE id = claim_lookup.claim_uuid ) ON CONFLICT (id) DO NOTHING RETURNING id ), -- Получаем финальный UUID claim_final AS ( SELECT CASE WHEN EXISTS (SELECT 1 FROM claim_created) THEN (SELECT id FROM claim_created LIMIT 1) ELSE claim_lookup.claim_uuid END AS claim_uuid FROM claim_lookup ), -- Обновляем существующую запись (если есть) upd AS ( UPDATE clpr_claims c SET unified_id = COALESCE(partial.unified_id_str, c.unified_id), payload = jsonb_set( jsonb_set( jsonb_set( jsonb_set( jsonb_set( COALESCE(c.payload, '{}'::jsonb), '{wizard_plan}', COALESCE( CASE WHEN partial.p->>'wizard_plan' IS NOT NULL THEN (partial.p->>'wizard_plan')::jsonb WHEN partial.p->'wizard_plan' IS NOT NULL AND jsonb_typeof(partial.p->'wizard_plan') = 'object' THEN partial.p->'wizard_plan' ELSE NULL END, c.payload->'wizard_plan' ), true ), '{ai_agent1_facts}', COALESCE( CASE WHEN partial.p->'ai_agent1_facts' IS NOT NULL AND jsonb_typeof(partial.p->'ai_agent1_facts') = 'object' THEN partial.p->'ai_agent1_facts' ELSE NULL END, c.payload->'ai_agent1_facts' ), true ), '{ai_agent13_rag}', COALESCE( CASE WHEN partial.p->>'ai_agent13_rag' IS NOT NULL THEN (partial.p->>'ai_agent13_rag')::jsonb WHEN partial.p->'ai_agent13_rag' IS NOT NULL AND jsonb_typeof(partial.p->'ai_agent13_rag') = 'object' THEN partial.p->'ai_agent13_rag' ELSE NULL END, c.payload->'ai_agent13_rag' ), true ), '{problem_description}', COALESCE(partial.p->>'problem_description', c.payload->>'problem_description'), true ), '{answers_prefill}', COALESCE( CASE WHEN partial.p->>'answers_prefill' IS NOT NULL THEN (partial.p->>'answers_prefill')::jsonb WHEN partial.p->'answers_prefill' IS NOT NULL AND jsonb_typeof(partial.p->'answers_prefill') = 'array' THEN partial.p->'answers_prefill' ELSE '[]'::jsonb END, c.payload->'answers_prefill', '[]'::jsonb ), true ), updated_at = now(), expires_at = now() + interval '14 days' FROM partial, claim_final WHERE c.id = claim_final.claim_uuid AND EXISTS (SELECT 1 FROM claim_lookup WHERE claim_uuid = c.id) RETURNING c.id, c.payload ) SELECT (SELECT jsonb_build_object( 'claim_id', COALESCE(u.id::text, cf.claim_uuid::text), 'session_token', partial.session_token_str, 'status_code', 'draft', 'payload', COALESCE(u.payload, jsonb_build_object()) ) FROM claim_final cf, partial LEFT JOIN upd u ON true LIMIT 1) AS claim;