- 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.
10 KiB
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:
- Invalidating caches - Ensuring fresh data on next request
- Sending SSE events - Notifying connected portal clients to refetch
- 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__cInternet_Eligibility_Status__cId_Verification_Status__cId_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
# 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
- Salesforce Workbench: Use "REST Explorer" to publish test events
- BFF Logs: Watch for event received messages
- 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) |