#!/usr/bin/env python3 """ Скрипт для исправления черновика bddb6815-8e17-4d54-a721-5e94382942c7 Добавляет documents_required и обновляет статус с учётом уже загруженного договора """ import asyncio import asyncpg import json from datetime import datetime # Параметры подключения к БД POSTGRES_HOST = "147.45.189.234" POSTGRES_PORT = 5432 POSTGRES_DB = "default_db" POSTGRES_USER = "gen_user" POSTGRES_PASSWORD = "2~~9_^kVsU?2\\S" CLAIM_ID = "bddb6815-8e17-4d54-a721-5e94382942c7" DOCUMENTS_REQUIRED = [ { "id": "contract", "name": "Договор или заказ", "hints": "Фото или скан подписанного договора или квитанции", "accept": ["pdf", "jpg", "png"], "priority": 1, "required": True }, { "id": "payment", "name": "Чек или подтверждение оплаты", "hints": "Копия кассового чека, онлайн-платежа или квитанции", "accept": ["pdf", "jpg", "png"], "priority": 1, "required": True }, { "id": "correspondence", "name": "Переписка", "hints": "Скриншоты сообщений, писем, жалоб", "accept": ["pdf", "jpg", "png"], "priority": 2, "required": False }, { "id": "evidence_photo", "name": "Фото доказательства", "hints": "Фото дефектов товара, видео процесса ремонта или передачи", "accept": ["jpg", "png", "pdf"], "priority": 2, "required": False } ] async def fix_draft(): """Исправляет черновик: добавляет documents_required и обновляет статус""" conn = await asyncpg.connect( host=POSTGRES_HOST, port=POSTGRES_PORT, database=POSTGRES_DB, user=POSTGRES_USER, password=POSTGRES_PASSWORD ) try: # Получаем текущее состояние черновика row = await conn.fetchrow(""" SELECT id, status_code, payload FROM clpr_claims WHERE id::text = $1 OR payload->>'claim_id' = $1 ORDER BY updated_at DESC LIMIT 1 """, CLAIM_ID) if not row: print(f"❌ Черновик {CLAIM_ID} не найден!") return payload = row['payload'] if isinstance(row['payload'], dict) else json.loads(row['payload']) current_status = row['status_code'] print(f"📋 Текущее состояние черновика:") print(f" - status_code: {current_status}") print(f" - documents_required: {len(payload.get('documents_required', []))} шт.") print(f" - documents_uploaded: {len(payload.get('documents_uploaded', []))} шт.") print(f" - documents_meta: {len(payload.get('documents_meta', []))} шт.") # Проверяем documents_meta на наличие загруженных документов documents_meta = payload.get('documents_meta', []) existing_documents_uploaded = payload.get('documents_uploaded', []) # Функция для определения типа документа (сначала по field_label, потом по field_name) def get_document_type(field_label: str, field_name: str) -> str: field_label_lower = field_label.lower() # ✅ СНАЧАЛА проверяем field_label (более точный способ) if 'договор' in field_label_lower or 'заказ' in field_label_lower: return 'contract' elif 'чек' in field_label_lower or 'оплат' in field_label_lower: return 'payment' elif 'переписк' in field_label_lower: return 'correspondence' elif 'доказательств' in field_label_lower or 'фото' in field_label_lower: return 'evidence_photo' # ✅ ПОТОМ проверяем field_name (fallback) elif 'uploads[0]' in field_name: return 'contract' elif 'uploads[1]' in field_name: return 'payment' elif 'uploads[2]' in field_name: return 'correspondence' elif 'uploads[3]' in field_name: return 'evidence_photo' else: return 'unknown' # ✅ Объединяем существующие documents_uploaded с documents_meta # Создаём мапу file_id -> doc_meta для быстрого поиска meta_by_file_id = {} if documents_meta: print(f"\n🔍 Найдено {len(documents_meta)} документов в documents_meta") for doc_meta in documents_meta: file_id = doc_meta.get('file_id', '') if file_id: meta_by_file_id[file_id] = doc_meta # ✅ Пересоздаём documents_uploaded: объединяем существующие с данными из documents_meta documents_uploaded = [] seen_file_ids = set() # Сначала обрабатываем documents_meta (приоритет) for doc_meta in documents_meta: file_id = doc_meta.get('file_id', '') if not file_id or file_id in seen_file_ids: continue field_label = doc_meta.get('field_label', '') field_name = doc_meta.get('field_name', '') doc_type = get_document_type(field_label, field_name) if doc_type != 'unknown': seen_file_ids.add(file_id) documents_uploaded.append({ "id": doc_type, "type": doc_type, "file_id": file_id, "file_name": doc_meta.get('file_name', ''), "original_file_name": doc_meta.get('original_file_name', ''), "uploaded_at": doc_meta.get('uploaded_at', datetime.utcnow().isoformat()), "ocr_status": "completed", "files_count": doc_meta.get('files_count', 1), "pages": doc_meta.get('pages', None) }) print(f" ✅ Из documents_meta: {doc_type} ({field_label}) - {doc_meta.get('original_file_name', 'N/A')}") # Затем добавляем существующие documents_uploaded, которых нет в documents_meta for existing_doc in existing_documents_uploaded: file_id = existing_doc.get('file_id', '') if not file_id or file_id in seen_file_ids: continue # Если есть в documents_meta - пропускаем (уже обработали) if file_id in meta_by_file_id: continue # Используем существующий тип или пытаемся определить по file_name doc_type = existing_doc.get('type') or existing_doc.get('id') or 'unknown' # Если тип неправильный (например, contract вместо payment), пытаемся определить по file_name if doc_type == 'contract' and 'chek' in file_id.lower(): doc_type = 'payment' elif doc_type == 'contract' and 'dogovor' in file_id.lower(): doc_type = 'contract' seen_file_ids.add(file_id) documents_uploaded.append({ "id": doc_type, "type": doc_type, "file_id": file_id, "file_name": existing_doc.get('file_name', ''), "original_file_name": existing_doc.get('original_file_name', ''), "uploaded_at": existing_doc.get('uploaded_at', datetime.utcnow().isoformat()), "ocr_status": existing_doc.get('ocr_status', 'completed'), "files_count": existing_doc.get('files_count', 1), "pages": existing_doc.get('pages', None) }) print(f" ✅ Из существующих: {doc_type} - {existing_doc.get('original_file_name', 'N/A')}") # Определяем current_doc_index (индекс следующего документа для загрузки) # Убираем дубликаты по типу документа uploaded_types = list(set([doc.get('id') or doc.get('type') for doc in documents_uploaded])) current_doc_index = 0 # Находим первый незагруженный документ for idx, doc_req in enumerate(DOCUMENTS_REQUIRED): if doc_req['id'] not in uploaded_types: current_doc_index = idx break else: # Все документы загружены current_doc_index = len(DOCUMENTS_REQUIRED) # Определяем новый статус (учитываем уникальные типы документов) uploaded_unique_types = len(uploaded_types) if uploaded_unique_types >= len(DOCUMENTS_REQUIRED): new_status = 'draft_docs_complete' elif uploaded_unique_types > 0: new_status = 'draft_docs_progress' else: new_status = 'draft_new' # Обновляем payload payload['documents_required'] = DOCUMENTS_REQUIRED payload['documents_uploaded'] = documents_uploaded payload['current_doc_index'] = current_doc_index print(f"\n📝 Обновление черновика:") print(f" - documents_required: {len(DOCUMENTS_REQUIRED)} документов") print(f" - documents_uploaded: {len(documents_uploaded)} документов") print(f" - current_doc_index: {current_doc_index} (следующий документ: {DOCUMENTS_REQUIRED[current_doc_index]['name'] if current_doc_index < len(DOCUMENTS_REQUIRED) else 'все загружены'})") print(f" - status_code: {current_status} → {new_status}") # Обновляем черновик await conn.execute(""" UPDATE clpr_claims SET status_code = $1, payload = $2::jsonb, updated_at = now() WHERE id::text = $3 OR payload->>'claim_id' = $3 """, new_status, json.dumps(payload, ensure_ascii=False), CLAIM_ID) print(f"\n✅ Черновик исправлен!") # Проверяем результат row_after = await conn.fetchrow(""" SELECT id::text, status_code, jsonb_array_length(COALESCE(payload->'documents_required', '[]'::jsonb)) as docs_required_count, jsonb_array_length(COALESCE(payload->'documents_uploaded', '[]'::jsonb)) as docs_uploaded_count, (payload->>'current_doc_index')::int as current_doc_index FROM clpr_claims WHERE id::text = $1 OR payload->>'claim_id' = $1 ORDER BY updated_at DESC LIMIT 1 """, CLAIM_ID) print(f"\n📊 Результат:") print(f" - status_code: {row_after['status_code']}") print(f" - documents_required count: {row_after['docs_required_count']}") print(f" - documents_uploaded count: {row_after['docs_uploaded_count']}") print(f" - current_doc_index: {row_after['current_doc_index']}") finally: await conn.close() if __name__ == "__main__": asyncio.run(fix_draft())