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

@@ -13,7 +13,7 @@ import logging
logger = logging.getLogger(__name__)
router = APIRouter()
router = APIRouter(prefix="/api/v1", tags=["Events"])
class EventPublish(BaseModel):
@@ -215,11 +215,97 @@ async def stream_events(task_id: str):
except Exception as e:
logger.error(f"❌ Error loading wizard data from PostgreSQL: {e}")
# ✅ Обработка ocr_status ready: загружаем form_draft из PostgreSQL
if actual_event.get('event_type') == 'ocr_status' and actual_event.get('status') == 'ready':
claim_id = actual_event.get('claim_id') or actual_event.get('data', {}).get('claim_id')
# ✅ Получаем cf_2624 из события (Данные подтверждены)
cf_2624 = actual_event.get('cf_2624')
if claim_id:
logger.info(f"🔍 OCR ready event received, loading form_draft for claim_id={claim_id}, cf_2624={cf_2624}")
try:
# ✅ Если есть cf_2624 в событии - сохраняем в черновик
if cf_2624 is not None:
try:
update_query = """
UPDATE clpr_claims
SET payload = jsonb_set(
COALESCE(payload, '{}'::jsonb),
'{cf_2624}',
$1::jsonb
)
WHERE id::text = $2 OR payload->>'claim_id' = $2
RETURNING id;
"""
await db.execute(update_query, json.dumps(cf_2624), claim_id)
logger.info(f"✅ Сохранён cf_2624={cf_2624} в черновик claim_id={claim_id}")
except Exception as e:
logger.warning(f"⚠️ Не удалось сохранить cf_2624 в черновик: {e}")
# Загружаем form_draft и documents из PostgreSQL
query = """
SELECT
c.id,
c.payload->'form_draft' as form_draft,
c.payload->'documents_required' as documents_required,
c.payload->'documents_meta' as documents_meta,
c.payload->>'cf_2624' as cf_2624
FROM clpr_claims c
WHERE c.id::text = $1 OR c.payload->>'claim_id' = $1
LIMIT 1
"""
row = await db.fetch_one(query, claim_id)
if row:
# Парсим JSONB поля (могут быть строками)
form_draft_raw = row.get('form_draft')
documents_required_raw = row.get('documents_required')
documents_meta_raw = row.get('documents_meta')
cf_2624_from_db = row.get('cf_2624') # ✅ Получаем cf_2624 из БД
# Парсим если строка
def parse_json_field(val):
if val is None:
return None
if isinstance(val, str):
try:
return json.loads(val)
except:
return val
return val
form_draft = parse_json_field(form_draft_raw)
documents_required = parse_json_field(documents_required_raw)
documents_meta = parse_json_field(documents_meta_raw)
# Обогащаем событие данными из БД
actual_event['data'] = {
'claim_id': claim_id,
'all_ready': True,
'form_draft': form_draft,
'documents_required': documents_required,
'documents_meta': documents_meta,
}
# ✅ Добавляем cf_2624 в событие (из БД или из события)
actual_event['cf_2624'] = cf_2624_from_db or cf_2624 or "0"
logger.info(f"✅ Form draft loaded from PostgreSQL for claim_id={claim_id}, has_form_draft={form_draft is not None}, cf_2624={actual_event.get('cf_2624')}")
else:
logger.warning(f"⚠️ Claim not found in PostgreSQL: claim_id={claim_id}")
except Exception as e:
logger.error(f"❌ Error loading form_draft from PostgreSQL: {e}")
# Отправляем событие клиенту (плоский формат)
event_json = json.dumps(actual_event, ensure_ascii=False)
event_json = json.dumps(actual_event, ensure_ascii=False, default=str)
event_type_sent = actual_event.get('event_type', 'unknown')
event_status = actual_event.get('status', 'unknown')
logger.info(f"📤 Sending event to client: type={event_type_sent}, status={event_status}")
# Логируем размер и наличие данных
data_info = actual_event.get('data', {})
has_form_draft = 'form_draft' in data_info if isinstance(data_info, dict) else False
logger.info(f"📤 Sending event to client: type={event_type_sent}, status={event_status}, json_len={len(event_json)}, has_form_draft={has_form_draft}")
yield f"data: {event_json}\n\n"
# Если обработка завершена - закрываем соединение
@@ -232,6 +318,11 @@ async def stream_events(task_id: str):
if event_type_sent in ['claim_ready', 'claim_plan_ready']:
logger.info(f"✅ Final event {event_type_sent} sent, closing SSE")
break
# Закрываем для ocr_status ready (форма заявления готова)
if event_type_sent == 'ocr_status' and event_status == 'ready':
logger.info(f"✅ OCR ready event sent, closing SSE")
break
else:
logger.info(f"⏰ Timeout waiting for message on {channel}")