Files
aiform_prod/docs/SQL_CLAIMSAVE_FINAL_FIXED.sql
AI Assistant a8de3f0fc9 fix: Add claim_lookup CTE to search by both ID and payload claim_id
Problem:
- Original query only searched by ID: WHERE c.id = partial.cid
- If record exists with different ID but same claim_id in payload,
  it wasn't found and documents weren't updated

Solution:
- Added claim_lookup CTE that searches both by ID and payload->>'claim_id':
  WHERE id::text = claim_id_str OR payload->>'claim_id' = claim_id_str
- Uses found ID from claim_lookup instead of partial.cid
- This ensures correct record is always used

Changes:
- partial now accepts $2::text (instead of $2::uuid)
- Added claim_lookup CTE for record lookup
- upd_claim uses claim_lookup.id instead of partial.cid
- docs uses claim_lookup.id instead of partial.cid

Files:
- docs/SQL_CLAIMSAVE_FINAL_FIXED.sql: Fixed version with claim_lookup
2025-11-24 17:02:29 +03:00

134 lines
5.0 KiB
SQL
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.

-- Исправленный SQL для сохранения документов (claimsave_final)
-- ✅ ИСПРАВЛЕНО: Ищем запись и по ID, и по payload->>'claim_id', чтобы избежать дубликатов
-- $1 = payload_partial_json (jsonb)
-- $2 = claim_id (text или uuid в виде строки)
WITH partial AS (
SELECT $1::jsonb AS p, $2::text AS claim_id_str
),
-- ✅ ИСПРАВЛЕНО: Ищем запись и по ID, и по payload->>'claim_id'
claim_lookup AS (
SELECT
id,
payload
FROM clpr_claims
WHERE id::text = partial.claim_id_str
OR payload->>'claim_id' = partial.claim_id_str
ORDER BY
CASE WHEN id::text = partial.claim_id_str THEN 1 ELSE 2 END,
updated_at DESC
LIMIT 1
),
docs AS (
SELECT
claim_lookup.id::text AS claim_id, -- uuid -> text для clpr_claim_documents
doc.field_name::text AS field_name,
doc.file_id::text AS file_id,
doc.file_name::text AS file_name,
doc.original_file_name::text AS original_file_name,
(doc.uploaded_at)::timestamptz AS uploaded_at,
doc.file_url::text AS file_url
FROM partial, claim_lookup
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, file_url text
)
),
upsert_docs AS (
INSERT INTO clpr_claim_documents
(claim_id, field_name, file_id, uploaded_at)
SELECT claim_id, field_name, file_id, uploaded_at
FROM docs
ON CONFLICT (claim_id, field_name) DO UPDATE
SET file_id = EXCLUDED.file_id,
uploaded_at = EXCLUDED.uploaded_at
RETURNING id, claim_id, field_name, file_id
),
-- ✅ ИСПРАВЛЕНО: Используем ID из claim_lookup вместо partial.cid
upd_claim AS (
UPDATE clpr_claims c
SET payload = jsonb_set(
COALESCE(c.payload, '{}'::jsonb),
'{documents_meta}',
COALESCE((SELECT p->'documents_meta' FROM partial), '[]'::jsonb),
true
),
updated_at = now(),
expires_at = now() + interval '14 days'
FROM partial, claim_lookup
WHERE c.id = claim_lookup.id
RETURNING c.id, c.payload
)
SELECT
(SELECT jsonb_build_object('claim_id', u.id, 'payload', u.payload) FROM upd_claim u) AS claim,
(
SELECT jsonb_agg(
jsonb_build_object(
'id', u.id,
'field_name', u.field_name,
'file_id', u.file_id,
'file_url', d.file_url,
'file_name', d.file_name,
'original_file_name', d.original_file_name,
'uploaded_at', d.uploaded_at,
-- имя, которое безопасно отдавать во внешний API
'filename_for_upload',
COALESCE(
NULLIF(d.original_file_name, ''),
NULLIF(d.file_name, ''),
regexp_replace(d.file_id, '^.*/', '') -- хвост пути как запасной
)
)
)
FROM upsert_docs u
JOIN docs d
ON d.claim_id = u.claim_id
AND d.field_name = u.field_name
WHERE d.file_url IS NOT NULL AND d.file_url <> '' -- не показываем без URL
) AS documents;
/*
============================================================================
ИСПРАВЛЕНИЯ (2025-11-24):
============================================================================
ПРОБЛЕМА: Запрос искал запись только по ID (WHERE c.id = partial.cid)
Если запись была создана с другим ID, но с тем же claim_id в payload,
она не находилась и не обновлялась.
РЕШЕНИЕ:
1. Добавлен CTE claim_lookup - ищет запись и по ID, и по payload->>'claim_id':
WHERE id::text = claim_id_str OR payload->>'claim_id' = claim_id_str
2. Используется найденный ID из claim_lookup вместо partial.cid
3. Это гарантирует, что всегда используется правильная запись
ИЗМЕНЕНИЯ:
- partial теперь принимает $2::text (вместо $2::uuid)
- Добавлен claim_lookup CTE для поиска записи
- upd_claim использует claim_lookup.id вместо partial.cid
- docs использует claim_lookup.id вместо partial.cid
============================================================================
ПРИМЕРЫ ИСПОЛЬЗОВАНИЯ:
============================================================================
1. С claim_id как UUID строкой:
$1 = '{"documents_meta": [...]}'::jsonb
$2 = '0eb051ec-23a6-4e06-8b98-f02d20d35f68'::text
2. С claim_id как UUID из payload:
$1 = '{"documents_meta": [...]}'::jsonb
$2 = '0eb051ec-23a6-4e06-8b98-f02d20d35f68'::text
(запрос найдет запись по payload->>'claim_id', если ID не совпадает)
============================================================================
*/