- Добавлена полная интеграция с Telegram Mini App (динамическая загрузка SDK)
- Отдельный компактный дизайн для Telegram Mini App
- Добавлен loader при инициализации (предотвращает мелькание SMS-авторизации)
- Улучшена навигация: кнопки "Назад" и "К списку заявок" теперь сохраняют авторизацию
- Telegram Mini App: кнопка "Выход" просто закрывает приложение
- Telegram Mini App: заявки "В работе" скрыты из списка
- Веб-версия: для заявок "В работе" добавлена кнопка "Просмотреть в Telegram" (ссылка на @klientprav_bot)
- Telegram Mini App: кнопки действий в черновиках расположены вертикально
- Веб-версия: убрано отображение номера телефона в приветствии
- Исправлена проблема с возвратом к списку черновиков (не требует повторной SMS-авторизации)
- Заблокировано удаление и редактирование заявок со статусом "В работе"
- Добавлена документация по Telegram Mini App интеграции
- Добавлен сервис CrmMySQLService для прямого подключения к MySQL CRM
- Обновлён метод get_draft() для получения cf_2624 напрямую из БД
- Реализована блокировка полей (readonly) при contact_data_confirmed = true
- Добавлен выбор банка для СБП выплат с динамической загрузкой из API
- Обновлена документация по работе с cf_2624 и MySQL
- Добавлен network_mode: host в docker-compose для доступа к MySQL
- Обновлены компоненты формы для поддержки блокировки полей
- Исправлена потеря документов при обновлении черновика (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
Added:
- Detailed logging for /api/v1/claims/description endpoint
- Full event data logging for debugging
- Documentation for n8n workflow setup (N8N_DESCRIPTION_WORKFLOW.md)
The issue: Form hangs on recommendations step because n8n doesn't process description events.
Flow:
1. Frontend sends description to /api/v1/claims/description
2. Backend publishes to Redis channel ticket_form:description
3. Frontend subscribes to SSE /api/v1/events/{session_id} (listens to ocr_events:{session_id})
4. n8n must:
- Subscribe to ticket_form:description channel
- Process description and generate wizard_plan
- Publish wizard_plan back to ocr_events:{session_id} channel
Files:
- backend/app/api/claims.py (enhanced logging)
- docs/N8N_DESCRIPTION_WORKFLOW.md (new documentation)
Added filtering to exclude approved/confirmed forms from drafts list:
- Updated /drafts/list endpoint to filter out forms with status_code='approved' or is_confirmed=true
- Created SQL script for n8n to mark forms as approved after processing Redis channel data
- Forms marked as approved will no longer appear in drafts list
SQL script: SQL_MARK_FORM_APPROVED.sql
- Updates status_code to 'approved'
- Sets is_confirmed = true
- Uses claim_lookup CTE to find claim by id or payload->>'claim_id'
Files:
- backend/app/api/claims.py (updated drafts list queries)
- docs/SQL_MARK_FORM_APPROVED.sql (new SQL script for n8n)
Changed from dynamic channel form_approve:{claim_id} to fixed channel:
- Channel: clientright:webform:approve
- Simpler n8n subscription (no need for dynamic channel name)
- All form approvals go to the same channel
Files:
- backend/app/api/claims.py
- frontend/src/components/form/StepClaimConfirmation.tsx
- docs/REDIS_FORM_APPROVE.md
Problem:
- Form was empty because propertyName was not passed to iframe
- JavaScript code checked for injected.propertyName but it was undefined
- Only case (normalized) was passed, not the original propertyName
Solution:
- Added propertyName to caseJson object that gets embedded in HTML
- Now JavaScript code can access both case and propertyName
- This allows the form to properly display data from send_to_form_approve.draft
Files:
- frontend/src/components/form/generateConfirmationFormHTML.ts: Added propertyName to caseJson
Problem:
- Query only searched by ID: WHERE id = claim_id::uuid
- If record exists with different ID but same claim_id in payload,
it wasn't found and send_to_form_approve wasn't saved
Solution:
- Added claim_lookup CTE that searches both by ID and payload->>'claim_id':
WHERE c.id = claim_id::uuid OR c.payload->>'claim_id' = claim_id::text
- base now uses claim_lookup instead of direct query
- UPDATE uses claim_lookup.id instead of direct claim_id::uuid
- This ensures correct record is always used
Changes:
- Added claim_lookup CTE for record lookup
- base reads from claim_lookup instead of direct query
- UPDATE uses claim_lookup.id instead of claim_id::uuid
Files:
- docs/SQL_SEND_TO_FORM_APPROVE_FIXED.sql: Fixed version with claim_lookup
Error:
- missing FROM-clause entry for table "partial"
- claim_lookup CTE used partial.claim_id_str but didn't have FROM partial
Root Cause:
- In CTE claim_lookup, we referenced partial.claim_id_str in WHERE clause
- But didn't include FROM partial, so PostgreSQL couldn't find the table
Solution:
- Added FROM partial to claim_lookup CTE:
FROM clpr_claims c, partial
- Now partial is available in claim_lookup CTE
- Also prefixed columns with table aliases (c.id, c.payload) for clarity
Files:
- docs/SQL_CLAIMSAVE_FINAL_FIXED.sql: Added FROM partial to claim_lookup
Problem:
- Original query only searched by ID: WHERE c.id = partial.cid
- If record exists with different ID but same claim_id in payload,
it wasn't found and documents weren't updated
Solution:
- Added claim_lookup CTE that searches both by ID and payload->>'claim_id':
WHERE id::text = claim_id_str OR payload->>'claim_id' = claim_id_str
- Uses found ID from claim_lookup instead of partial.cid
- This ensures correct record is always used
Changes:
- partial now accepts $2::text (instead of $2::uuid)
- Added claim_lookup CTE for record lookup
- upd_claim uses claim_lookup.id instead of partial.cid
- docs uses claim_lookup.id instead of partial.cid
Files:
- docs/SQL_CLAIMSAVE_FINAL_FIXED.sql: Fixed version with claim_lookup
Error:
- column "created_at" does not exist
- There is a column named "created_at" in table "clpr_claims", but it cannot be referenced from this part of the query
Root Cause:
- existing_claim CTE only selected id and payload
- But INSERT query tried to use: (SELECT created_at FROM existing_claim)
- PostgreSQL couldn't find created_at in existing_claim CTE
Solution:
- Added created_at to existing_claim CTE SELECT clause
- Now created_at is available for use in INSERT query
Files:
- docs/SQL_CLAIMSAVE_UPSERT_SIMPLE.sql: Added created_at to existing_claim CTE
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
Problem:
- After wizard form submission, need to wait for claim data from n8n
- Claim data comes via Redis channel claim:plan:{session_token}
- Need to display confirmation form with claim data
Solution:
1. Backend: Added SSE endpoint /api/v1/claim-plan/{session_token}
- Subscribes to Redis channel claim:plan:{session_token}
- Streams claim data from n8n to frontend
- Handles timeouts and errors gracefully
2. Frontend: Added subscription to claim:plan channel
- StepWizardPlan: After form submission, subscribes to SSE
- Waits for claim_plan_ready event
- Shows loading message while waiting
- On success: saves claimPlanData and shows confirmation step
3. New component: StepClaimConfirmation
- Displays claim confirmation form in iframe
- Receives claimPlanData from parent
- Generates HTML form (placeholder - should call n8n for real HTML)
- Handles confirmation/cancellation via postMessage
4. ClaimForm: Added conditional step for confirmation
- Shows StepClaimConfirmation when showClaimConfirmation=true
- Step appears after StepWizardPlan
- Only visible when claimPlanData is available
Flow:
1. User fills wizard form → submits
2. Form data sent to n8n via /api/v1/claims/wizard
3. Frontend subscribes to SSE /api/v1/claim-plan/{session_token}
4. n8n processes data → publishes to Redis claim:plan:{session_token}
5. Backend receives → streams to frontend via SSE
6. Frontend receives → shows StepClaimConfirmation
7. User confirms → proceeds to next step
Files:
- backend/app/api/events.py: Added stream_claim_plan endpoint
- frontend/src/components/form/StepWizardPlan.tsx: Added subscribeToClaimPlan
- frontend/src/components/form/StepClaimConfirmation.tsx: New component
- frontend/src/pages/ClaimForm.tsx: Added confirmation step to steps array
Problem:
- When uploading files on Step 3, wizard_plan was reset to NULL
- wizard_plan is created on Step 2 (StepDescription) and saved by claimsave_primary
- form_get workflow on Step 3 doesn't receive wizard_plan again
- Old SQL was overwriting wizard_plan with NULL
Solution:
- Add 'existing_claim' CTE to read current payload from DB
- Modified all parsers to fallback to DB values if field not in incoming payload:
* wizard_plan_parsed - preserves generated wizard plan
* answers_prefill_parsed - preserves AI-generated prefill
* coverage_report_parsed - preserves coverage analysis
* ai_agent1_facts_parsed - preserves fact extraction
* ai_agent13_rag_parsed - preserves RAG analysis
* problem_description_parsed - preserves user description
Flow:
1. Step 2: User describes problem → claimsave_primary saves wizard_plan ✅
2. Step 3: User uploads files → form_get/claimsave preserves wizard_plan from DB ✅
File: docs/SQL_CLAIMSAVE_UPSERT_SIMPLE.sql
Next: Update n8n workflow 'form_get' node 'claimsave' with this SQL
Database changes:
- Add unified_id, contact_id, phone columns to clpr_claims table
- Create indexes for fast lookup by these fields
- Migrate existing data from payload to new columns
- SQL migration: docs/SQL_ALTER_CLPR_CLAIMS_ADD_FIELDS.sql
SQL improvements:
- Simplify claimsave query: remove complex claim_lookup logic
- Use UPSERT (INSERT ON CONFLICT) with known claim_id
- Always return claim (fix NULL issue)
- Store unified_id, contact_id, phone directly in table columns
- SQL: docs/SQL_CLAIMSAVE_UPSERT_SIMPLE.sql
Workflow enhancements:
- Add branch for form submissions WITHOUT files
- Create 6 new nodes: extract, prepare, save, redis, respond
- Separate flow for has_files=false in IF node
- Instructions: docs/N8N_FORM_GET_NO_FILES_INSTRUCTIONS.md
- Node config: docs/N8N_FORM_GET_NO_FILES_BRANCH.json
Migration stats:
- Total claims: 81
- With unified_id: 77
- Migrated from payload: 2
Next steps:
1. Add 6 nodes to n8n workflow form_get (ID: 8ZVMTsuH7Cmw7snw)
2. Connect TRUE branch of IF node to extract_webhook_data_no_files
3. Test form submission without files
4. Verify PostgreSQL save and Redis event
- Добавлены логи в frontend (ClaimForm.tsx) для отслеживания unified_id и запросов к API
- Добавлены логи в backend (claims.py) для отладки SQL запросов
- Создан лог сессии с описанием проблемы и текущего состояния
- Проблема: API возвращает 0 черновиков, хотя в БД есть данные