- Добавлены unified_id и contact_id в TicketFormDescriptionRequest - Исправлен CODE_MERGE_PROJECT_TO_SESSION.js - теперь сохраняются ВСЕ данные из body.other - Добавлен fallback на получение other из Webhook напрямую - Генерация новой session_id при создании новой жалобы (сохраняя авторизацию) - Добавлен SQL_SELECT_CONTACT_WITH_CUSTOM_FIELDS.sql для CRM контактов - Создан SESSION_LOG_2025-11-25.md с документацией сессии
8.8 KiB
Анализ workflow 8ZVMTsuH7Cmw7snw и предложения
Текущая структура
Основные ноды PostgreSQL:
-
claimsave(строка 190-210)- Использует обновленный SQL с
$2::text(строка claim_id) - ПРОБЛЕМА: SQL запрос не использует
claim_finalCTE, который я добавил в исправленной версии - Это основная нода для сохранения данных визарда
- Использует обновленный SQL с
-
claimsave_final(строка 428-450)- Использует другой SQL запрос с
$2::uuid - Используется после конвертации файлов в PDF
- ПРОБЛЕМА: Ожидает UUID, но может получать строку
- Использует другой SQL запрос с
-
claimsave1(строка 634-655)- Использует старый SQL запрос с
$2::uuid - ПРОБЛЕМА: Не работает со строковым claim_id
- Использует старый SQL запрос с
Проблемы
1. SQL запрос в claimsave неполный
Текущий SQL в ноде claimsave:
- ✅ Использует
$2::text(правильно) - ✅ Имеет
claim_lookupиclaim_createdCTE - ❌ НЕ использует
claim_finalCTE (который я добавил в исправленной версии) - ❌ Использует
claim_lookup.claim_uuidнапрямую, что может не работать, если запись была создана вclaim_created
2. Несоответствие типов данных
claimsaveожидает строку ($2::text)claimsave_finalожидает UUID ($2::uuid)claimsave1ожидает UUID ($2::uuid)
Но везде передается claim_id как строка "CLM-2025-11-18-GEQ3KL".
3. Проблема с existing CTE
В текущем SQL запросе existing может не найти запись, если она была создана в claim_created, потому что:
claim_lookupвыполняется ДОclaim_createdexistingиспользуетclaim_lookup.claim_uuid, но запись может быть создана вclaim_created
Решения
Решение 1: Обновить SQL в ноде claimsave
Заменить SQL запрос на исправленную версию из FIXED_SQL_QUERY.md:
Ключевые изменения:
- Добавить
claim_finalCTE для получения правильного UUID - Использовать
claim_final.claim_uuidвместоclaim_lookup.claim_uuid - Исправить
oldCTE, чтобы он всегда возвращал строку
Решение 2: Унифицировать типы данных
Вариант A: Все ноды используют строку claim_id
- Изменить
claimsave_finalиclaimsave1на$2::text - Добавить логику поиска UUID по строке
claim_id
Вариант B: Все ноды используют UUID
- Перед SQL запросами добавить Code Node, который:
- Находит запись в
clpr_claimsпоpayload->>'claim_id' - Извлекает её
id(UUID) - Передает UUID в SQL запрос
- Находит запись в
Рекомендую Вариант A (использовать строку везде), т.к.:
- Проще реализовать
- Меньше изменений в workflow
claim_idв форматеCLM-YYYY-MM-DD-XXXXXX- это основной идентификатор
Решение 3: Упростить логику
Можно упростить SQL запрос, убрав сложную логику слияния:
WITH partial AS (
SELECT $1::jsonb AS p, $2::text AS claim_id_str
),
-- Находим или создаем запись
claim_final AS (
SELECT
COALESCE(
(SELECT id FROM clpr_claims WHERE payload->>'claim_id' = partial.claim_id_str LIMIT 1),
gen_random_uuid()
) AS claim_uuid
FROM partial
),
-- Создаем запись, если её нет
claim_created AS (
INSERT INTO clpr_claims (
id, session_token, channel, type_code, status_code, payload, created_at, updated_at, expires_at
)
SELECT
claim_final.claim_uuid,
COALESCE(partial.p->>'session_id', 'sess-' || gen_random_uuid()::text),
'web_form',
COALESCE(partial.p->>'type_code', 'consumer'),
'draft',
jsonb_build_object(
'claim_id', partial.claim_id_str,
'answers', COALESCE(partial.p->'answers', '{}'::jsonb),
'documents_meta', COALESCE(partial.p->'documents_meta', '[]'::jsonb),
'wizard_plan', partial.p->'wizard_plan',
'wizard_answers', partial.p->'wizard_answers',
'form_data', partial.p
),
now(), now(), now() + interval '14 days'
FROM partial, claim_final
WHERE NOT EXISTS (SELECT 1 FROM clpr_claims WHERE id = claim_final.claim_uuid)
ON CONFLICT (id) DO NOTHING
RETURNING id
),
-- Сохраняем документы
inserted_docs AS (
INSERT INTO clpr_claim_documents
(claim_id, field_name, file_id, uploaded_at, file_name, original_file_name)
SELECT
claim_final.claim_uuid::text,
doc.field_name, doc.file_id,
(doc.uploaded_at)::timestamptz,
doc.file_name, doc.original_file_name
FROM partial, claim_final
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)
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
),
-- Обновляем запись (простое слияние)
upd AS (
UPDATE clpr_claims c
SET
payload = COALESCE(c.payload, '{}'::jsonb) || partial.p,
status_code = CASE
WHEN (partial.p->'answers'->>'docs_exist' = 'true') THEN 'in_work'
ELSE COALESCE(c.status_code, 'draft')
END,
updated_at = now(),
expires_at = now() + interval '14 days'
FROM partial, claim_final
WHERE c.id = claim_final.claim_uuid
RETURNING c.id, c.status_code, c.payload
)
SELECT
(SELECT jsonb_build_object(
'claim_id', u.id::text,
'claim_id_str', (u.payload->>'claim_id'),
'status_code', u.status_code,
'payload', u.payload
) FROM upd u LIMIT 1) AS claim,
(SELECT jsonb_agg(jsonb_build_object(
'id', id,
'field_name', field_name,
'file_id', file_id
)) FROM inserted_docs) AS documents;
Рекомендации
Немедленные действия:
-
Обновить SQL в ноде
claimsave- Заменить на исправленную версию из
FIXED_SQL_QUERY.md - Или использовать упрощенную версию выше
- Заменить на исправленную версию из
-
Проверить параметры
- Убедиться, что
queryReplacementправильный:={{ $json.payload_partial_json }}, {{ $json.claim_id }} payload_partial_jsonдолжен быть JSON объектомclaim_idдолжен быть строкой
- Убедиться, что
-
Протестировать
- Запустить workflow с тестовыми данными
- Проверить, что
claimне возвращаетnull - Проверить, что документы сохраняются правильно
Долгосрочные улучшения:
-
Унифицировать все SQL запросы
- Привести
claimsave_finalиclaimsave1к единому формату - Использовать строковый
claim_idвезде
- Привести
-
Добавить обработку ошибок
- Проверять результат SQL запроса
- Логировать ошибки
- Возвращать понятные сообщения об ошибках
-
Оптимизировать workflow
- Упростить логику слияния payload
- Использовать транзакции для атомарности операций
Готовый SQL для копирования
Полный исправленный SQL запрос находится в файле FIXED_SQL_QUERY.md.
Основные изменения:
- ✅ Использует
claim_finalCTE для правильного получения UUID - ✅
oldCTE всегда возвращает строку (даже если запись не найдена) - ✅ Все подзапросы используют
LIMIT 1для гарантии одной строки - ✅ Правильное слияние
answersиdocuments_meta