barsa a41f2bf47e Enhance BFF Modules and Update Domain Schemas
- Added new modules for SIM management, internet management, and call history to the BFF, improving service organization and modularity.
- Updated environment validation schema to reflect changes in Salesforce event channels, ensuring accurate configuration.
- Refactored router configuration to include new subscription-related modules, enhancing API routing clarity.
- Cleaned up Salesforce integration by removing unused service files and optimizing event handling logic.
- Improved support service by adding cache invalidation logic for case comments, ensuring real-time updates for users.
- Updated domain schemas to remove deprecated fields and enhance validation for residence card verification, promoting data integrity.
- Enhanced utility functions in the portal for better address formatting and confirmation prompts, improving user experience.
2026-01-05 15:11:56 +09:00

269 lines
10 KiB
Markdown

# Salesforce Platform Events & CDC
This guide documents all Platform Events and CDC (Change Data Capture) channels used for real-time communication between Salesforce and the Customer Portal.
## Overview
The BFF subscribes to Salesforce events using the Pub/Sub API and reacts by:
1. **Invalidating caches** - Ensuring fresh data on next request
2. **Sending SSE events** - Notifying connected portal clients to refetch
3. **Creating in-app notifications** - For significant status changes
## Event Types
| Type | Channel Prefix | Purpose |
| ------------------- | -------------- | ------------------------------------ |
| **Platform Events** | `/event/` | Custom events from Salesforce Flows |
| **CDC** | `/data/` | Standard object change notifications |
## Architecture
```
Salesforce Record Change
┌─────────────────────────────────────────┐
│ Platform Events: Record-Triggered Flow │
│ CDC: Automatic change tracking │
└─────────────────────────────────────────┘
BFF Pub/Sub Subscriber
┌────────────────────────────────────────┐
│ 1. Invalidate Redis cache │
│ 2. Send SSE to connected portal │
│ 3. Create notification (if applicable) │
└────────────────────────────────────────┘
```
---
## Platform Events
### 1. Account Update Event
**Purpose:** Notify portal when eligibility or verification status changes.
**Channel:** `SF_ACCOUNT_EVENT_CHANNEL` (default: `/event/Account_Eligibility_Update__e`)
#### Fields
| Field | API Name | Type | Required | When to Include |
| ------------------- | ------------------------ | --------- | --------- | --------------------------------------------------- |
| Account ID | `Account_Id__c` | Text(255) | ✅ Always | Always |
| Eligibility Status | `Eligibility_Status__c` | Text(255) | Optional | Only if `ISCHANGED(Internet_Eligibility_Status__c)` |
| Verification Status | `Verification_Status__c` | Text(255) | Optional | Only if `ISCHANGED(Id_Verification_Status__c)` |
| Rejection Message | `Rejection_Message__c` | Text(255) | Optional | Only if Verification_Status\_\_c = "Rejected" |
#### Salesforce Flow Logic
**Trigger:** Record update on Account when ANY of these fields change:
- `Internet_Eligibility__c`
- `Internet_Eligibility_Status__c`
- `Id_Verification_Status__c`
- `Id_Verification_Rejection_Message__c`
**Event Payload:**
```
Account_Id__c = {!$Record.Id}
IF ISCHANGED({!$Record.Internet_Eligibility_Status__c}) THEN
Eligibility_Status__c = {!$Record.Internet_Eligibility_Status__c}
END IF
IF ISCHANGED({!$Record.Id_Verification_Status__c}) THEN
Verification_Status__c = {!$Record.Id_Verification_Status__c}
IF {!$Record.Id_Verification_Status__c} = "Rejected" THEN
Rejection_Message__c = {!$Record.Id_Verification_Rejection_Message__c}
END IF
END IF
```
#### BFF Behavior
| Scenario | Cache Action | SSE Event | Notification |
| -------------------------------------- | --------------- | -------------------- | ------------------------- |
| Eligibility value changes (not status) | Invalidate both | ✅ `account.updated` | ❌ |
| Eligibility status → Pending | Invalidate both | ✅ `account.updated` | ❌ |
| Eligibility status → Eligible | Invalidate both | ✅ `account.updated` | ✅ ELIGIBILITY_ELIGIBLE |
| Eligibility status → Ineligible | Invalidate both | ✅ `account.updated` | ✅ ELIGIBILITY_INELIGIBLE |
| Verification status → Submitted | Invalidate both | ✅ `account.updated` | ❌ |
| Verification status → Verified | Invalidate both | ✅ `account.updated` | ✅ VERIFICATION_VERIFIED |
| Verification status → Rejected | Invalidate both | ✅ `account.updated` | ✅ VERIFICATION_REJECTED |
| Rejection message changes only | Invalidate both | ✅ `account.updated` | ❌ |
---
### 2. Case Status Update Event
**Purpose:** Notify portal when a support case status changes.
**Channel:** `SF_CASE_EVENT_CHANNEL` (default: `/event/Case_Status_Update__e`)
#### Fields
| Field | API Name | Type | Required |
| ---------- | --------------- | --------- | --------- |
| Account ID | `Account_Id__c` | Text(255) | ✅ Always |
| Case ID | `Case_Id__c` | Text(255) | ✅ Always |
#### Salesforce Flow Logic
**Trigger:** Record update on Case when Status changes (and Origin = "Portal Support")
**Event Payload:**
```
Account_Id__c = {!$Record.AccountId}
Case_Id__c = {!$Record.Id}
```
#### BFF Behavior
| Action | Description |
| -------------------------------------- | ------------------------- |
| Invalidate `support:cases:{accountId}` | Clear case list cache |
| Invalidate `support:messages:{caseId}` | Clear case messages cache |
| SSE `support.case.changed` | Notify portal to refetch |
---
### 3. Order Provision Requested Event
**Purpose:** Trigger order fulfillment when Salesforce Order is approved.
**Channel:** `/event/OrderProvisionRequested__e`
See `docs/how-it-works/order-fulfillment.md` for details.
---
## CDC (Change Data Capture)
### 1. Product2 CDC
**Purpose:** Detect product catalog changes.
**Channel:** `SF_CATALOG_PRODUCT_CDC_CHANNEL` (default: `/data/Product2ChangeEvent`)
#### BFF Behavior
| Action | Description |
| -------------------------- | --------------------------------- |
| Invalidate product cache | Clear affected products |
| Fallback full invalidation | If no specific products found |
| SSE `services.changed` | Notify portals to refetch catalog |
---
### 2. PricebookEntry CDC
**Purpose:** Detect pricing changes.
**Channel:** `SF_CATALOG_PRICEBOOKENTRY_CDC_CHANNEL` (default: `/data/PricebookEntryChangeEvent`)
#### BFF Behavior
| Action | Description |
| ------------------------ | ------------------------------------- |
| Filter by pricebook | Only process portal pricebook changes |
| Invalidate product cache | Clear affected products |
| SSE `services.changed` | Notify portals to refetch catalog |
---
### 3. Order CDC
**Purpose:** Detect order changes + trigger provisioning.
**Channel:** `SF_ORDER_CDC_CHANNEL` (default: `/data/OrderChangeEvent`)
#### BFF Behavior
| Scenario | Action |
| ------------------------------------- | ------------------------------ |
| `Activation_Status__c` → "Activating" | Enqueue provisioning job |
| Customer-facing field changes | Invalidate order cache + SSE |
| Internal field changes only | Ignore (no cache invalidation) |
**Internal fields (ignored):** `Activation_Status__c`, `WHMCS_Order_ID__c`, `Activation_Error_*`
---
### 4. OrderItem CDC
**Purpose:** Detect order line item changes.
**Channel:** `SF_ORDER_ITEM_CDC_CHANNEL` (default: `/data/OrderItemChangeEvent`)
#### BFF Behavior
| Scenario | Action |
| ----------------------------- | ------------------------------ |
| Customer-facing field changes | Invalidate order cache + SSE |
| Internal field changes only | Ignore (no cache invalidation) |
**Internal fields (ignored):** `WHMCS_Service_ID__c`
---
## Environment Variables
```bash
# Platform Events
SF_ACCOUNT_EVENT_CHANNEL=/event/Account_Eligibility_Update__e
SF_CASE_EVENT_CHANNEL=/event/Case_Status_Update__e
# Catalog CDC
SF_CATALOG_PRODUCT_CDC_CHANNEL=/data/Product2ChangeEvent
SF_CATALOG_PRICEBOOKENTRY_CDC_CHANNEL=/data/PricebookEntryChangeEvent
# Order CDC
SF_ORDER_CDC_CHANNEL=/data/OrderChangeEvent
SF_ORDER_ITEM_CDC_CHANNEL=/data/OrderItemChangeEvent
# Enable/disable all CDC subscriptions (Platform Events always enabled)
SF_EVENTS_ENABLED=true
```
---
## BFF Implementation
### Subscribers
| Subscriber | Events | Channel | File |
| ------------------------- | ------------------------ | --------- | ------------------------------ |
| `AccountEventsSubscriber` | Account | `/event/` | `account-events.subscriber.ts` |
| `CaseEventsSubscriber` | Case | `/event/` | `case-events.subscriber.ts` |
| `CatalogCdcSubscriber` | Product2, PricebookEntry | `/data/` | `catalog-cdc.subscriber.ts` |
| `OrderCdcSubscriber` | Order, OrderItem | `/data/` | `order-cdc.subscriber.ts` |
### Shared Utilities (`shared/`)
| File | Purpose |
| ------------------- | ------------------------------------ |
| `pubsub.service.ts` | Salesforce Pub/Sub client management |
| `pubsub.utils.ts` | Payload extraction helpers |
| `pubsub.types.ts` | TypeScript types |
| `index.ts` | Public exports |
---
## Testing
1. **Salesforce Workbench:** Use "REST Explorer" to publish test events
2. **BFF Logs:** Watch for event received messages
3. **Redis:** Verify cache keys are deleted after event
## Troubleshooting
| Issue | Cause | Solution |
| ------------------------ | ------------------------- | ----------------------------------------- |
| Events not received | Pub/Sub connection failed | Check BFF logs for connection errors |
| Cache not invalidated | Wrong ID in payload | Verify Flow is sending correct ID |
| Notification not created | Status not in final state | Only final states trigger notifications |
| Duplicate notifications | Same event re-delivered | Dedupe logic handles this (1 hour window) |