Commit Graph

114 Commits

Author SHA1 Message Date
AI Assistant
f26e0ba48e fix: Add claim_lookup CTE to send_to_form_approve SQL query
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
2025-11-24 17:07:52 +03:00
AI Assistant
d08e0da1ad fix: Add FROM partial to claim_lookup CTE to fix PostgreSQL error
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
2025-11-24 17:05:59 +03:00
AI Assistant
a8de3f0fc9 fix: Add claim_lookup CTE to search by both ID and payload claim_id
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
2025-11-24 17:02:29 +03:00
AI Assistant
33de3955ac fix: Add created_at to existing_claim CTE to fix PostgreSQL error
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
2025-11-24 16:59:33 +03:00
AI Assistant
81963d18c3 fix: Prevent duplicate claims by searching both by ID and payload claim_id
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
2025-11-24 16:52:58 +03:00
AI Assistant
894463742f fix: Order by updated_at DESC to get latest claim record with send_to_form_approve
Problem:
- Multiple records exist with same claim_id in DB
- One record (ID: 0eb051ec...) has send_to_form_approve.draft (updated: 2025-11-24)
- Another record (ID: b532b1b3...) doesn't have send_to_form_approve (updated: 2025-11-21)
- API query used LIMIT 1 without ORDER BY, could return wrong record
- Form was empty because wrong record (without send_to_form_approve) was returned

Solution:
- Added ORDER BY updated_at DESC to get latest record first
- This ensures we always get the record with send_to_form_approve.draft
- Latest record has correct data structure for confirmation form

Files:
- backend/app/api/claims.py: Added ORDER BY updated_at DESC
2025-11-24 16:46:56 +03:00
AI Assistant
29a9fe7532 fix: Use payload.send_to_form_approve.draft data directly instead of converting
Problem:
- Data already exists in DB in propertyName format at payload.send_to_form_approve.draft
- We were trying to convert from wizard_answers instead of using existing data
- Form was empty because we ignored the correct data structure

Solution:
1. Added priority check for payload.send_to_form_approve.draft:
   - If exists, use it directly (PRIORITY 1)
   - If not, fall back to conversion from wizard_answers (PRIORITY 2)

2. Direct usage of send_to_form_approve.draft:
   - Extract propertyName structure directly from draft
   - Preserve all fields: applicant, case, contract_or_service, offenders, claim, meta, attachments
   - Use unified_id from draft.meta or fallback to claim/formData

3. Enhanced logging:
   - Logs if send_to_form_approve.draft found
   - Logs draft data structure
   - Logs result structure

Files:
- frontend/src/pages/ClaimForm.tsx: Use send_to_form_approve.draft directly
2025-11-24 16:42:16 +03:00
AI Assistant
717295eb02 feat: Complete wizard_answers to propertyName conversion from DB data
Problem:
- Data comes from DB in wizard_answers format (answers to wizard questions)
- Form confirmation expects propertyName format (structured data)
- transformDraftToClaimPlanFormat tried to extract propertyName from DB, but it doesn't exist
- Form shows empty because propertyName structure is empty

Solution:
1. Added complete field mapping from wizard_answers to propertyName:
   - answersParsed.item → contract_or_service.subject
   - answersParsed.price → contract_or_service.amount_paid (normalized)
   - answersParsed.place_date → contract_or_service.agreement_date
   - answersParsed.cancel_date → contract_or_service.period_start
   - answersParsed.steps_taken → claim.description
   - answersParsed.expectation → claim.reason
   - payload.problem_description → claim.description and contract.subject

2. Added applicant data extraction:
   - phone from claim.phone, payload.phone, body.phone, or formData.phone
   - email from claim.email, payload.email, body.email, or formData.email
   - Other applicant fields (FIO, birth_date, INN) will be filled in confirmation form

3. Added default values:
   - case.category = 'consumer'
   - case.direction = 'web_form'

4. Enhanced logging:
   - Logs what data exists in DB
   - Logs wizard_answers keys
   - Logs conversion process

