2025-12-22 18:59:38 +09:00
|
|
|
# Opportunity Lifecycle Management Guide
|
|
|
|
|
|
|
|
|
|
This guide documents the Salesforce Opportunity integration for service lifecycle tracking.
|
|
|
|
|
|
|
|
|
|
## Table of Contents
|
|
|
|
|
|
|
|
|
|
1. [Overview](#overview)
|
|
|
|
|
2. [Existing Field Architecture](#existing-field-architecture)
|
|
|
|
|
3. [Opportunity Matching Rules](#opportunity-matching-rules)
|
|
|
|
|
4. [Internet Eligibility Flow](#internet-eligibility-flow)
|
|
|
|
|
5. [ID Verification Flow](#id-verification-flow)
|
|
|
|
|
6. [Order Placement Flow](#order-placement-flow)
|
|
|
|
|
7. [Service Activation Flow](#service-activation-flow)
|
|
|
|
|
8. [Cancellation Flow](#cancellation-flow)
|
|
|
|
|
9. [Implementation Checklist](#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 │
|
2025-12-23 17:53:08 +09:00
|
|
|
│ └─ Portal: POST /api/verification/residence-card │
|
|
|
|
|
│ └─ BFF uploads file to Salesforce Files (ContentVersion) │
|
2025-12-22 18:59:38 +09:00
|
|
|
│ │
|
|
|
|
|
│ 3. UPDATE ACCOUNT │
|
2025-12-23 17:53:08 +09:00
|
|
|
│ └─ Id_Verification_Status__c = "Submitted" (portal maps to pending) │
|
2025-12-22 18:59:38 +09:00
|
|
|
│ └─ Id_Verification_Submitted_Date_Time__c = now() │
|
|
|
|
|
│ │
|
2025-12-23 17:53:08 +09:00
|
|
|
│ 4. CS REVIEWS IN SALESFORCE │
|
|
|
|
|
│ └─ Id_Verification_Status__c = "Verified" or "Rejected" │
|
|
|
|
|
│ └─ Id_Verification_Verified_Date_Time__c = now() (on verify) │
|
|
|
|
|
│ └─ Id_Verification_Rejection_Message__c = reason (on reject) │
|
2025-12-22 18:59:38 +09:00
|
|
|
│ │
|
2025-12-23 17:53:08 +09:00
|
|
|
│ 5. CUSTOMER RESUBMITS IF NEEDED │
|
|
|
|
|
│ └─ Portal shows feedback + upload UI │
|
2025-12-22 18:59:38 +09:00
|
|
|
│ │
|
|
|
|
|
└─────────────────────────────────────────────────────────────────────────┘
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 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 │
|
2025-12-23 16:44:45 +09:00
|
|
|
│ └─ WHMCS Service.OpportunityId → Opportunity (optional; helpful for ops/debugging) │
|
2025-12-22 18:59:38 +09:00
|
|
|
│ │
|
|
|
|
|
│ 5. CUSTOMER SEES SERVICE PAGE │
|
2025-12-23 16:44:45 +09:00
|
|
|
│ └─ Portal shows active services from WHMCS; lifecycle/cancellation tracking lives on the linked Salesforce Opportunity (via WHMCS_Service_ID__c) │
|
2025-12-22 18:59:38 +09:00
|
|
|
│ │
|
|
|
|
|
└─────────────────────────────────────────────────────────────────────────┘
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 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):**
|
|
|
|
|
|
|
|
|
|
- [x] Opportunity Stage picklist
|
|
|
|
|
- [x] CommodityType field
|
|
|
|
|
- [x] Application_Stage\_\_c
|
|
|
|
|
- [x] CancellationNotice\_\_c
|
|
|
|
|
- [x] LineReturn\_\_c
|
|
|
|
|
- [x] ScheduledCancellationDateAndTime\_\_c
|
|
|
|
|
- [x] Account Internet eligibility fields
|
|
|
|
|
- [x] Account ID verification fields
|
|
|
|
|
- [x] Case.OpportunityId (standard lookup)
|
|
|
|
|
- [x] Order.OpportunityId (standard lookup)
|
|
|
|
|
|
2025-12-23 16:44:45 +09:00
|
|
|
**Opportunity Fields Required (Portal writes these):**
|
2025-12-22 18:59:38 +09:00
|
|
|
|
2025-12-23 16:44:45 +09:00
|
|
|
- [ ] `Portal_Source__c` picklist (used to track how the Opportunity was created)
|
|
|
|
|
- [ ] `WHMCS_Service_ID__c` number field (used to link WHMCS service → Salesforce Opportunity for cancellations)
|
2025-12-22 18:59:38 +09:00
|
|
|
|
|
|
|
|
### WHMCS Admin Tasks
|
|
|
|
|
|
2025-12-23 16:44:45 +09:00
|
|
|
- [ ] Create an `OpportunityId` custom field on Services/Hosting (optional but recommended for ops/debugging)
|
|
|
|
|
- [ ] Confirm whether your WHMCS expects `customfields[]` keys by **name** (`OpportunityId`) or by **numeric field id**, and configure accordingly
|
2025-12-22 18:59:38 +09:00
|
|
|
|
|
|
|
|
### BFF Development Tasks
|
|
|
|
|
|
|
|
|
|
**Completed:**
|
|
|
|
|
|
|
|
|
|
- [x] Domain types in `packages/domain/opportunity/`
|
|
|
|
|
- [x] Field map configuration
|
|
|
|
|
- [x] `SalesforceOpportunityService`
|
|
|
|
|
- [x] Cancellation deadline helpers (25th rule)
|
2025-12-23 16:44:45 +09:00
|
|
|
- [x] Eligibility request creates/reuses Opportunity (Stage `Introduction`) and links Case (`Case.OpportunityId`)
|
|
|
|
|
- [x] Order placement reuses Opportunity in `Introduction`/`Ready` (otherwise creates new `Post Processing`)
|
|
|
|
|
- [x] Fulfillment passes `OpportunityId` to WHMCS and links `WHMCS_Service_ID__c` back to the Opportunity
|
|
|
|
|
- [x] Cancellation Case creation + Opportunity cancellation field updates (Internet cancellations)
|
2025-12-22 18:59:38 +09:00
|
|
|
|
2025-12-23 16:44:45 +09:00
|
|
|
**Optional / Future:**
|
2025-12-22 18:59:38 +09:00
|
|
|
|
2025-12-23 16:44:45 +09:00
|
|
|
- [ ] Read `OpportunityId` back from WHMCS service custom fields (portal currently relies on Salesforce `WHMCS_Service_ID__c` for linking)
|
2025-12-22 18:59:38 +09:00
|
|
|
|
|
|
|
|
### Frontend Tasks
|
|
|
|
|
|
|
|
|
|
- [ ] Order tracking page (from Salesforce Order)
|
|
|
|
|
- [ ] Service page with cancellation status
|
2025-12-23 16:44:45 +09:00
|
|
|
- [x] Cancellation forms (Internet + SIM) with 25th deadline logic
|
2025-12-22 18:59:38 +09:00
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Related Documentation
|
|
|
|
|
|
|
|
|
|
- [Salesforce-WHMCS Mapping](./SALESFORCE-WHMCS-MAPPING-REFERENCE.md)
|
|
|
|
|
- [Order Provisioning](../orders/PORTAL-ORDERING-PROVISIONING.md)
|