2025-11-21 15:57:18 +03:00
|
|
|
|
-- Упрощённый UPSERT для сохранения claim с известным claim_id
|
|
|
|
|
|
-- Используется в n8n workflow: form_get (нода claimsave)
|
2025-11-21 16:04:55 +03:00
|
|
|
|
-- Дата: 2025-11-21 (обновлено: сохранение существующих полей)
|
2025-11-21 15:57:18 +03:00
|
|
|
|
-- Описание: Простой INSERT/UPDATE для claim, т.к. claim_id уже известен
|
2025-11-21 16:04:55 +03:00
|
|
|
|
-- ВАЖНО: Сохраняет wizard_plan и другие поля из БД, если не пришли новые
|
2025-11-21 15:57:18 +03:00
|
|
|
|
|
|
|
|
|
|
-- Входные параметры:
|
|
|
|
|
|
-- $1: payload_partial_json (jsonb) - данные формы с wizard_answers, wizard_plan, documents_meta
|
|
|
|
|
|
-- $2: claim_id (text) - UUID заявки
|
|
|
|
|
|
|
|
|
|
|
|
WITH partial AS (
|
|
|
|
|
|
SELECT
|
|
|
|
|
|
$1::jsonb AS p,
|
|
|
|
|
|
$2::text AS claim_id_str
|
|
|
|
|
|
),
|
|
|
|
|
|
|
2025-11-21 16:04:55 +03:00
|
|
|
|
-- Получаем существующий payload из БД (если запись есть)
|
|
|
|
|
|
existing_claim AS (
|
|
|
|
|
|
SELECT
|
|
|
|
|
|
id,
|
|
|
|
|
|
payload
|
|
|
|
|
|
FROM clpr_claims
|
|
|
|
|
|
WHERE id = (SELECT claim_id_str::uuid FROM partial)
|
|
|
|
|
|
LIMIT 1
|
|
|
|
|
|
),
|
|
|
|
|
|
|
2025-11-21 15:57:18 +03:00
|
|
|
|
-- Парсим wizard_answers
|
|
|
|
|
|
wizard_answers_parsed AS (
|
|
|
|
|
|
SELECT
|
|
|
|
|
|
CASE
|
2025-11-21 16:10:57 +03:00
|
|
|
|
-- Из edit_fields_raw.body.wizard_answers (строка)
|
|
|
|
|
|
WHEN partial.p->'edit_fields_raw'->'body'->>'wizard_answers' IS NOT NULL
|
|
|
|
|
|
THEN (partial.p->'edit_fields_raw'->'body'->>'wizard_answers')::jsonb
|
|
|
|
|
|
-- Из edit_fields_parsed.body.wizard_answers (строка)
|
|
|
|
|
|
WHEN partial.p->'edit_fields_parsed'->'body'->>'wizard_answers' IS NOT NULL
|
|
|
|
|
|
THEN (partial.p->'edit_fields_parsed'->'body'->>'wizard_answers')::jsonb
|
|
|
|
|
|
-- Из корня как строка
|
2025-11-21 15:57:18 +03:00
|
|
|
|
WHEN partial.p->>'wizard_answers' IS NOT NULL
|
|
|
|
|
|
THEN (partial.p->>'wizard_answers')::jsonb
|
2025-11-21 16:10:57 +03:00
|
|
|
|
-- Из корня как объект
|
2025-11-21 15:57:18 +03:00
|
|
|
|
WHEN partial.p->'wizard_answers' IS NOT NULL
|
|
|
|
|
|
AND jsonb_typeof(partial.p->'wizard_answers') = 'object'
|
|
|
|
|
|
THEN partial.p->'wizard_answers'
|
|
|
|
|
|
ELSE '{}'::jsonb
|
|
|
|
|
|
END AS answers
|
|
|
|
|
|
FROM partial
|
|
|
|
|
|
),
|
|
|
|
|
|
|
2025-11-21 16:04:55 +03:00
|
|
|
|
-- Парсим wizard_plan (или берём из существующей записи)
|
2025-11-21 15:57:18 +03:00
|
|
|
|
wizard_plan_parsed AS (
|
|
|
|
|
|
SELECT
|
|
|
|
|
|
CASE
|
2025-11-21 16:10:57 +03:00
|
|
|
|
-- Сначала пытаемся взять из edit_fields_parsed.wizard_plan_parsed (уже объект)
|
|
|
|
|
|
WHEN partial.p->'edit_fields_parsed'->'wizard_plan_parsed' IS NOT NULL
|
|
|
|
|
|
AND jsonb_typeof(partial.p->'edit_fields_parsed'->'wizard_plan_parsed') = 'object'
|
|
|
|
|
|
THEN partial.p->'edit_fields_parsed'->'wizard_plan_parsed'
|
|
|
|
|
|
-- Или из корня как строка
|
2025-11-21 15:57:18 +03:00
|
|
|
|
WHEN partial.p->>'wizard_plan' IS NOT NULL
|
|
|
|
|
|
THEN (partial.p->>'wizard_plan')::jsonb
|
2025-11-21 16:10:57 +03:00
|
|
|
|
-- Или из корня как объект
|
2025-11-21 15:57:18 +03:00
|
|
|
|
WHEN partial.p->'wizard_plan' IS NOT NULL
|
|
|
|
|
|
AND jsonb_typeof(partial.p->'wizard_plan') = 'object'
|
|
|
|
|
|
THEN partial.p->'wizard_plan'
|
2025-11-21 16:10:57 +03:00
|
|
|
|
-- Или из edit_fields_raw.body.wizard_plan (строка)
|
|
|
|
|
|
WHEN partial.p->'edit_fields_raw'->'body'->>'wizard_plan' IS NOT NULL
|
|
|
|
|
|
THEN (partial.p->'edit_fields_raw'->'body'->>'wizard_plan')::jsonb
|
2025-11-21 16:04:55 +03:00
|
|
|
|
-- Если нет в payload - берём из существующей записи в БД
|
|
|
|
|
|
WHEN EXISTS (SELECT 1 FROM existing_claim WHERE payload->'wizard_plan' IS NOT NULL)
|
|
|
|
|
|
THEN (SELECT payload->'wizard_plan' FROM existing_claim)
|
2025-11-21 15:57:18 +03:00
|
|
|
|
ELSE NULL
|
|
|
|
|
|
END AS wizard_plan
|
|
|
|
|
|
FROM partial
|
|
|
|
|
|
),
|
|
|
|
|
|
|
2025-11-21 16:04:55 +03:00
|
|
|
|
-- Парсим answers_prefill (или берём из БД)
|
|
|
|
|
|
answers_prefill_parsed AS (
|
|
|
|
|
|
SELECT
|
|
|
|
|
|
CASE
|
|
|
|
|
|
WHEN partial.p->'answers_prefill' IS NOT NULL
|
|
|
|
|
|
AND jsonb_typeof(partial.p->'answers_prefill') = 'array'
|
|
|
|
|
|
THEN partial.p->'answers_prefill'
|
|
|
|
|
|
WHEN EXISTS (SELECT 1 FROM existing_claim WHERE payload->'answers_prefill' IS NOT NULL)
|
|
|
|
|
|
THEN (SELECT payload->'answers_prefill' FROM existing_claim)
|
|
|
|
|
|
ELSE '[]'::jsonb
|
|
|
|
|
|
END AS answers_prefill
|
|
|
|
|
|
FROM partial
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
|
|
|
|
-- Парсим coverage_report (или берём из БД)
|
|
|
|
|
|
coverage_report_parsed AS (
|
|
|
|
|
|
SELECT
|
|
|
|
|
|
CASE
|
|
|
|
|
|
WHEN partial.p->'coverage_report' IS NOT NULL
|
|
|
|
|
|
AND jsonb_typeof(partial.p->'coverage_report') = 'object'
|
|
|
|
|
|
THEN partial.p->'coverage_report'
|
|
|
|
|
|
WHEN EXISTS (SELECT 1 FROM existing_claim WHERE payload->'coverage_report' IS NOT NULL)
|
|
|
|
|
|
THEN (SELECT payload->'coverage_report' FROM existing_claim)
|
|
|
|
|
|
ELSE NULL
|
|
|
|
|
|
END AS coverage_report
|
|
|
|
|
|
FROM partial
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
|
|
|
|
-- Парсим ai_agent1_facts (или берём из БД)
|
|
|
|
|
|
ai_agent1_facts_parsed AS (
|
|
|
|
|
|
SELECT
|
|
|
|
|
|
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'
|
|
|
|
|
|
WHEN EXISTS (SELECT 1 FROM existing_claim WHERE payload->'ai_agent1_facts' IS NOT NULL)
|
|
|
|
|
|
THEN (SELECT payload->'ai_agent1_facts' FROM existing_claim)
|
|
|
|
|
|
ELSE NULL
|
|
|
|
|
|
END AS ai_agent1_facts
|
|
|
|
|
|
FROM partial
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
|
|
|
|
-- Парсим ai_agent13_rag (или берём из БД)
|
|
|
|
|
|
ai_agent13_rag_parsed AS (
|
|
|
|
|
|
SELECT
|
|
|
|
|
|
CASE
|
|
|
|
|
|
WHEN partial.p->'ai_agent13_rag' IS NOT NULL
|
|
|
|
|
|
THEN partial.p->'ai_agent13_rag'
|
|
|
|
|
|
WHEN partial.p->>'ai_agent13_rag' IS NOT NULL
|
|
|
|
|
|
THEN to_jsonb(partial.p->>'ai_agent13_rag')
|
|
|
|
|
|
WHEN EXISTS (SELECT 1 FROM existing_claim WHERE payload->'ai_agent13_rag' IS NOT NULL)
|
|
|
|
|
|
THEN (SELECT payload->'ai_agent13_rag' FROM existing_claim)
|
|
|
|
|
|
ELSE NULL
|
|
|
|
|
|
END AS ai_agent13_rag
|
|
|
|
|
|
FROM partial
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
|
|
|
|
-- Парсим problem_description (или берём из БД)
|
|
|
|
|
|
problem_description_parsed AS (
|
|
|
|
|
|
SELECT
|
|
|
|
|
|
CASE
|
|
|
|
|
|
WHEN partial.p->>'problem_description' IS NOT NULL
|
|
|
|
|
|
THEN partial.p->>'problem_description'
|
|
|
|
|
|
WHEN EXISTS (SELECT 1 FROM existing_claim WHERE payload->>'problem_description' IS NOT NULL)
|
|
|
|
|
|
THEN (SELECT payload->>'problem_description' FROM existing_claim)
|
|
|
|
|
|
ELSE NULL
|
|
|
|
|
|
END AS problem_description
|
|
|
|
|
|
FROM partial
|
|
|
|
|
|
),
|
|
|
|
|
|
|
2025-11-21 15:57:18 +03:00
|
|
|
|
-- UPSERT claim
|
|
|
|
|
|
claim_upsert AS (
|
|
|
|
|
|
INSERT INTO clpr_claims (
|
|
|
|
|
|
id,
|
|
|
|
|
|
session_token,
|
|
|
|
|
|
unified_id,
|
|
|
|
|
|
contact_id,
|
|
|
|
|
|
phone,
|
|
|
|
|
|
channel,
|
|
|
|
|
|
type_code,
|
|
|
|
|
|
status_code,
|
|
|
|
|
|
payload,
|
|
|
|
|
|
created_at,
|
|
|
|
|
|
updated_at,
|
|
|
|
|
|
expires_at
|
|
|
|
|
|
)
|
|
|
|
|
|
SELECT
|
|
|
|
|
|
partial.claim_id_str::uuid,
|
2025-11-21 16:10:57 +03:00
|
|
|
|
COALESCE(
|
|
|
|
|
|
partial.p->>'session_id',
|
|
|
|
|
|
partial.p->'edit_fields_parsed'->'body'->>'session_id',
|
|
|
|
|
|
partial.p->'edit_fields_raw'->'body'->>'session_id',
|
|
|
|
|
|
'sess-unknown'
|
|
|
|
|
|
),
|
|
|
|
|
|
COALESCE(
|
|
|
|
|
|
partial.p->>'unified_id',
|
|
|
|
|
|
partial.p->'edit_fields_parsed'->'body'->>'unified_id',
|
|
|
|
|
|
partial.p->'edit_fields_raw'->'body'->>'unified_id'
|
|
|
|
|
|
),
|
|
|
|
|
|
COALESCE(
|
|
|
|
|
|
partial.p->>'contact_id',
|
|
|
|
|
|
partial.p->'edit_fields_parsed'->'body'->>'contact_id',
|
|
|
|
|
|
partial.p->'edit_fields_raw'->'body'->>'contact_id'
|
|
|
|
|
|
),
|
|
|
|
|
|
COALESCE(
|
|
|
|
|
|
partial.p->>'phone',
|
|
|
|
|
|
partial.p->'edit_fields_parsed'->'body'->>'phone',
|
|
|
|
|
|
partial.p->'edit_fields_raw'->'body'->>'phone'
|
|
|
|
|
|
),
|
2025-11-21 15:57:18 +03:00
|
|
|
|
'web_form',
|
|
|
|
|
|
COALESCE(partial.p->>'type_code', 'consumer'),
|
|
|
|
|
|
CASE
|
|
|
|
|
|
WHEN (SELECT answers->>'docs_exist' FROM wizard_answers_parsed) = 'true'
|
|
|
|
|
|
THEN 'in_work'
|
|
|
|
|
|
ELSE 'draft'
|
|
|
|
|
|
END,
|
|
|
|
|
|
jsonb_build_object(
|
|
|
|
|
|
'claim_id', partial.claim_id_str,
|
2025-11-21 16:04:55 +03:00
|
|
|
|
'problem_description', (SELECT problem_description FROM problem_description_parsed),
|
2025-11-21 15:57:18 +03:00
|
|
|
|
'answers', (SELECT answers FROM wizard_answers_parsed),
|
|
|
|
|
|
'documents_meta', COALESCE(partial.p->'documents_meta', '[]'::jsonb),
|
2025-11-21 16:04:55 +03:00
|
|
|
|
'wizard_plan', (SELECT wizard_plan FROM wizard_plan_parsed),
|
|
|
|
|
|
'answers_prefill', (SELECT answers_prefill FROM answers_prefill_parsed),
|
|
|
|
|
|
'coverage_report', (SELECT coverage_report FROM coverage_report_parsed),
|
|
|
|
|
|
'ai_agent1_facts', (SELECT ai_agent1_facts FROM ai_agent1_facts_parsed),
|
|
|
|
|
|
'ai_agent13_rag', (SELECT ai_agent13_rag FROM ai_agent13_rag_parsed),
|
|
|
|
|
|
'phone', COALESCE(partial.p->>'phone', (SELECT payload->>'phone' FROM existing_claim)),
|
|
|
|
|
|
'email', COALESCE(partial.p->>'email', (SELECT payload->>'email' FROM existing_claim))
|
2025-11-21 15:57:18 +03:00
|
|
|
|
),
|
|
|
|
|
|
COALESCE(
|
|
|
|
|
|
(SELECT created_at FROM clpr_claims WHERE id = partial.claim_id_str::uuid),
|
|
|
|
|
|
now()
|
|
|
|
|
|
),
|
|
|
|
|
|
now(),
|
|
|
|
|
|
now() + interval '14 days'
|
|
|
|
|
|
FROM partial
|
|
|
|
|
|
ON CONFLICT (id) DO UPDATE SET
|
|
|
|
|
|
session_token = EXCLUDED.session_token,
|
|
|
|
|
|
unified_id = COALESCE(EXCLUDED.unified_id, clpr_claims.unified_id),
|
|
|
|
|
|
contact_id = COALESCE(EXCLUDED.contact_id, clpr_claims.contact_id),
|
|
|
|
|
|
phone = COALESCE(EXCLUDED.phone, clpr_claims.phone),
|
|
|
|
|
|
status_code = EXCLUDED.status_code,
|
2025-11-21 16:04:55 +03:00
|
|
|
|
payload = EXCLUDED.payload,
|
2025-11-21 15:57:18 +03:00
|
|
|
|
updated_at = now(),
|
|
|
|
|
|
expires_at = now() + interval '14 days'
|
|
|
|
|
|
RETURNING id, status_code, payload, unified_id, contact_id, phone, session_token
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
|
|
|
|
-- UPSERT documents (если есть)
|
|
|
|
|
|
docs_upsert AS (
|
|
|
|
|
|
INSERT INTO clpr_claim_documents (
|
|
|
|
|
|
claim_id,
|
|
|
|
|
|
field_name,
|
|
|
|
|
|
file_id,
|
|
|
|
|
|
uploaded_at,
|
|
|
|
|
|
file_name,
|
|
|
|
|
|
original_file_name
|
|
|
|
|
|
)
|
|
|
|
|
|
SELECT
|
|
|
|
|
|
partial.claim_id_str AS claim_id,
|
|
|
|
|
|
doc.field_name,
|
|
|
|
|
|
doc.file_id,
|
|
|
|
|
|
COALESCE((doc.uploaded_at)::timestamptz, now()),
|
|
|
|
|
|
doc.file_name,
|
|
|
|
|
|
doc.original_file_name
|
|
|
|
|
|
FROM partial
|
|
|
|
|
|
CROSS JOIN LATERAL jsonb_to_recordset(
|
|
|
|
|
|
COALESCE(partial.p->'documents_meta', '[]'::jsonb)
|
|
|
|
|
|
) AS doc(
|
|
|
|
|
|
field_name text,
|
|
|
|
|
|
file_id text,
|
|
|
|
|
|
file_name text,
|
|
|
|
|
|
original_file_name text,
|
|
|
|
|
|
uploaded_at text
|
|
|
|
|
|
)
|
|
|
|
|
|
WHERE partial.p->'documents_meta' IS NOT NULL
|
|
|
|
|
|
AND jsonb_array_length(partial.p->'documents_meta') > 0
|
|
|
|
|
|
ON CONFLICT (claim_id, field_name) DO UPDATE SET
|
|
|
|
|
|
file_id = EXCLUDED.file_id,
|
|
|
|
|
|
uploaded_at = EXCLUDED.uploaded_at,
|
|
|
|
|
|
file_name = EXCLUDED.file_name,
|
|
|
|
|
|
original_file_name = EXCLUDED.original_file_name
|
|
|
|
|
|
RETURNING id, claim_id, field_name, file_id, file_name, original_file_name
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
-- Возвращаем результат
|
|
|
|
|
|
SELECT
|
|
|
|
|
|
(SELECT jsonb_build_object(
|
|
|
|
|
|
'claim_id', cu.id::text,
|
|
|
|
|
|
'claim_id_str', (cu.payload->>'claim_id'),
|
|
|
|
|
|
'status_code', cu.status_code,
|
|
|
|
|
|
'unified_id', cu.unified_id,
|
|
|
|
|
|
'contact_id', cu.contact_id,
|
|
|
|
|
|
'phone', cu.phone,
|
|
|
|
|
|
'session_token', cu.session_token,
|
|
|
|
|
|
'payload', cu.payload
|
|
|
|
|
|
) FROM claim_upsert cu) AS claim,
|
|
|
|
|
|
|
|
|
|
|
|
(SELECT jsonb_agg(jsonb_build_object(
|
|
|
|
|
|
'id', id,
|
|
|
|
|
|
'field_name', field_name,
|
|
|
|
|
|
'file_id', file_id,
|
|
|
|
|
|
'file_name', file_name,
|
|
|
|
|
|
'original_file_name', original_file_name
|
|
|
|
|
|
)) FROM docs_upsert) AS documents;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2025-11-21 16:04:55 +03:00
|
|
|
|
============================================================================
|
|
|
|
|
|
КЛЮЧЕВЫЕ ИЗМЕНЕНИЯ (2025-11-21):
|
|
|
|
|
|
============================================================================
|
|
|
|
|
|
|
|
|
|
|
|
1. Добавлена CTE "existing_claim" - читает существующий payload из БД
|
|
|
|
|
|
2. Все парсеры (wizard_plan, answers_prefill, coverage_report и т.д.)
|
|
|
|
|
|
теперь проверяют БД, если поле не пришло в payload_partial_json
|
|
|
|
|
|
3. Это критично для workflow form_get, где wizard_plan создаётся на Step 2,
|
|
|
|
|
|
а файлы загружаются на Step 3 (без повторной отправки wizard_plan)
|
|
|
|
|
|
|
|
|
|
|
|
============================================================================
|
2025-11-21 15:57:18 +03:00
|
|
|
|
ПРИМЕРЫ ИСПОЛЬЗОВАНИЯ:
|
2025-11-21 16:04:55 +03:00
|
|
|
|
============================================================================
|
2025-11-21 15:57:18 +03:00
|
|
|
|
|
2025-11-21 16:04:55 +03:00
|
|
|
|
1. Первое сохранение (после Step 2 - описание проблемы):
|
2025-11-21 15:57:18 +03:00
|
|
|
|
|
|
|
|
|
|
SELECT * FROM ... WHERE ... = (
|
|
|
|
|
|
'{
|
|
|
|
|
|
"session_id": "sess_xxx",
|
|
|
|
|
|
"unified_id": "usr_xxx",
|
|
|
|
|
|
"contact_id": "12345",
|
|
|
|
|
|
"phone": "79262306381",
|
2025-11-21 16:04:55 +03:00
|
|
|
|
"problem_description": "Не вернули деньги...",
|
|
|
|
|
|
"wizard_plan": {...полный wizard_plan...},
|
|
|
|
|
|
"ai_agent1_facts": {...},
|
|
|
|
|
|
"ai_agent13_rag": "...",
|
|
|
|
|
|
"answers_prefill": [...],
|
|
|
|
|
|
"coverage_report": {...}
|
|
|
|
|
|
}'::jsonb,
|
|
|
|
|
|
'uuid-here'::text
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
Результат: Создаётся claim с wizard_plan ✅
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
2. Обновление с файлами (Step 3 - загрузка документов):
|
|
|
|
|
|
|
|
|
|
|
|
SELECT * FROM ... WHERE ... = (
|
|
|
|
|
|
'{
|
|
|
|
|
|
"session_id": "sess_xxx",
|
|
|
|
|
|
"unified_id": "usr_xxx",
|
|
|
|
|
|
"wizard_answers": {"q1": "answer1"},
|
2025-11-21 15:57:18 +03:00
|
|
|
|
"documents_meta": [
|
|
|
|
|
|
{
|
|
|
|
|
|
"field_name": "uploads[0][0]",
|
|
|
|
|
|
"file_id": "clientright/0/file.pdf",
|
|
|
|
|
|
"file_name": "file.pdf",
|
|
|
|
|
|
"original_file_name": "original.pdf",
|
|
|
|
|
|
"uploaded_at": "2025-11-21T12:00:00Z"
|
|
|
|
|
|
}
|
|
|
|
|
|
]
|
|
|
|
|
|
}'::jsonb,
|
2025-11-21 16:04:55 +03:00
|
|
|
|
'СУЩЕСТВУЮЩИЙ-uuid'::text
|
2025-11-21 15:57:18 +03:00
|
|
|
|
);
|
|
|
|
|
|
|
2025-11-21 16:04:55 +03:00
|
|
|
|
Результат:
|
|
|
|
|
|
- Обновляется answers ✅
|
|
|
|
|
|
- Добавляются documents_meta ✅
|
|
|
|
|
|
- wizard_plan СОХРАНЯЕТСЯ из БД ✅ (не затирается!)
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
3. Сохранение БЕЗ файлов (только answers):
|
2025-11-21 15:57:18 +03:00
|
|
|
|
|
|
|
|
|
|
SELECT * FROM ... WHERE ... = (
|
|
|
|
|
|
'{
|
|
|
|
|
|
"session_id": "sess_xxx",
|
2025-11-21 16:04:55 +03:00
|
|
|
|
"wizard_answers": {"q1": "answer1"},
|
2025-11-21 15:57:18 +03:00
|
|
|
|
"documents_meta": []
|
|
|
|
|
|
}'::jsonb,
|
|
|
|
|
|
'uuid-here'::text
|
|
|
|
|
|
);
|
|
|
|
|
|
|
2025-11-21 16:04:55 +03:00
|
|
|
|
Результат:
|
|
|
|
|
|
- status_code = 'draft' (т.к. docs_exist != true)
|
|
|
|
|
|
- wizard_plan сохраняется из БД ✅
|
|
|
|
|
|
|
|
|
|
|
|
============================================================================
|
|
|
|
|
|
ОЖИДАЕМЫЙ РЕЗУЛЬТАТ:
|
|
|
|
|
|
============================================================================
|
|
|
|
|
|
|
2025-11-21 15:57:18 +03:00
|
|
|
|
{
|
|
|
|
|
|
"claim": {
|
|
|
|
|
|
"claim_id": "uuid",
|
|
|
|
|
|
"claim_id_str": "uuid",
|
|
|
|
|
|
"status_code": "draft" or "in_work",
|
|
|
|
|
|
"unified_id": "usr_xxx",
|
|
|
|
|
|
"contact_id": "12345",
|
|
|
|
|
|
"phone": "79262306381",
|
|
|
|
|
|
"session_token": "sess_xxx",
|
2025-11-21 16:04:55 +03:00
|
|
|
|
"payload": {
|
|
|
|
|
|
"claim_id": "uuid",
|
|
|
|
|
|
"problem_description": "...",
|
|
|
|
|
|
"answers": {...},
|
|
|
|
|
|
"documents_meta": [...],
|
|
|
|
|
|
"wizard_plan": {...}, // ← СОХРАНЯЕТСЯ из БД!
|
|
|
|
|
|
"answers_prefill": [...],
|
|
|
|
|
|
"coverage_report": {...},
|
|
|
|
|
|
"ai_agent1_facts": {...},
|
|
|
|
|
|
"ai_agent13_rag": "..."
|
2025-11-21 15:57:18 +03:00
|
|
|
|
}
|
2025-11-21 16:04:55 +03:00
|
|
|
|
},
|
|
|
|
|
|
"documents": [...]
|
2025-11-21 15:57:18 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-21 16:04:55 +03:00
|
|
|
|
============================================================================
|
|
|
|
|
|
TROUBLESHOOTING:
|
|
|
|
|
|
============================================================================
|
|
|
|
|
|
|
|
|
|
|
|
Проблема: wizard_plan всё равно NULL после загрузки файлов
|
|
|
|
|
|
Причина: В n8n workflow form_get не передаётся claim_id в payload
|
|
|
|
|
|
Решение: Убедиться, что в set_token1 извлекается claim_id из webhook:
|
|
|
|
|
|
"claim_id": "={{ $('Webhook').item.json.body.claim_id }}"
|
|
|
|
|
|
|
|
|
|
|
|
Проблема: Затираются ai_agent1_facts после Step 3
|
|
|
|
|
|
Причина: Не включены в payload при отправке
|
|
|
|
|
|
Решение: SQL сохраняет их из БД автоматически ✅
|
|
|
|
|
|
|
|
|
|
|
|
*/
|