Files:
- frontend/src/pages/ClaimForm.tsx: Complete wizard_answers conversion
2025-11-24 16:35:27 +03:00
AI Assistant
4516fe8bfe feat: Add wizard_answers to propertyName conversion mapping
Problem:
- Data comes from DB in wizard_answers format (answers to wizard questions)
- Form confirmation expects propertyName format (structured data: applicant, case, contract_or_service)
- transformDraftToClaimPlanFormat tried to extract propertyName data from DB, but it doesn't exist there
- Form shows empty because propertyName structure is empty

Solution:
1. Added wizard_answers parsing from multiple sources:
   - body.answers, payload.answers
   - body.wizard_answers, payload.wizard_answers

2. Added basic field mapping from wizard_answers to propertyName:
   - answersParsed.item → contract_or_service.subject
   - answersParsed.price → contract_or_service.amount_paid
   - answersParsed.place_date → contract_or_service.agreement_date
   - answersParsed.steps_taken → claim.description

3. Added logging to debug data flow:
   - Logs what data exists in DB
   - Logs wizard_answers parsing
   - Logs conversion process

Note: This is a basic mapping. Full conversion requires complete field mapping from wizard_answers to propertyName structure.

Files:
- frontend/src/pages/ClaimForm.tsx: Added wizard_answers conversion
2025-11-24 16:33:16 +03:00
AI Assistant
d9414b32ad fix: Remove incorrect formData.case.meta access causing crash
Problem:
- Line 77 tried to access formData.case.meta
- formData structure changed to propertyName format
- formData.case doesn't exist, causing runtime error
- Form shows blank screen due to crash

Solution:
- Removed incorrect formData.case.meta access
- Added proper logging for formData and propertyName structure
- Form should now render correctly

Files:
- frontend/src/components/form/StepClaimConfirmation.tsx: Fixed formData access
2025-11-24 16:25:50 +03:00
AI Assistant
d34712f666 fix: Correct data extraction logic in JavaScript for propertyName format
Problem:
- When data comes as { propertyName: {...}, ... }, dataCandidate was set to propertyName object
- normalizeData expects { propertyName: {...} } format, not just propertyName
- Data normalization failed because structure didn't match

Solution:
- Changed logic to use entire injected object when propertyName exists
- This ensures normalizeData receives correct structure
- Data should now normalize correctly and populate form fields

Files:
- frontend/src/components/form/generateConfirmationFormHTML.ts: Fixed data extraction logic
2025-11-24 16:17:29 +03:00
AI Assistant
fc3ecdb63f fix: Pass data in propertyName format to match n8n structure
Problem:
- Data was being passed in normalized 'case' format
- generateConfirmationFormHTML expects propertyName format for normalization
- Form fields were empty because normalization didn't work correctly

Solution:
- Changed StepClaimConfirmation to pass data in propertyName format
- This matches the structure expected by normalizeData function
- Function can now properly normalize data from propertyName to case format
- All fields should now populate correctly

Files:
- frontend/src/components/form/StepClaimConfirmation.tsx: Changed data format to propertyName
2025-11-24 16:16:45 +03:00
AI Assistant
5e59a15bae feat: Increase iframe size and add auto-resize functionality
Problem:
- Form iframe was too small (800px fixed height)
- Only spinner visible, form content not fully visible

Solution:
1. Increased iframe container:
   - Changed Card bodyStyle to use calc(100vh - 200px)
   - Set minHeight to 800px
   - Made iframe flex: 1 to fill available space

2. Added auto-resize functionality:
   - Form sends iframe_resize messages with height
   - Parent component listens and adjusts iframe height
   - ResizeObserver watches for content changes
   - Window resize handler updates iframe size

3. Improved iframe styling:
   - Added sandbox attributes for security
   - Made height responsive (100% of container)
   - Minimum height ensures form is always visible

Files:
- frontend/src/components/form/StepClaimConfirmation.tsx: Increased iframe size, added resize handler
- frontend/src/components/form/generateConfirmationFormHTML.ts: Added auto-resize messaging
2025-11-24 16:03:25 +03:00
AI Assistant
08d59b9522 fix: Remove duplicate caseObj declaration
Problem:
- caseObj was declared twice: once at line 6 and again at line 270
- Caused esbuild compilation error

