Files
aiform_prod/docs/SQL_CLAIMSAVE_FINAL_FIXED.sql
AI Assistant d08e0da1ad fix: Add FROM partial to claim_lookup CTE to fix PostgreSQL error
Error:
- missing FROM-clause entry for table "partial"
- claim_lookup CTE used partial.claim_id_str but didn't have FROM partial

Root Cause:
- In CTE claim_lookup, we referenced partial.claim_id_str in WHERE clause
- But didn't include FROM partial, so PostgreSQL couldn't find the table

Solution:
- Added FROM partial to claim_lookup CTE:
  FROM clpr_claims c, partial
- Now partial is available in claim_lookup CTE
- Also prefixed columns with table aliases (c.id, c.payload) for clarity

Files:
- docs/SQL_CLAIMSAVE_FINAL_FIXED.sql: Added FROM partial to claim_lookup
2025-11-24 17:05:59 +03:00

134 lines
5.1 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
c.id,
c.payload
FROM clpr_claims c, partial
WHERE c.id::text = partial.claim_id_str
OR c.payload->>'claim_id' = partial.claim_id_str
ORDER BY
CASE WHEN c.id::text = partial.claim_id_str THEN 1 ELSE 2 END,
c.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 не совпадает)
============================================================================
*/