fix: Исправление загрузки документов и SQL запросов

- Исправлена потеря документов при обновлении черновика (SQL объединяет вместо перезаписи)
- Исправлено определение типа документа (приоритет field_label над field_name)
- Исправлены дубликаты в documents_meta и documents_uploaded
- Добавлена передача group_index с фронтенда для правильного field_name
- Исправлены все документы в таблице clpr_claim_documents с правильными field_name
- Обновлены SQL запросы: claimsave и claimsave_final для нового флоу
- Добавлена поддержка multi-file upload для одного документа
- Исправлены дубликаты в списке загруженных документов на фронтенде

Файлы:
- SQL: SQL_CLAIMSAVE_FIXED_NEW_FLOW.sql, SQL_CLAIMSAVE_FINAL_FIXED_NEW_FLOW_WITH_UPLOADED.sql
- n8n: N8N_CODE_PROCESS_UPLOADED_FILES_FIXED.js (поддержка group_index)
- Backend: documents.py (передача group_index в n8n)
- Frontend: StepWizardPlan.tsx (передача group_index, исправление дубликатов)
- Скрипты: fix_claim_documents_field_names.py, fix_documents_meta_duplicates.py

Результат: документы больше не теряются, имеют правильные типы и field_name
This commit is contained in:
AI Assistant
2025-11-26 19:54:51 +03:00
parent 1d6c9d1f52
commit 02689e65db
42 changed files with 8314 additions and 232 deletions

View File

@@ -0,0 +1,130 @@
-- ============================================================================
-- Исправленный SQL для сохранения документов (claimsave_final) - ПОДДЕРЖКА НОВОГО ФЛОУ
-- ============================================================================
-- Проблема: SQL не сохранял documents_required и мог перезаписать статус
-- Решение: Сохраняем documents_required и не перезаписываем новые статусы
-- ============================================================================
WITH partial AS (
SELECT $1::jsonb AS p, $2::text AS claim_id_str
),
claim_lookup AS (
SELECT
c.id,
c.payload,
c.status_code
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,
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, file_name, original_file_name)
SELECT claim_id, field_name, file_id, uploaded_at, file_name, original_file_name
FROM docs
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
),
-- ✅ ИСПРАВЛЕНО: Сохраняем documents_required и обновляем статус правильно
upd_claim AS (
UPDATE clpr_claims c
SET
-- ✅ Объединяем payload: сохраняем documents_required и documents_meta
payload = jsonb_set(
jsonb_set(
COALESCE(c.payload, '{}'::jsonb),
'{documents_meta}',
COALESCE((SELECT p->'documents_meta' FROM partial), '[]'::jsonb),
true
),
'{documents_required}',
COALESCE(
(SELECT p->'documents_required' FROM partial WHERE partial.p->'documents_required' IS NOT NULL),
c.payload->'documents_required', -- Сохраняем существующий, если новый не пришёл
'[]'::jsonb
),
true
),
-- ✅ Обновляем статус только если нужно (не перезаписываем новые статусы)
status_code = CASE
-- Если статус уже новый - сохраняем его
WHEN c.status_code IN ('draft_new', 'draft_docs_progress', 'draft_docs_complete', 'draft_claim_ready')
THEN c.status_code
-- Если есть documents_required и документы загружены - обновляем статус
WHEN c.payload->'documents_required' IS NOT NULL
AND jsonb_array_length(COALESCE(c.payload->'documents_required', '[]'::jsonb)) > 0
AND (SELECT COUNT(*) FROM docs) > 0
THEN CASE
WHEN (SELECT COUNT(*) FROM docs) >= jsonb_array_length(COALESCE(c.payload->'documents_required', '[]'::jsonb))
THEN 'draft_docs_complete'
ELSE 'draft_docs_progress'
END
-- Иначе сохраняем существующий
ELSE c.status_code
END,
updated_at = now(),
expires_at = now() + interval '14 days'
FROM partial, claim_lookup
WHERE c.id = claim_lookup.id
RETURNING c.id, c.payload, c.status_code
)
SELECT
(SELECT jsonb_build_object(
'claim_id', u.id::text,
'status_code', u.status_code,
'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,
'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 <> ''
) AS documents;