Solution:
- Removed first declaration at line 6
- Updated smsInputData extraction to handle multiple data formats
- caseObj is now only declared after normalization at line 270

Files:
- frontend/src/components/form/generateConfirmationFormHTML.ts: Fixed duplicate declaration
2025-11-24 15:59:40 +03:00
AI Assistant
67e0ff400e feat: Add normalizeData function matching n8n implementation
Problem:
- Form didn't handle data in propertyName format from n8n
- Missing normalization logic from n8n Code node

Solution:
1. Added normalizeData function in TypeScript:
   - Handles propertyName format (new format from n8n)
   - Handles old format (applicant, case, contract_or_service)
   - Handles case format (current structure)
   - Converts field names (first_name -> firstname, etc.)
   - Normalizes money values
   - Extracts attachments_names

2. Added normalizeData function in JavaScript:
   - Same logic as TypeScript version
   - Handles data extraction from multiple sources:
     * propertyName (object or string)
     * value
     * data
     * output
     * case
   - Supports array format (takes first element)

3. Enhanced data extraction logic:
   - Checks multiple data sources
   - Handles both array and object formats
   - Merges SMS meta data from injected
   - Ensures base structures exist

Files:
- frontend/src/components/form/generateConfirmationFormHTML.ts: Added normalization logic
2025-11-24 15:58:17 +03:00
AI Assistant
206e62ce76 feat: Add full confirmation form functionality matching n8n structure
Problem:
- Form was simplified and didn't match n8n implementation
- Missing validation, button state updates, checkbox handling
- Missing full statement text with consent checkbox

Solution:
1. Added complete renderStatement function:
   - Возмещение section with SBP phone display
   - Full ЗАЯВЛЕНИЕ text with all fields inline
   - Period fields (startdate/finishdate)
   - Full offender fields (email, phone, website)
   - Consent checkbox for privacy policy
   - Attachments list display

2. Added validation functions:
   - validateAllFields - checks all required fields
   - updateSubmitButton - updates button state based on consent and validation
   - Field validation helpers (isValidPhone, isValidEmail, isValidINN, etc.)

3. Enhanced attachBindings:
   - Date field conversion (YYYY-MM-DD <-> DD.MM.YYYY)
   - Money field comma to dot replacement
   - INN field filtering (numeric only, length limits)
   - Checkbox handling for privacy consent
   - Phone display update in SBP section

4. Added checkbox styles and createCheckbox function:
   - Custom checkbox styling matching n8n
   - Required checkbox error states
   - Proper label and link styling

5. Improved initialization:
   - Better error handling
   - Field validation on load
   - Delegated INN filtering
   - Proper state initialization

Files:
- frontend/src/components/form/generateConfirmationFormHTML.ts: Complete form implementation
2025-11-24 15:47:16 +03:00
AI Assistant
7fa3561038 fix: Remove duplicate smsInputData declaration
- Removed second declaration of smsInputData that used undefined 'raw' variable
- First declaration already correctly uses data.sms_meta
2025-11-24 15:41:33 +03:00
AI Assistant
ad7ff3786a fix: Add money normalization for confirmation form
- Normalize agrprice if it comes as string with 'рублей' etc
- Ensures consistent number format for money fields
2025-11-24 15:39:14 +03:00
AI Assistant
c410eb77c9 fix: Simplify data normalization in confirmation form HTML generator
Problem:
- Function was trying to normalize already normalized data
- Used undefined 'raw' variable after refactoring
- Data structure mismatch causing form not to render

Solution:
1. Removed redundant normalization logic:
   - Data is already normalized in StepClaimConfirmation component
   - Use caseObj directly from data.case
   - Only ensure base structures exist (user, project, offenders, meta, attachments)

2. Fixed undefined variable:
   - Changed raw.token to data.token
   - Removed unused normalization code

3. Simplified data flow:
   - Input: data.case (already normalized)
   - Output: caseJson with same structure
   - JavaScript in HTML uses injected.case directly

