- 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.
244 lines
11 KiB
Markdown
244 lines
11 KiB
Markdown
# Eligibility & Verification
|
||
|
||
This guide describes how eligibility and verification work in the customer portal:
|
||
|
||
- **Internet eligibility** (NTT serviceability review)
|
||
- **ID verification** (residence card / identity document) for all services
|
||
|
||
## Overview
|
||
|
||
| Concept | Source of Truth | Description |
|
||
| --------------------------- | ------------------------------------------- | -------------------------------- |
|
||
| Products + pricing | Salesforce pricebook | Single catalog truth |
|
||
| Payment methods | WHMCS | Card storage via Stripe |
|
||
| Orders + fulfillment | Salesforce Order (and downstream WHMCS) | Operational workflow |
|
||
| Internet eligibility status | Salesforce Account (with Case for workflow) | Reuse for future internet orders |
|
||
| ID verification status | Salesforce Account (with Files) | Reuse for future orders |
|
||
|
||
## Internet Eligibility (NTT Address Review)
|
||
|
||
### How It Works
|
||
|
||
1. Customer navigates to `/account/services/internet`
|
||
2. Customer clicks **Check Availability** (requires a service address on file)
|
||
3. Portal calls `POST /api/services/internet/eligibility-request` and shows an immediate confirmation screen at `/account/services/internet/request-submitted`
|
||
4. Portal **finds/creates a Salesforce Opportunity** (Stage = `Introduction`) and creates a Salesforce Case **linked to that Opportunity** for agent review
|
||
5. Agent performs NTT serviceability check (manual process)
|
||
6. Agent updates Account eligibility fields
|
||
7. Salesforce Flow sends email notification to customer
|
||
8. Customer returns and sees eligible plans
|
||
|
||
### Caching & Real-Time Updates
|
||
|
||
#### Redis Caching (BFF)
|
||
|
||
| Cache Key | Content | Invalidation |
|
||
| ----------------------------------- | --------------------------- | -------------- |
|
||
| `services:eligibility:{accountId}` | Eligibility status & value | Platform Event |
|
||
| `services:verification:{accountId}` | Verification status & dates | Platform Event |
|
||
|
||
Both caches use CDC-driven invalidation with a safety TTL (12 hours default). When Salesforce sends a Platform Event, the BFF:
|
||
|
||
1. Invalidates both caches (eligibility + verification)
|
||
2. Sends SSE `account.updated` to connected portals
|
||
3. Portal refetches fresh data
|
||
|
||
#### Platform Event Integration
|
||
|
||
See `docs/integrations/salesforce/platform-events.md` for full details.
|
||
|
||
**Account Update Event** fires when any of these fields change:
|
||
|
||
- `Internet_Eligibility__c`, `Internet_Eligibility_Status__c`
|
||
- `Id_Verification_Status__c`, `Id_Verification_Rejection_Message__c`
|
||
|
||
The Flow should use `ISCHANGED()` to only include status fields when they actually changed (not on every field change).
|
||
|
||
#### Portal Cache (React Query)
|
||
|
||
- Service catalog responses are cached in-memory, scoped by auth state
|
||
- SSE events trigger automatic refetch
|
||
- On logout, cached queries are cleared
|
||
|
||
#### Rate Limiting
|
||
|
||
- Public catalog endpoints: rate-limited per IP + User-Agent
|
||
- `POST /api/services/internet/eligibility-request`: authenticated, rate-limited, idempotent
|
||
|
||
### Subscription Type Detection
|
||
|
||
The portal identifies Internet subscriptions by product name matching:
|
||
|
||
```typescript
|
||
// Matches any of these patterns (case-insensitive):
|
||
// - "internet"
|
||
// - "sonixnet"
|
||
// - "ntt" + "fiber"
|
||
const isInternetService =
|
||
productName.includes("internet") ||
|
||
productName.includes("sonixnet") ||
|
||
(productName.includes("ntt") && productName.includes("fiber"));
|
||
```
|
||
|
||
### Salesforce Account Fields
|
||
|
||
| Field API Name | Type | Set By | When |
|
||
| ------------------------------------------- | -------- | ------------ | ------------- |
|
||
| `Internet_Eligibility_Status__c` | Picklist | Portal/Agent | Request/Check |
|
||
| `Internet_Eligibility__c` | Text | Agent | After check |
|
||
| `Internet_Eligibility_Request_Date_Time__c` | DateTime | Portal | On request |
|
||
| `Internet_Eligibility_Checked_Date_Time__c` | DateTime | Agent | After check |
|
||
|
||
**Notes:**
|
||
|
||
- The portal returns an API-level **request id** (Salesforce Case ID) from `POST /api/services/internet/eligibility-request` for display/auditing.
|
||
- The portal UI reads eligibility status/value from the Account fields above; it does not rely on an Account-stored Case ID.
|
||
|
||
### Status Values
|
||
|
||
| Status | Services Page UI | Checkout Gating |
|
||
| --------------- | --------------------------------------- | --------------- |
|
||
| `Not Requested` | Show "Request eligibility check" button | Block submit |
|
||
| `Pending` | Show "Review in progress" | Block submit |
|
||
| `Eligible` | Show eligible plans | Allow submit |
|
||
| `Ineligible` | Show "Not available" + contact support | Block submit |
|
||
|
||
## ID Verification (Residence Card)
|
||
|
||
### How It Works
|
||
|
||
1. Customer navigates to `/account/settings` (Profile page)
|
||
2. Customer uploads residence card in the "Identity Verification" section
|
||
3. File is uploaded to Salesforce (ContentVersion linked to Account)
|
||
4. Agent reviews document and updates verification status
|
||
5. Customer sees "Verified" status and can submit orders
|
||
|
||
### Where to Upload
|
||
|
||
ID verification is available in two places:
|
||
|
||
1. **Profile Page** (`/account/settings`) - Integrated upload in the "Identity Verification" card
|
||
2. **Standalone Page** (`/account/settings/verification`) - For checkout flow redirects
|
||
|
||
The Profile page is the primary location. The standalone page is used when redirecting from checkout with a `returnTo` parameter.
|
||
|
||
### Salesforce Account Fields
|
||
|
||
| Field API Name | Type | Set By | When |
|
||
| ---------------------------------------- | -------- | ------------ | ------------- |
|
||
| `Id_Verification_Status__c` | Picklist | Portal/Agent | Upload/Review |
|
||
| `Id_Verification_Submitted_Date_Time__c` | DateTime | Portal | On upload |
|
||
| `Id_Verification_Verified_Date_Time__c` | DateTime | Agent | After review |
|
||
| `Id_Verification_Note__c` | Text | Agent | After review |
|
||
| `Id_Verification_Rejection_Message__c` | Text | Agent | If rejected |
|
||
|
||
### Status Values
|
||
|
||
| Status | Portal UI | Can Submit Order? |
|
||
| --------------- | --------------------------------------- | ----------------: |
|
||
| `Not Submitted` | Show upload form | No |
|
||
| `Submitted` | Show "Under Review" with submitted info | Yes |
|
||
| `Verified` | Show "Verified" badge | Yes |
|
||
| `Rejected` | Show rejection reason + upload form | No |
|
||
|
||
### Supported File Types
|
||
|
||
- PDF
|
||
- PNG
|
||
- JPG/JPEG
|
||
|
||
## Portal UI Locations
|
||
|
||
| Location | What's Shown |
|
||
| ---------------------------------------------- | -------------------------------------------------------------- |
|
||
| `/account/settings` | Profile, Address, ID Verification (with upload) |
|
||
| `/account/services/internet` | Eligibility status and eligible plans |
|
||
| `/account/services/internet/request-submitted` | Immediate confirmation after submitting an eligibility request |
|
||
| Subscription detail | Service-specific actions (cancel, etc.) |
|
||
|
||
## Cancellation Flow
|
||
|
||
### Internet Cancellation
|
||
|
||
1. Customer navigates to subscription detail → clicks "Request Cancellation"
|
||
2. Portal creates Salesforce Case with WHMCS Service ID
|
||
3. Portal updates Opportunity with cancellation data:
|
||
- `ScheduledCancellationDateAndTime__c` = end of cancellation month
|
||
- `CancellationNotice__c` = "有" (received)
|
||
- `LineReturn__c` = "NotYet"
|
||
4. Agent processes Case:
|
||
- Terminates WHMCS service on scheduled date
|
||
- Updates `LineReturn__c` for equipment return tracking
|
||
- Updates Opportunity to "〇Cancelled"
|
||
|
||
**Note:** WHMCS service termination is manual (agent work). The portal updates Salesforce, but does not automatically terminate in WHMCS.
|
||
|
||
### SIM Cancellation
|
||
|
||
1. Customer navigates to subscription detail → SIM Management → Cancel
|
||
2. Portal calls Freebit PA02-04 cancellation API
|
||
3. Service is scheduled for cancellation at end of selected month
|
||
|
||
## Opportunity ↔ WHMCS Linking
|
||
|
||
### How They're Connected
|
||
|
||
After order provisioning, the Opportunity is linked to WHMCS via:
|
||
|
||
```
|
||
Opportunity.WHMCS_Service_ID__c = WHMCS Service ID (e.g., 456)
|
||
```
|
||
|
||
### Provisioning Flow
|
||
|
||
1. Order placed → Opportunity created (Stage = "Post Processing")
|
||
2. Order approved → Fulfillment runs
|
||
3. WHMCS `AddOrder` API called → returns `serviceIds`
|
||
4. Opportunity updated:
|
||
- `WHMCS_Service_ID__c` = service ID from WHMCS
|
||
- `StageName` = "Active"
|
||
|
||
### Finding Opportunity for Cancellation
|
||
|
||
When customer requests cancellation, the portal:
|
||
|
||
1. Takes WHMCS subscription ID from the portal
|
||
2. Queries Salesforce: `WHERE WHMCS_Service_ID__c = {subscriptionId}`
|
||
3. Updates the found Opportunity with cancellation data
|
||
|
||
### If Opportunity is Cancelled but WHMCS is Not
|
||
|
||
This can happen if the agent doesn't complete the WHMCS termination. Result:
|
||
|
||
- Customer continues to be billed (WHMCS active)
|
||
- Service remains active (not terminated)
|
||
- Salesforce says cancelled, WHMCS says active
|
||
|
||
**Prevention:** Agent must follow Case instructions to terminate WHMCS service on the scheduled date.
|
||
|
||
## Customer Profile Data
|
||
|
||
### Data Sources
|
||
|
||
| Field | Source | Editable in Portal? |
|
||
| --------------- | ---------------------------- | ------------------- |
|
||
| Email | Portal DB / WHMCS | Yes |
|
||
| Phone Number | WHMCS | Yes |
|
||
| First Name | WHMCS | No (read-only) |
|
||
| Last Name | WHMCS | No (read-only) |
|
||
| Customer Number | WHMCS Custom Field (ID: 198) | No (read-only) |
|
||
| Date of Birth | WHMCS Custom Field (ID: 201) | No (read-only) |
|
||
| Gender | WHMCS Custom Field (ID: 200) | No (read-only) |
|
||
| Address | WHMCS | Yes |
|
||
|
||
### Environment Variables
|
||
|
||
```bash
|
||
# WHMCS custom field IDs (must match your WHMCS installation)
|
||
WHMCS_CUSTOMER_NUMBER_FIELD_ID=198 # Default
|
||
WHMCS_DOB_FIELD_ID=201 # Default
|
||
WHMCS_GENDER_FIELD_ID=200 # Default
|
||
```
|
||
|
||
If customer number, DOB, or gender aren't showing, verify these field IDs match your WHMCS custom fields.
|