feat: Получение cf_2624 из MySQL и блокировка полей при подтверждении данных

- Добавлен сервис CrmMySQLService для прямого подключения к MySQL CRM
- Обновлён метод get_draft() для получения cf_2624 напрямую из БД
- Реализована блокировка полей (readonly) при contact_data_confirmed = true
- Добавлен выбор банка для СБП выплат с динамической загрузкой из API
- Обновлена документация по работе с cf_2624 и MySQL
- Добавлен network_mode: host в docker-compose для доступа к MySQL
- Обновлены компоненты формы для поддержки блокировки полей
This commit is contained in:
AI Assistant
2025-12-04 12:22:23 +03:00
parent 64385c430d
commit 080e7ec105
69 changed files with 17034 additions and 1439 deletions

View File

@@ -0,0 +1,91 @@
-- ============================================================================
-- SQL запрос для обновления upload_description документа по claim_document_id
-- ============================================================================
-- Параметры:
-- $1 :: uuid -- claim_document_id (ID документа из таблицы clpr_claim_documents)
-- $2 :: text -- upload_description (новое описание документа)
-- ============================================================================
WITH
-- Находим документ и извлекаем нужные данные
doc_info AS (
SELECT
cd.id AS claim_document_id,
cd.claim_id::text AS claim_id_text,
cd.field_name,
-- Извлекаем индекс i из field_name (например, uploads[0][0] -> 0)
NULLIF((regexp_match(cd.field_name, 'uploads\[(\d+)\]'))[1], '')::int AS upload_index,
c.id AS claim_uuid,
c.payload
FROM clpr_claim_documents cd
JOIN clpr_claims c ON c.id::text = cd.claim_id::text
WHERE cd.id = $1
LIMIT 1
),
-- Обновляем payload: приоритет обновления в следующем порядке:
-- 1. payload.body['uploads_descriptions[i]'] (самый приоритетный)
-- 2. payload['uploads_descriptions[i]'] (если нет body)
-- 3. payload.edit_fields_parsed.uploads_descriptions[i] (массив, если нет плоских ключей)
updated_claim AS (
UPDATE clpr_claims c
SET
payload = CASE
-- Если есть payload.body, обновляем там
WHEN c.payload->'body' IS NOT NULL THEN
jsonb_set(
c.payload,
ARRAY['body', 'uploads_descriptions[' || di.upload_index::text || ']'],
to_jsonb($2::text),
true
)
-- Если нет body, но есть корневой ключ, обновляем там
WHEN c.payload ? ('uploads_descriptions[' || di.upload_index::text || ']') THEN
jsonb_set(
c.payload,
ARRAY['uploads_descriptions[' || di.upload_index::text || ']'],
to_jsonb($2::text),
true
)
-- Если есть edit_fields_parsed.uploads_descriptions (массив), обновляем там
WHEN c.payload->'edit_fields_parsed'->'uploads_descriptions' IS NOT NULL
AND jsonb_typeof(c.payload->'edit_fields_parsed'->'uploads_descriptions') = 'array' THEN
-- Для массива используем jsonb_set с числовым индексом
jsonb_set(
c.payload,
ARRAY['edit_fields_parsed', 'uploads_descriptions', di.upload_index::text],
to_jsonb($2::text),
true
)
-- Если ничего нет, создаём в body
ELSE
jsonb_set(
COALESCE(c.payload, '{}'::jsonb),
ARRAY['body', 'uploads_descriptions[' || di.upload_index::text || ']'],
to_jsonb($2::text),
true
)
END,
updated_at = now()
FROM doc_info di
WHERE c.id = di.claim_uuid
RETURNING c.id, c.payload
)
-- Возвращаем обновлённые данные
SELECT
di.claim_document_id,
di.claim_id_text AS claim_id,
di.field_name,
di.upload_index,
-- Проверяем, где сохранилось описание
COALESCE(
uc.payload->'body'->>('uploads_descriptions[' || di.upload_index::text || ']'),
uc.payload->>('uploads_descriptions[' || di.upload_index::text || ']'),
uc.payload->'edit_fields_parsed'->'uploads_descriptions'->>di.upload_index::text,
NULL
) AS upload_description,
uc.payload
FROM doc_info di
JOIN updated_claim uc ON uc.id = di.claim_uuid;