Files:
- frontend/src/components/form/generateConfirmationFormHTML.ts: Simplified normalization
2025-11-24 15:38:24 +03:00
AI Assistant
827a1e46ad refactor: Use provided structure for confirmation form HTML generation
Problem:
- User wants to use the provided n8n Code node structure for generating confirmation form HTML
- Current implementation doesn't match the expected structure

Solution:
1. Created separate file generateConfirmationFormHTML.ts:
   - Implements data normalization from propertyName format
   - Uses provided HTML template structure
   - Includes field creation functions (createField, createDateField, etc.)
   - Implements form rendering with editable inline fields
   - Handles form data binding and submission via postMessage

2. Updated StepClaimConfirmation component:
   - Imports generateConfirmationFormHTML from separate file
   - Removed old inline HTML generation function
   - Uses new structure-based generation

3. Data normalization:
   - Transforms propertyName structure to form structure
   - Maps applicant fields: first_name -> firstname
   - Maps contract_or_service fields to project
   - Maps claim fields to project (description, reason)
   - Handles attachments and offenders arrays

4. Form features:
   - Inline editable fields in statement text
   - Date fields with calendar picker
   - Money fields with рублей suffix
   - Readonly fields for phone and category
   - Form data collection and submission

Files:
- frontend/src/components/form/generateConfirmationFormHTML.ts: New file with form generation logic
- frontend/src/components/form/StepClaimConfirmation.tsx: Updated to use new generator
2025-11-24 15:32:08 +03:00
AI Assistant
98802b0540 feat: Implement full confirmation form with editable fields
Problem:
- Only placeholder with Claim ID and Unified ID was shown
- No actual form for editing claim data
- User asked when the actual form will appear

Solution:
1. Created full HTML form with editable fields:
   - Applicant data (name, birthday, birthplace, INN, address, phone, email)
   - Case data (category, subject, date, amount, reason, description)
   - Offender data (organization name, address, INN, OGRN, contacts)
   - Attachments list (read-only display)

2. Fixed data mapping:
   - Transform propertyName structure to form structure
   - Map applicant fields: first_name -> firstname, etc.
   - Map contract_or_service fields to project
   - Map claim fields to project (description, reason)

3. Form features:
   - All fields are editable except phone (read-only)
   - Category is read-only (set by system)
   - Form collects edited values on confirmation
   - Sends form data back via postMessage

4. Removed n8n webhook call:
   - HTML form is generated locally in React component
   - No external dependencies for form generation

Files:
- frontend/src/components/form/StepClaimConfirmation.tsx: Full form implementation
2025-11-24 15:24:49 +03:00
AI Assistant
aed2a86ba8 fix: Fix claim_id and unified_id display in confirmation form
Problem:
- Claim ID and Unified ID showing as 'не указан' in confirmation form
- transformDraftToClaimPlanFormat was returning array instead of object
- StepClaimConfirmation was not correctly extracting IDs from claimPlanData

Solution:
1. Changed transformDraftToClaimPlanFormat return type:
   - Changed from array [{ propertyName, ... }] to object { propertyName, ... }
   - This matches what StepClaimConfirmation expects

2. Enhanced ID extraction in StepClaimConfirmation:
   - Added explicit claimId and unifiedId variables
   - Better fallback chain: claimPlanData.claim_id -> propertyName.meta.claim_id
   - Same for unified_id

3. Added comprehensive logging:
   - Log claimPlanData structure on component mount
   - Log extracted IDs before form generation
   - Log transformDraftToClaimPlanFormat input/output
   - Log claim.unified_id from API response

4. Improved data flow:
   - claim.unified_id from API -> transformDraftToClaimPlanFormat -> StepClaimConfirmation
   - Fallback to currentFormData.unified_id if claim.unified_id missing

Files:
- frontend/src/pages/ClaimForm.tsx: Changed return type, added logging
- frontend/src/components/form/StepClaimConfirmation.tsx: Enhanced ID extraction, added logging
2025-11-24 15:16:46 +03:00
AI Assistant
1789dafce2 fix: Improve problem_description detection for draft completeness check
Problem:
- problem_description not found in payload, but exists in draft list
- Completeness check fails because hasDescription = false
- Draft not recognized as ready for confirmation

