# 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.
