# Support Cases How the portal surfaces and creates support cases for customers. ## Data Source & Scope - Cases are read and written directly in Salesforce. Origin is set to "Portal Support." - The portal only shows cases for the customer's mapped Salesforce Account to avoid leakage across customers. ## Creating a Case - Required inputs: subject and description. Optional: category/type and priority. - The portal creates the case in Salesforce with Status = New and Priority mapped to Salesforce values. - If a Contact ID is available it is used; otherwise the Account ID is set on the case. ## Viewing Cases - Cases are fetched from Salesforce with Redis caching (see Caching section below). - The portal summarizes open vs. closed counts and highlights high-priority cases. ## Real-Time Updates via Platform Events Support cases use Platform Events for real-time cache invalidation: **Platform Event:** `Case_Status_Update__e` | Field | API Name | Description | | ---------- | --------------- | --------------------- | | Account ID | `Account_Id__c` | Salesforce Account ID | | Case ID | `Case_Id__c` | Salesforce Case ID | **Flow Trigger:** Record update on Case when Status changes (and Origin = "Portal Support") **BFF Behavior:** 1. Invalidates `support:cases:{accountId}` cache 2. Invalidates `support:messages:{caseId}` cache 3. Sends SSE `support.case.changed` to connected portals 4. Portal refetches case data automatically See `docs/integrations/salesforce/platform-events.md` for full Platform Event documentation. ## Caching Strategy We use Redis TTL-based caching to reduce Salesforce API calls: | Cache Key | TTL | Invalidated On | | --------------------------- | --------- | -------------- | | `support:cases:{accountId}` | 2 minutes | Case created | | `support:messages:{caseId}` | 1 minute | Comment added | Features: - **Request coalescing**: Prevents thundering herd on cache miss - **Write-through invalidation**: Cache cleared after customer writes - **Metrics tracking**: Hits, misses, and invalidations are tracked ## Customer-Friendly Status Mapping Salesforce uses internal workflow statuses that may not be meaningful to customers. We map them to simplified, customer-friendly labels: | Salesforce Status (API) | Portal Display | Meaning | | ----------------------- | ----------------- | ------------------------------------- | | 新規 (New) | New | New case, not yet reviewed | | 対応中 (In Progress) | In Progress | Support is working on it | | Awaiting Approval | In Progress | Internal workflow (hidden) | | VPN Pending | In Progress | Internal workflow (hidden) | | Pending | In Progress | Internal workflow (hidden) | | 完了済み (Replied) | Awaiting Customer | Support replied, waiting for customer | | Closed | Closed | Case is closed | **Rationale:** - Internal workflow statuses are hidden from customers and shown as "In Progress" - "Replied/完了済み" means support has responded and is waiting for the customer - Only 4 statuses visible to customers: New, In Progress, Awaiting Customer, Closed ## Case Conversation (Messages) The case detail view shows a unified conversation timeline composed of: 1. **EmailMessages** - Email exchanges attached to the case 2. **CaseComments** - Portal comments added by customer or agent ### Features - **Date grouping**: Messages are grouped by date (Today, Yesterday, Mon Dec 30, etc.) - **Attachment indicators**: Messages with attachments show a paperclip icon - **Clean email bodies**: Quoted reply chains are stripped (see below) ### Email Body Cleaning Emails often contain quoted reply chains that pollute the conversation view. We automatically clean email bodies to show only the latest reply by stripping: **Single-line patterns:** - Lines starting with `>` (quoted text) - `From:`, `To:`, `Subject:`, `Sent:` headers - Japanese equivalents (送信者:, 件名:, etc.) **Multi-line patterns:** - "On Mon, Dec 29, 2025 at 18:43 ... wrote:" (Gmail style, spans multiple lines) - "-------- Original Message --------" blocks - Forwarded message headers This ensures each message bubble shows only the new content, not the entire email history. ## If something goes wrong - Salesforce unavailable: we show "support system unavailable, please try again later." - Case not found or belongs to another account: we respond with "case not found" to avoid leaking information.