Solution:
1. Enhanced problem_description extraction:
   - Checks multiple locations: body.problem_description, payload.problem_description
   - Also checks payload.body.problem_description for nested structures
   - Added fallback to body.description and payload.description

2. Improved completeness logic:
   - If problem_description not found but wizard_plan and answers exist,
     infer that description was entered (plan is generated from description)
   - This handles cases where description exists but not in expected payload location

3. Better logging:
   - Shows if problem_description was found directly or inferred
   - Logs all payload keys for debugging

Logic:
- hasDescription = !!problemDescription || (!!wizardPlan && !!answers)
- If plan and answers exist → description was entered earlier
- This allows drafts with plan+answers+documents to proceed to confirmation

Files:
- frontend/src/pages/ClaimForm.tsx: Enhanced problem_description detection
2025-11-24 15:12:29 +03:00
AI Assistant
577611c65d refactor: Load claim confirmation data from DB instead of SSE for drafts
Problem:
- When draft is fully filled, we subscribed to Redis SSE channel claim:plan
- But all data already exists in PostgreSQL database
- No need to wait for n8n to publish data - we can load it directly

Solution:
1. Removed subscribeToClaimPlanForDraft() function
   - No longer subscribes to SSE channel for drafts
   - Removed EventSource cleanup code

2. Added transformDraftToClaimPlanFormat() function
   - Transforms draft data from DB format to propertyName format
   - Extracts data from payload/body (telegram/web_form formats)
   - Maps documents_meta to attachments array
   - Formats applicant, case, contract_or_service, offenders, claim, meta
   - Returns data in array format expected by confirmation form

3. Updated loadDraft() logic:
   - When draft is ready for confirmation (all steps filled + draft status)
   - Calls transformDraftToClaimPlanFormat() instead of subscribing to SSE
   - Immediately shows confirmation form with data from DB

Flow:
1. User selects fully filled draft
2. System checks completeness (description, plan, answers, documents)
3. If ready → transforms DB data to propertyName format
4. Shows confirmation form immediately (no SSE wait)

Benefits:
-  Faster: no waiting for n8n to publish data
-  More reliable: data always available from DB
-  Simpler: no SSE connection management for drafts
-  Works offline: doesn't depend on Redis pub/sub

Files:
- frontend/src/pages/ClaimForm.tsx: Added transform function, removed SSE subscription
2025-11-24 15:08:00 +03:00
AI Assistant
379995ba51 feat: Auto-navigate to confirmation form when draft is fully filled
Problem:
- When user selects a draft with all steps filled (description, plan, answers, documents)
- But claim status is still 'draft' (not submitted)
- User has to manually navigate through all steps again

Solution:
1. Added check in loadDraft() to detect fully filled drafts:
   - hasDescription: problem_description exists
   - hasWizardPlan: wizard_plan exists
   - hasAnswers: answers exist and not empty
   - hasDocuments: documents_meta array has items
   - isDraft: status_code === 'draft'
   - allStepsFilled: all checks pass

2. When draft is ready for confirmation:
   - Automatically subscribe to claim:plan SSE channel
   - Wait for claim data from n8n
   - Show loading message while waiting
   - On success: show confirmation form automatically

3. Added subscribeToClaimPlanForDraft() function:
   - Subscribes to /api/v1/claim-plan/{session_token}
   - Handles claim_plan_ready event
   - Updates formData with claimPlanData
   - Auto-navigates to confirmation step via useEffect

4. Added useEffect for auto-navigation:
   - Watches formData.showClaimConfirmation and formData.claimPlanData
   - When both true, navigates to step 3 (confirmation)
   - Handles cleanup of EventSource on unmount

Flow:
1. User selects draft → loadDraft() checks completeness
2. If all filled + draft → subscribeToClaimPlanForDraft()
3. SSE receives data → updates formData
4. useEffect detects → navigates to confirmation step
5. User sees confirmation form immediately

