- Refactored the SignupWorkflowService to throw a DomainHttpException for legacy account conflicts, improving error handling. - Updated the SignupForm component to include initialEmail and showFooterLinks props, enhancing user experience during account creation. - Improved the AccountStep in the SignupForm to allow users to add optional details, such as date of birth and gender, for a more personalized signup process. - Enhanced the PasswordStep to include terms acceptance and marketing consent options, ensuring compliance and user engagement. - Updated various catalog views to improve layout and user guidance, streamlining the onboarding process for new users.
33 KiB
33 KiB
Opportunity Lifecycle Management Guide
This guide documents the Salesforce Opportunity integration for service lifecycle tracking.
Table of Contents
- Overview
- Existing Field Architecture
- Opportunity Matching Rules
- Internet Eligibility Flow
- ID Verification Flow
- Order Placement Flow
- Service Activation Flow
- Cancellation Flow
- Implementation Checklist
Overview
What Customers See vs What's Internal
┌─────────────────────────────────────────────────────────────────────────┐
│ INTERNAL ONLY (Sales/CS Pipeline) │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ Opportunity Stages: Introduction, Ready (before Order placed) │
│ Application Stages: INTRO-1, UNRESPONSIVE-1, etc. (CS workflow) │
│ Eligibility fields on Account (eligibility status) │
│ ID Verification fields on Account (verification status) │
│ │
│ These are for internal tracking - customer sees results, not fields. │
│ │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ CUSTOMER-FACING (Portal) │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ 1. ELIGIBILITY STATUS (from Account field) │
│ └─ "Checking...", "Eligible", "Not Eligible" │
│ │
│ 2. ID VERIFICATION STATUS (from Account field) │
│ └─ "Pending", "Verified", "Rejected" │
│ │
│ 3. ORDER TRACKING (from Salesforce Order) │
│ └─ After order placed, before WHMCS activates │
│ │
│ 4. SERVICE PAGE (from WHMCS) │
│ └─ After service is active │
│ │
│ 5. CANCELLATION STATUS (from Opportunity) │
│ └─ End date, return deadline, kit status │
│ │
└─────────────────────────────────────────────────────────────────────────┘
Existing Field Architecture
Account Fields (Already Exist)
Internet Eligibility Fields:
| Field | API Name | Purpose |
|---|---|---|
| Eligibility Value | Internet_Eligibility__c |
The actual eligibility result |
| Status | Internet_Eligibility_Status__c |
Pending, Checked |
| Requested At | Internet_Eligibility_Request_Date_Time__c |
When request was made |
| Checked At | Internet_Eligibility_Checked_Date_Time__c |
When eligibility was checked |
| Notes | Internet_Eligibility_Notes__c |
Agent notes |
| Case ID | Internet_Eligibility_Case_Id__c |
Linked Case for request |
ID Verification Fields:
| Field | API Name | Purpose |
|---|---|---|
| Status | Id_Verification_Status__c |
Pending, Verified, Rejected |
| Submitted At | Id_Verification_Submitted_Date_Time__c |
When submitted |
| Verified At | Id_Verification_Verified_Date_Time__c |
When verified |
| Notes | Id_Verification_Note__c |
Agent notes |
| Rejection Message | Id_Verification_Rejection_Message__c |
Reason for rejection |
Opportunity Fields (Existing)
| Field | API Name | Purpose |
|---|---|---|
| Stage | StageName |
Introduction, Ready, Post Processing, Active, △Cancelling, etc. |
| Commodity Type | CommodityType |
Personal SonixNet Home Internet, SIM, VPN |
| Application Stage | Application_Stage__c |
INTRO-1 (for portal) |
| Cancellation Notice | CancellationNotice__c |
有, 未, 不要, 移転 |
| Scheduled Cancellation | ScheduledCancellationDateAndTime__c |
End of cancellation month |
| Line Return Status | LineReturn__c |
NotYet, SentKit, Returned, etc. |
New Opportunity Fields (To Create)
| Field | API Name | Type | Purpose |
|---|---|---|---|
| Portal Source | Portal_Source__c |
Picklist | How Opportunity was created |
| WHMCS Service ID | WHMCS_Service_ID__c |
Number | Link to WHMCS after provisioning |
Order Fields (Existing)
| Field | API Name | Purpose |
|---|---|---|
| Opportunity | OpportunityId |
Links Order TO Opportunity |
Case Fields (Existing)
| Field | API Name | Purpose |
|---|---|---|
| Opportunity | OpportunityId |
Links Case TO Opportunity |
Key Principle: Cases and Orders link TO Opportunity, not vice versa.
Opportunity Matching Rules
When to Find vs Create Opportunity
┌─────────────────────────────────────────────────────────────────────────┐
│ OPPORTUNITY MATCHING RULES │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ INTERNET ELIGIBILITY REQUEST: │
│ ───────────────────────────── │
│ 1. Check if Account already has eligibility status set │
│ └─ If already "Eligible" or "Not Eligible" → Don't create Opp │
│ │
│ 2. Find existing Opportunity: │
│ └─ WHERE AccountId = ? │
│ AND CommodityType IN ('Personal SonixNet Home Internet', │
│ 'Corporate SonixNet Home Internet') │
│ AND StageName = 'Introduction' │
│ AND IsClosed = false │
│ │
│ 3. If found → Use existing, create Case linked to it │
│ If not → Create new Opportunity, then create Case linked to it │
│ │
│ ORDER PLACEMENT: │
│ ───────────────── │
│ 1. Find existing Opportunity: │
│ └─ WHERE AccountId = ? │
│ AND CommodityType = ? (based on order type) │
│ AND StageName IN ('Introduction', 'Ready') │
│ AND IsClosed = false │
│ │
│ 2. If found → Use existing, update stage to 'Post Processing' │
│ If not → Create new Opportunity with stage 'Post Processing' │
│ │
│ 3. Create Order with Order.OpportunityId = Opportunity.Id │
│ │
└─────────────────────────────────────────────────────────────────────────┘
Stage Matching by Flow
| Flow | Match Stages | If Not Found |
|---|---|---|
| Internet Eligibility | Introduction only | Create with Introduction |
| Order Placement | Introduction, Ready | Create with Post Processing |
| Provisioning | Post Processing | Error (should exist from order) |
| Cancellation | Active | Error (service must be active) |
Internet Eligibility Flow
Complete Flow Diagram
┌─────────────────────────────────────────────────────────────────────────┐
│ INTERNET ELIGIBILITY FLOW │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ 1. CUSTOMER ENTERS ADDRESS │
│ └─ Portal: POST /api/catalog/internet/eligibility-request │
│ │
│ 2. CHECK IF ELIGIBILITY ALREADY KNOWN │
│ └─ Query: SELECT Internet_Eligibility__c FROM Account │
│ └─ If already set → Return cached result, no action needed │
│ │
│ 3. FIND OR CREATE OPPORTUNITY │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ Query: │ │
│ │ SELECT Id FROM Opportunity │ │
│ │ WHERE AccountId = ? │ │
│ │ AND CommodityType IN ('Personal SonixNet Home Internet', │ │
│ │ 'Corporate SonixNet Home Internet') │ │
│ │ AND StageName = 'Introduction' │ │
│ │ AND IsClosed = false │ │
│ │ │ │
│ │ If found → Use existing │ │
│ │ If not → Create new: │ │
│ │ - Stage: Introduction │ │
│ │ - CommodityType: Personal SonixNet Home Internet │ │
│ │ - Portal_Source__c: Portal - Internet Eligibility Request │ │
│ │ - Application_Stage__c: INTRO-1 │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
│ 4. CREATE CASE (linked to Opportunity) │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ Case.Type = "Eligibility Check" │ │
│ │ Case.AccountId = customer's account │ │
│ │ Case.OpportunityId = opportunity from step 3 ←── THE LINK │ │
│ │ Case.Subject = "Internet Eligibility - {Address}" │ │
│ │ Case.Description = address details, postal code, etc. │ │
│ │ Case.Status = "New" │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
│ 5. UPDATE ACCOUNT │
│ └─ Internet_Eligibility_Status__c = "Pending" │
│ └─ Internet_Eligibility_Request_Date_Time__c = now() │
│ └─ Internet_Eligibility_Case_Id__c = Case.Id │
│ │
│ 6. CS PROCESSES CASE │
│ └─ Checks with NTT / provider │
│ └─ Updates Account: │
│ - Internet_Eligibility__c = result │
│ - Internet_Eligibility_Status__c = "Checked" │
│ - Internet_Eligibility_Checked_Date_Time__c = now() │
│ └─ Updates Opportunity: │
│ - Eligible → Stage: Ready │
│ - Not Eligible → Stage: Void │
│ │
│ 7. PORTAL DETECTS CHANGE (via CDC or polling) │
│ └─ Shows eligibility result to customer │
│ │
└─────────────────────────────────────────────────────────────────────────┘
What Customer Sees
| Account Field State | Portal Shows |
|---|---|
| Status = null | Address input form |
| Status = "Pending" | "Checking your address..." spinner |
| Eligibility = eligible value | Plan selection enabled |
| Eligibility = not eligible | "Sorry, service not available" message |
ID Verification Flow
Complete Flow Diagram
┌─────────────────────────────────────────────────────────────────────────┐
│ ID VERIFICATION (eKYC) FLOW │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ WHEN: During checkout registration or before order placement │
│ │
│ 1. CHECK IF ALREADY VERIFIED │
│ └─ Query: SELECT Id_Verification_Status__c FROM Account │
│ └─ If "Verified" → Skip verification, proceed to checkout │
│ │
│ 2. CUSTOMER UPLOADS ID DOCUMENTS │
│ └─ Portal: POST /api/verification/submit │
│ └─ eKYC service processes documents │
│ │
│ 3. UPDATE ACCOUNT │
│ └─ Id_Verification_Status__c = "Pending" │
│ └─ Id_Verification_Submitted_Date_Time__c = now() │
│ │
│ 4. IF eKYC AUTO-APPROVED │
│ └─ Id_Verification_Status__c = "Verified" │
│ └─ Id_Verification_Verified_Date_Time__c = now() │
│ └─ Customer can proceed to order immediately │
│ │
│ 5. IF MANUAL REVIEW NEEDED │
│ └─ Create Case for CS review │
│ └─ Case.Type = "ID Verification" │
│ └─ Case.OpportunityId = linked Opportunity (if exists) │
│ └─ CS reviews and updates Account │
│ │
│ 6. IF REJECTED │
│ └─ Id_Verification_Status__c = "Rejected" │
│ └─ Id_Verification_Rejection_Message__c = reason │
│ └─ Customer must resubmit │
│ │
└─────────────────────────────────────────────────────────────────────────┘
What Customer Sees
| Account Field State | Portal Shows |
|---|---|
| Status = null | ID upload form |
| Status = "Pending" | "Verifying your identity..." |
| Status = "Verified" | Proceed to checkout enabled |
| Status = "Rejected" | Error message + resubmit option |
Order Placement Flow
┌─────────────────────────────────────────────────────────────────────────┐
│ ORDER PLACEMENT FLOW │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ PREREQUISITES: │
│ - Internet: Eligibility = Eligible (Account field) │
│ - SIM: ID Verification = Verified (Account field) │
│ │
│ 1. CUSTOMER SUBMITS ORDER │
│ └─ Portal: POST /api/orders │
│ │
│ 2. FIND OR CREATE OPPORTUNITY │
│ └─ Query for existing (Introduction or Ready stage) │
│ └─ If found → Use existing │
│ └─ If not → Create with stage 'Post Processing' │
│ │
│ 3. CREATE SALESFORCE ORDER │
│ └─ Order.OpportunityId = Opportunity.Id ←── THE LINK │
│ └─ Order.Status = "Pending Review" │
│ │
│ 4. UPDATE OPPORTUNITY │
│ └─ Stage = "Post Processing" │
│ │
│ 5. CUSTOMER SEES ORDER TRACKING │
│ └─ "Your order is being processed" │
│ │
└─────────────────────────────────────────────────────────────────────────┘
Service Activation Flow
┌─────────────────────────────────────────────────────────────────────────┐
│ SERVICE ACTIVATION FLOW │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ 1. AGENT APPROVES ORDER │
│ └─ Order.Status = "Approved" (triggers CDC) │
│ │
│ 2. BFF PROVISIONS TO WHMCS │
│ └─ Calls WHMCS AddOrder API │
│ └─ Passes OpportunityId as custom field ←── WHMCS GETS OPP ID │
│ └─ WHMCS returns serviceId │
│ │
│ 3. UPDATE OPPORTUNITY │
│ └─ WHMCS_Service_ID__c = serviceId ←── OPP GETS WHMCS ID │
│ └─ Stage = "Active" │
│ │
│ 4. BIDIRECTIONAL LINK COMPLETE │
│ └─ Opportunity.WHMCS_Service_ID__c → WHMCS Service │
│ └─ WHMCS Service.OpportunityId → Opportunity │
│ │
│ 5. CUSTOMER SEES SERVICE PAGE │
│ └─ Portal queries WHMCS → gets OpportunityId → queries Opp │
│ │
└─────────────────────────────────────────────────────────────────────────┘
Cancellation Flow
Always Create Case
For every cancellation request, create a Case (notification to CS):
┌─────────────────────────────────────────────────────────────────────────┐
│ CANCELLATION FLOW │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ 1. CUSTOMER SUBMITS CANCELLATION FORM │
│ └─ Selects month (25th rule applies) │
│ └─ Enters comments, alternative email (optional) │
│ │
│ 2. CREATE CANCELLATION CASE │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ Case.Type = "Cancellation Request" │ │
│ │ Case.AccountId = customer's account │ │
│ │ Case.Subject = "Cancellation Request - {Product}" │ │
│ │ Case.Description = ALL form data: │ │
│ │ - WHMCS Service ID │ │
│ │ - Cancellation month │ │
│ │ - Alternative email (if provided) │ │
│ │ - Customer comments (if provided) │ │
│ │ Case.OpportunityId = linked Opportunity (if found) │ │
│ │ Case.Status = "New" │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
│ 3. IF OPPORTUNITY IS LINKED (via WHMCS_Service_ID__c) │
│ └─ Update Opportunity: │
│ - Stage = "△Cancelling" │
│ - ScheduledCancellationDateAndTime__c = end of month │
│ - CancellationNotice__c = "有" │
│ - LineReturn__c = "NotYet" │
│ │
│ 4. IF NOT LINKED (Legacy) │
│ └─ Case contains all info for CS to process │
│ └─ CS will manually find and update correct Opportunity │
│ │
│ 5. CUSTOMER SEES │
│ └─ If linked: Cancellation status from Opportunity │
│ └─ If not linked: "Request received, we'll confirm by email" │
│ │
└─────────────────────────────────────────────────────────────────────────┘
The 25th Rule
TODAY'S DATE AVAILABLE CANCELLATION MONTHS
─────────────────────────────────────────────────────────
Before 25th of month → Can select THIS month or later
On/After 25th → Must select NEXT month or later
Cancellation Data Location
| Data | Where It Goes | Why |
|---|---|---|
| Scheduled date | Opportunity | Lifecycle tracking |
| Notice status | Opportunity | Lifecycle tracking |
| Return status | Opportunity | Lifecycle tracking |
| Customer comments | Case | Not needed on Opp |
| Alternative email | Case | Not needed on Opp |
| WHMCS Service ID | Case (for reference) | Helps CS identify service |
Implementation Checklist
Salesforce Admin Tasks
Existing Fields (No Changes):
- Opportunity Stage picklist
- CommodityType field
- Application_Stage__c
- CancellationNotice__c
- LineReturn__c
- ScheduledCancellationDateAndTime__c
- Account Internet eligibility fields
- Account ID verification fields
- Case.OpportunityId (standard lookup)
- Order.OpportunityId (standard lookup)
New Fields to Create on Opportunity:
Portal_Source__cpicklistWHMCS_Service_ID__cnumber field
WHMCS Admin Tasks
- Create
OpportunityIdcustom field on Services/Hosting - Document custom field ID for AddOrder API
BFF Development Tasks
Completed:
- Domain types in
packages/domain/opportunity/ - Field map configuration
SalesforceOpportunityService- Cancellation deadline helpers (25th rule)
Pending:
- Register services in Salesforce module
- Integrate Opportunity matching into eligibility flow
- Integrate Opportunity matching into order placement
- Update order provisioning to pass OpportunityId to WHMCS
- Update WHMCS mapper to read OpportunityId custom field
- Create cancellation Case service
- Integrate Case creation into cancellation flow
Frontend Tasks
- Order tracking page (from Salesforce Order)
- Service page with cancellation status
- Cancellation form with 25th deadline logic