fix: Prevent duplicate claims by searching both by ID and payload claim_id

Problem:
- Multiple records created with same claim_id but different IDs
- Example: ID=0eb051ec... (correct) vs ID=b532b1b3... (duplicate)
- Different SQL queries used different approaches:
  * Some used claim_id as UUID for ID (partial.claim_id_str::uuid)
  * Others searched by payload->>'claim_id' and created new UUID if not found

Root Cause:
- SQL_CLAIMSAVE_UPSERT_SIMPLE.sql only searched by ID:
  WHERE id = claim_id_str::uuid
- If record existed with different ID but same claim_id in payload,
  it wasn't found and new record was created

Solution:
1. existing_claim now searches both by ID and payload->>'claim_id':
   WHERE id = claim_id_str::uuid OR payload->>'claim_id' = claim_id_str
   ORDER BY priority (ID match first), then updated_at DESC
2. INSERT uses ID from existing_claim if found:
   COALESCE((SELECT id FROM existing_claim), partial.claim_id_str::uuid)
3. This ensures same record is always used, preventing duplicates

Files:
- docs/SQL_CLAIMSAVE_UPSERT_SIMPLE.sql: Fixed search logic and INSERT ID
This commit is contained in:
AI Assistant
2025-11-24 16:52:58 +03:00
parent 894463742f
commit 81963d18c3

View File

@@ -15,12 +15,17 @@ WITH partial AS (
),
-- Получаем существующий payload из БД (если запись есть)
-- ✅ ИСПРАВЛЕНО: Ищем и по ID, и по payload->>'claim_id', чтобы избежать дубликатов
existing_claim AS (
SELECT
id,
payload
FROM clpr_claims
WHERE id = (SELECT claim_id_str::uuid FROM partial)
OR payload->>'claim_id' = (SELECT claim_id_str FROM partial)
ORDER BY
CASE WHEN id = (SELECT claim_id_str::uuid FROM partial) THEN 1 ELSE 2 END,
updated_at DESC
LIMIT 1
),
@@ -143,6 +148,7 @@ problem_description_parsed AS (
),
-- UPSERT claim
-- ✅ ИСПРАВЛЕНО: Используем ID из existing_claim, если он найден, чтобы избежать дубликатов
claim_upsert AS (
INSERT INTO clpr_claims (
id,
@@ -159,7 +165,10 @@ claim_upsert AS (
expires_at
)
SELECT
partial.claim_id_str::uuid,
COALESCE(
(SELECT id FROM existing_claim),
partial.claim_id_str::uuid
),
COALESCE(
partial.p->>'session_id',
partial.p->'edit_fields_parsed'->'body'->>'session_id',
@@ -202,7 +211,7 @@ claim_upsert AS (
'email', COALESCE(partial.p->>'email', (SELECT payload->>'email' FROM existing_claim))
),
COALESCE(
(SELECT created_at FROM clpr_claims WHERE id = partial.claim_id_str::uuid),
(SELECT created_at FROM existing_claim),
now()
),
now(),
@@ -289,6 +298,22 @@ SELECT
3. Это критично для workflow form_get, где wizard_plan создаётся на Step 2,
а файлы загружаются на Step 3 (без повторной отправки wizard_plan)
============================================================================
ИСПРАВЛЕНИЕ ДУБЛИКАТОВ (2025-11-24):
============================================================================
ПРОБЛЕМА: Создавались дубликаты записей с одинаковым claim_id, но разными ID
Причина: Разные SQL запросы использовали разные подходы:
- Одни использовали claim_id как UUID для ID (partial.claim_id_str::uuid)
- Другие искали по payload->>'claim_id' и создавали новый UUID, если не находили
РЕШЕНИЕ:
1. existing_claim теперь ищет и по ID, и по payload->>'claim_id':
WHERE id = claim_id_str::uuid OR payload->>'claim_id' = claim_id_str
2. INSERT использует ID из existing_claim, если он найден:
COALESCE((SELECT id FROM existing_claim), partial.claim_id_str::uuid)
3. Это гарантирует, что всегда используется одна и та же запись
============================================================================
ПРИМЕРЫ ИСПОЛЬЗОВАНИЯ:
============================================================================