Files:
- frontend/src/pages/ClaimForm.tsx: Added auto-navigation logic
2025-11-24 14:11:04 +03:00
AI Assistant
0978e485dc feat: Add claim plan confirmation flow via Redis SSE
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
2025-11-24 13:36:14 +03:00
AI Assistant
40ad46c026 fix: Parse wizard_plan from edit_fields_parsed structure
Problem:
- wizard_plan comes in nested structure: edit_fields_parsed.wizard_plan_parsed
- Old SQL looked for wizard_plan at root level (partial.p->'wizard_plan')
- Result: wizard_plan was always NULL even though it existed in payload

Solution:
- Updated wizard_plan_parsed CTE to check multiple locations:
  1. edit_fields_parsed.wizard_plan_parsed (already parsed object) 
  2. edit_fields_raw.body.wizard_plan (escaped JSON string)
  3. Root level wizard_plan (backward compatibility)
  4. Database fallback (if not in payload)

- Updated wizard_answers_parsed CTE:
  1. edit_fields_raw.body.wizard_answers (string) 
  2. edit_fields_parsed.body.wizard_answers (string)
  3. Root level (backward compatibility)

- Updated session_id, unified_id, contact_id, phone extraction:
  COALESCE() checks edit_fields_parsed.body and edit_fields_raw.body

Input structure from n8n workflow form_get:
{
  "payload_partial_json": {
    "edit_fields_parsed": {
      "wizard_plan_parsed": {...},  ← TARGET
      "body": {
        "session_id": "sess_xxx",  ← ALSO HERE
        "unified_id": "usr_xxx",
        "wizard_answers": "{...}"
      }
    }
  }
}

Now: wizard_plan preserves correctly when uploading files 
2025-11-21 16:10:57 +03:00
AI Assistant
60a67c7e37 fix: Preserve wizard_plan and AI fields from DB when updating claim
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
2025-11-21 16:04:55 +03:00
AI Assistant
d6b17baa7d feat: Add PostgreSQL fields and workflow for form without files
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
2025-11-21 15:57:18 +03:00
AI Assistant
3621ae6021 feat: Session persistence with Redis + Draft management fixes
- Implement session management API (/api/v1/session/create, verify, logout)
- Add session restoration from localStorage on page reload
- Fix session_id priority when loading drafts (use current, not old from DB)
- Add unified_id and claim_id to wizard payload sent to n8n
- Add Docker volume for frontend HMR (Hot Module Replacement)
- Add comprehensive session logging for debugging

Components updated:
- backend/app/api/session.py (NEW) - Session management endpoints
- backend/app/main.py - Include session router
- frontend/src/components/form/Step1Phone.tsx v2.0 - Create session after SMS
- frontend/src/pages/ClaimForm.tsx v3.8 - Session restoration & priority fix
- frontend/src/components/form/StepWizardPlan.tsx v1.4 - Add unified_id/claim_id
- docker-compose.yml - Add frontend volume for live reload

Session flow:
1. User verifies phone -> session created in Redis (24h TTL)
2. session_token saved to localStorage
3. Page reload -> session restored automatically
4. Draft selected -> current session_id used (not old from DB)
5. Wizard submit -> unified_id, claim_id, session_id sent to n8n
6. Logout -> session removed from Redis & localStorage

Fixes:
- Session token not persisting after page reload
- unified_id missing in n8n webhook payload
- Old session_id from draft overwriting current session
- Frontend changes requiring container rebuild
2025-11-20 18:31:42 +03:00
AI Assistant
4c8fda5f55 Добавлено логирование для отладки черновиков
- Добавлены логи в frontend (ClaimForm.tsx) для отслеживания unified_id и запросов к API
- Добавлены логи в backend (claims.py) для отладки SQL запросов
- Создан лог сессии с описанием проблемы и текущего состояния
- Проблема: API возвращает 0 черновиков, хотя в БД есть данные
2025-11-19 18:46:48 +03:00
AI Assistant
cbab1c0fe6 feat(ticket_form): add wizard plan step and dev cache 2025-11-15 18:48:15 +03:00
AI Assistant
3306d01e0d Ticket form: new stack + description step 2025-11-14 19:06:36 +03:00
AI Assistant
3d121054ab docs: Финальная документация с прямым PHP эндпоинтом 2025-11-02 19:25:29 +03:00
AI Assistant
ec44f43ca0 docs: Добавлена краткая шпаргалка для быстрого старта 2025-11-02 19:21:37 +03:00
AI Assistant
efb0cd6f05 feat: Поддержка batch-обработки документов и умного парсинга S3 путей
Изменения в /api/n8n/documents/attach:
 Принимает массив документов (не одиночный объект)
 Умная обработка S3 путей:
   - /bucket/path → https://s3.twcstorage.ru/bucket/path
   - bucket/path → https://s3.twcstorage.ru/bucket/path
   - https://... → без изменений
 Поддержка обоих форматов полей:
   - file / file_url
   - filename / file_name
 Batch-обработка с детальной статистикой
 Возвращает результаты для каждого документа отдельно
 Логирование успешных и неуспешных операций

Формат ответа:
{
  total_processed: N,
  successful: M,
  failed: K,
  results: [...],
  errors: [...]
}

Тесты:
- TEST_REAL_DATA.sh - тест с реальными данными из n8n
- TEST_QUICK.sh - быстрые тесты

Документация обновлена с примерами batch-обработки
2025-11-02 19:21:02 +03:00
AI Assistant
e27280e675 docs: Добавлена полная документация API привязки документов 2025-11-02 19:06:51 +03:00
AI Assistant
936cea62ae feat: Добавлен эндпоинт для привязки документов к проекту/заявке
Изменения:
 Новый endpoint: POST /api/n8n/documents/attach
 Поддерживает привязку к Project или HelpDesk
 Логика: если указан ticket_id → HelpDesk, иначе → Project
 Полное логирование всех операций
 Интеграция с upload_documents_to_crm.php

Входные данные:
- contact_id (обязательно)
- project_id (обязательно)
- file_url (обязательно)
- file_name (обязательно)
- ticket_id (опционально, для привязки к заявке)
- file_type (опционально, описание документа)

Готово к интеграции в n8n workflow!
2025-11-02 19:05:53 +03:00
AI Assistant
d3b7b3bb6a feat: Добавлены все N8N webhook URLs в config.py
Изменения:
 Добавлены переменные n8n_create_contact_webhook и n8n_create_claim_webhook в Settings
 Все webhook URLs теперь централизованно в .env
 Удалён хардкод из n8n_proxy.py

Теперь все N8N webhooks:
- N8N_POLICY_CHECK_WEBHOOK
- N8N_FILE_UPLOAD_WEBHOOK
- N8N_CREATE_CONTACT_WEBHOOK
- N8N_CREATE_CLAIM_WEBHOOK
2025-11-02 12:45:30 +03:00
AI Assistant
2d08043b4d feat: Добавлено логирование response для policy/check
Проблема:
- Backend не логировал что именно n8n возвращает для /api/n8n/policy/check
- Не видно откуда брать project_id в response

Исправление:
 Добавлено логирование response.text[:500] для policy/check
 Добавлена обработка ошибок парсинга JSON

Теперь в логах видно полный ответ от n8n!
2025-11-02 10:47:56 +03:00
AI Assistant
cd2ff8e61b feat: Добавлен backend proxy для создания контакта
Проблема:
- Step1Phone делал запрос НАПРЯМУЮ к n8n (палил webhook URL)
- В backend логах не было видно что n8n возвращает для контакта
- Нельзя было отследить contact_id, claim_id, is_new_contact

Решение:
 Добавлен endpoint /api/n8n/contact/create в n8n_proxy.py
 Step1Phone.tsx теперь использует proxy вместо прямого URL
 Backend логирует полный response от n8n (contact_id, claim_id и тд)

Теперь весь трафик к n8n идёт через backend proxy!
2025-11-02 10:40:57 +03:00
AI Assistant
b17825ee52 fix: Добавлены недостающие поля в FormData интерфейс
Проблема:
- TypeScript игнорировал project_id, is_new_project, ticket_id, ticket_number
- Они не были объявлены в interface FormData

Исправление:
 Добавлены в FormData:
  - project_id?: string          (ID проекта в vTiger)
  - is_new_project?: boolean     (флаг создания)
  - ticket_id?: string           (ID заявки HelpDesk)
  - ticket_number?: string       (номер заявки)

Теперь updateFormData корректно сохраняет все данные от n8n!
2025-11-02 10:25:24 +03:00
AI Assistant
c6d848fd14 fix: Корректное извлечение данных из n8n response в Step1Phone
Проблема:
- n8n возвращает [{success: true, result: {claim_id, contact_id, ...}}]
- Код пытался взять data.claim_id вместо data.result.claim_id

Исправление:
-  Обработка массива от n8n
-  Извлечение данных из result: const result = crmResult.result || crmResult
-  Улучшенное логирование для отладки
-  Проверка crmResult.success перед обработкой

Теперь formData корректно получает:
- claim_id (от n8n)
- contact_id (от CreateWebContact)
- is_new_contact (флаг)
2025-11-02 08:42:41 +03:00
AI Assistant
ea287b32eb feat: Сохранение project_id в formData при проверке полиса
-  Добавлена обработка массива от n8n (как в Step2EventType)
-  Сохранение project_id, is_new_project в formData
-  Сохранение contact_id для консистентности
-  Работает как для найденного, так и для не найденного полиса

Теперь formData содержит полную информацию:
- claim_id (из n8n)
- contact_id (из CreateWebContact)
- project_id (из CreateWebProject) ← НОВОЕ
- is_new_project (флаг создания) ← НОВОЕ
2025-11-02 08:37:25 +03:00
AI Assistant
0be216ba43 docs: Добавлен лог сессии CreateWebClaim + полная интеграция
Подробная документация:
-  CreateWebClaim.php - операция vTiger для заявок
-  n8n workflow get_claim_CRM_ERV (ID: qdYZqhIDGhK9E4DA)
-  Backend proxy /api/n8n/claim/create
-  Frontend интеграция Step2EventType
-  Решенные проблемы: BOM, пустой ответ n8n, массив вместо объекта
-  Полный флоу создания заявки
-  Метрики и статистика

Создано заявок: 8 (последняя ЗАЯВКА_825)
Время работы: 4 часа 15 минут
2025-11-02 01:19:12 +03:00
AI Assistant
6cd7027e1a fix: Улучшена обработка ответа n8n в claim/create
-  Проверка на пустой ответ
-  Подробное логирование тела ответа
-  Детальное сообщение об ошибке парсинга JSON
2025-11-02 00:57:03 +03:00
AI Assistant
927a8f5f7c feat: Проксирование CreateClaim через backend
-  Новый endpoint: POST /api/n8n/claim/create
-  Проксирует запросы к n8n webhook создания заявки
-  Frontend теперь использует /api/n8n/claim/create вместо прямого URL
-  Решает проблему CORS и скрывает webhook URL
-  Логирование запросов и ошибок
2025-11-02 00:55:25 +03:00
AI Assistant
cacb2ee7bb fix: Обработка массива в ответе n8n для CreateWebClaim
-  n8n может вернуть [{success: true, ...}] вместо {success: true, ...}
-  Добавлена проверка Array.isArray и извлечение первого элемента
-  Теперь корректно обрабатывается ответ от webhook создания заявки
2025-11-02 00:53:21 +03:00
AI Assistant
793177b1e2 feat: Интеграция создания черновика заявки в Step2EventType
-  Вызов n8n webhook после выбора типа события
-  Формирование title из event_type + voucher
-  Передача всех данных: claim_id, contact_id, project_id, event_type
-  Сохранение ticket_id и ticket_number в formData
-  Loading состояние кнопки
-  Debug события для отслеживания
2025-11-02 00:09:35 +03:00
AI Assistant
b06fdb731c fix: claim_id теперь генерируется только на бэкенде (n8n)
-  Удалена локальная генерация claim_id в ClaimForm.tsx
-  claim_id создаётся n8n при SMS верификации
-  Step1Phone: передаёт session_id в n8n, сохраняет claim_id
-  Step1Policy: сохраняет claim_id из ответа n8n при проверке полиса
-  Добавлено детальное логирование для отладки
- 📝 PROJECT_TIMELINE.md - полная хронология проекта (24 окт - 1 ноя)
2025-11-01 16:53:10 +03:00