Assist_Design/docs/PORTAL-DATA-MODEL.md
T. Narantuya 94e1625b78 order fix
2025-08-27 10:54:05 +09:00

29 KiB
Raw Blame History

Portal Data Model & Mappings

This document consolidates all required/used fields across Salesforce and WHMCS, plus how the portal consumes them.

Quick Reference: Required Fields Summary

Product2 (7 core + service-specific fields)

Core: SKU__c, Product2Categories1__c, Portal_Catalog__c, Portal_Accessible__c, Item_Class__c, Billing_Cycle__c, WH_Product_ID__c, WH_Product_Name__c
Internet: Internet_Plan_Tier__c, Internet_Offering_Type__c, Internet_Monthly_Price__c, Internet_Display_Order__c
SIM: SIM_Data_Size__c, SIM_Plan_Type__c, SIM_Has_Family_Discount__c
VPN: VPN_Display_Order__c

Order (6 core + service-specific independent fields)

Core: AccountId, EffectiveDate, Status, Pricebook2Id, Order_Type__c
Activation: Activation_Type__c, Activation_Scheduled_At__c, Activation_Status__c
Internet: Internet_Plan_Tier__c, Installation_Type__c, Weekend_Install__c, Access_Mode__c, Hikari_Denwa__c
VPN: VPN_Region__c
SIM: SIM_Type__c, EID__c, SIM_Voice_Mail__c, SIM_Call_Waiting__c + MNP fields
WHMCS: WHMCS_Order_ID__c

OrderItem (2 core + 2 integration fields)

Core: OrderId, PricebookEntryId, Quantity, UnitPrice
WHMCS: WHMCS_Service_ID__c, Billing_Cycle__c

Order with Add-ons Example

When a customer orders "Internet Gold + Hikari Denwa + Weekend Installation":

-- Order Header
Order_Type__c: "Internet"
Internet_Plan_Tier__c: "Gold"
Installation_Type__c: "Single"
Weekend_Install__c: true  -- Synced from add-on OrderItem

-- OrderItems (5 separate items)
1. Internet Gold Service         SKU: "INTERNET-GOLD"               WH: 188 (monthly)
2. Internet Installation         SKU: "INTERNET-INSTALL-SINGLE"     WH: 242 (one-time)
3. Weekend Installation Fee      SKU: "INTERNET-INSTALL-WEEKEND"    WH: 245 (one-time ¥3000)
4. Hikari Denwa Service         SKU: "INTERNET-ADDON-HOME-PHONE"    WH: 246 (monthly ¥450)
5. Hikari Denwa Installation    SKU: "INTERNET-ADDON-DENWA-INSTALL"  WH: 247 (one-time)

Complete Product Structure Needed:

-- Main Services (Portal_Visible = true)
"Internet Gold Plan"            Item_Class: "Service"     Monthly billing
"Single Installation"           Item_Class: "Installation"     One-time billing

-- Add-on Services (Portal_Visible = false, shown as checkboxes)
"Hikari Denwa (Home Phone)"     Item_Class: "Add-on"      Monthly billing
"Weekend Installation"          Item_Class: "Add-on"      One-time billing  
"Hikari Denwa Installation"     Item_Class: "Add-on"      One-time billing (auto-added when Denwa selected)

Key Points:

  • 5 OrderItems total - each service/fee is separate
  • Automatic dependencies - selecting Hikari Denwa auto-adds its installation fee
  • Mixed billing cycles - services are monthly, installations are one-time
  • Independent WHMCS products - each OrderItem maps to different WHMCS Product ID

Object inventory (what's standard vs custom)

  • Salesforce standard

    • Product2 (catalog)
    • Pricebook2 / PricebookEntry (pricing)
    • Order (header)
    • OrderItem (line)
    • Account (customer profile and eligibility)
  • WHMCS

    • Use native User, Client, Order, Invoice, Product (Service). No custom tables.

Salesforce fields (by object)

Account (eligibility and mapping)

  • Eligibility (used for personalized Internet catalog)

    • Internet_Eligibility__c (Picklist)
      • Values (Label = API Name):
        • Home 1G
        • Home 10G
        • Apartment 1G
        • Apartment 100M
      • Default behavior: if the field is missing/blank/invalid, the portal treats eligibility as Home 1G.
    • Environment variable mapping (so code doesnt hardcode field API names):
      • ELIGIBILITY_INTERNET_FIELD (default: Internet_Eligibility__c)
  • Mapping key

    • SF_Account_No__c (Text) used to link portal user ↔ Account (via WHMCS link/signup)

Product2 (clean field structure)

Core Fields (Required for all products)

StockKeepingUnit          Text(255)        -- Product identifier (standard Salesforce field)
Product2Categories1__c    Picklist         -- "Internet", "SIM", "VPN", "Other"  
Portal_Catalog__c         Checkbox         -- Show in main catalog (GET /catalog)
Portal_Accessible__c      Checkbox         -- Can be used in orders/OrderItems
Item_Class__c             Picklist         -- "Service", "Installation", "Add-on", "Activation"
Billing_Cycle__c          Picklist         -- "Monthly", "Onetime"
WH_Product_ID__c          Number(18,0)     -- WHMCS Product ID (operator can change on OrderItem)
WH_Product_Name__c        Text(255)       -- WHMCS Product Name for reference

Internet Product Fields

Internet_Plan_Tier__c     Picklist         -- "Silver", "Gold", "Platinum"
Internet_Offering_Type__c Picklist         -- "Home 1G", "Home 10G", "Apartment 1G", "Apartment 100M"
     -- UI sorting (1, 2, 3)

Pricing (from PricebookEntry)

-- Pricing comes from PricebookEntry.UnitPrice where Pricebook2Id = '01sTL000008eLVlYAM' (Portal Price Book)
-- Portal Price Book ID is configurable via PORTAL_PRICEBOOK_ID environment variable
UnitPrice                 Currency         -- Display price (¥4800, ¥4900, ¥5300)

SIM Product Fields

SIM_Data_Size__c          Text(50)         -- "5GB", "10GB", "25GB", "30GB", "50GB", "Voice-Only"
SIM_Plan_Type__c          Picklist         -- "DataOnly", "DataSmsVoice", "VoiceOnly" (only for Service items)
SIM_Has_Family_Discount__c Checkbox        -- Family discount eligibility

Note: Display order is determined by data size, plan type, and offering type - no separate display order fields needed.

VPN Product Fields

     -- UI sorting

Note: VPN type is typically "Remote Access" for all portal products, no separate field needed.

Add-on Products

Add-ons are separate products that customers can select alongside main services. They use the existing product structure with Item_Class__c = "Add-on", Portal_Catalog__c = false (hidden from catalog), and Portal_Accessible__c = true (can be ordered).

How Add-ons Work:

  1. Customer Selection: Optional add-ons appear as checkboxes (e.g., Hikari Denwa)
  2. Frontend Logic: Auto-add dependencies (e.g., Hikari Denwa adds installation fee)
  3. Salesforce Logic: Auto-detect conditions and add OrderItems (e.g., weekend installation dates)
  4. Order Creation: Each selected/detected add-on creates a separate OrderItem
  5. Provisioning: Each add-on provisions as separate WHMCS product
  6. Billing: Add-ons have their own pricing and billing cycles

Internet Add-ons:

  • Weekend Installation: Salesforce auto-adds (¥3000) - INTERNET-INSTALL-WEEKEND (when installation date is weekend)
  • Hikari Denwa Service: Customer checkbox (¥450/month) - INTERNET-ADDON-HOME-PHONE
  • Hikari Denwa Installation: Frontend auto-adds (one-time) - INTERNET-ADDON-DENWA-INSTALL

SIM Add-ons:

  • Voice Mail: Monthly service - SIM-ADDON-VOICE-MAIL
  • Call Waiting: Monthly service - SIM-ADDON-CALL-WAITING
  • Unlimited Calling: Monthly service - SIM-ADDON-UNLIMITED-CALLING

Product Structure Examples:

-- Main Service Plans (Portal_Catalog = true, Portal_Accessible = true)
"Internet Silver Plan"  SKU: "INTERNET-SILVER"  WH_Product_ID__c: 184
"Internet Gold Plan"  SKU: "INTERNET-GOLD"  WH_Product_ID__c: 188 (default, operator can change)
"Internet Platinum Plan"  SKU: "INTERNET-PLATINUM"  WH_Product_ID__c: 183 (default, operator can change)

-- Installation Options (Portal_Catalog = true, Portal_Accessible = true)
"Single Installation"  SKU: "INTERNET-INSTALL-SINGLE"  WH_Product_ID__c: 242
"12-Month Installation"  SKU: "INTERNET-INSTALL-12M"  WH_Product_ID__c: 243
"24-Month Installation"  SKU: "INTERNET-INSTALL-24M"  WH_Product_ID__c: 244

-- Add-on Services (Portal_Catalog = false, Portal_Accessible = true)
"Weekend Installation"  SKU: "INTERNET-INSTALL-WEEKEND"  WH_Product_ID__c: 245
"Hikari Denwa (Home Phone)"  SKU: "INTERNET-ADDON-HOME-PHONE"  WH_Product_ID__c: 246
"Hikari Denwa Installation"  SKU: "INTERNET-ADDON-DENWA-INSTALL"  WH_Product_ID__c: 247

-- Customer sees clear messaging:
Silver: Standard pricing, customer configures access mode
Gold: Premium pricing, operator reviews and may adjust configuration  
Platinum: Premium pricing + additional fees, operator reviews and may adjust configuration

Order (clean field structure)

Core Fields (Required for all orders)

-- Salesforce Standard Fields
AccountId                 Lookup(Account)  -- Customer account
EffectiveDate            Date             -- Order date
Status                   Picklist         -- "Pending Review", "Approved", "Completed", "Cancelled"
Pricebook2Id             Lookup(Pricebook2) -- Portal pricebook
OpportunityId            Lookup(Opportunity) -- Optional, created by BFF

-- Order Classification
Order_Type__c            Picklist         -- "Internet", "SIM", "VPN", "Other"

Activation Fields (All order types)

Activation_Type__c       Picklist         -- "Immediate", "Scheduled"
Activation_Scheduled_At__c Datetime       -- When Status = Scheduled
Activation_Status__c     Picklist         -- "Not Started", "Activating", "Activated", "Failed"

Internet Order Fields (Independent fields synced with OrderItems)

-- Customer/Operator Selections (Independent fields)
Internet_Plan_Tier__c       Picklist         -- "Silver", "Gold", "Platinum" (syncs with OrderItems)
Installation_Type__c        Picklist         -- "Single", "12-Month", "24-Month" (syncs with OrderItems)
Weekend_Install__c          Checkbox         -- Weekend installation add-on (syncs with OrderItems)
Access_Mode__c              Picklist         -- "IPoE-BYOR", "IPoE-HGW", "PPPoE" (operator configures)

-- Add-on Selections (Customer choices, syncs with OrderItems)
Hikari_Denwa__c             Checkbox         -- Customer selected Hikari Denwa service

VPN Order Fields (Customer selections)

-- Customer Selections
VPN_Region__c            Picklist         -- "USA-SF", "UK-London" (customer chooses region)

SIM Order Fields (Customer choices + MNP data)

-- SIM Configuration (plan type and data size come from selected Product2)
SIM_Type__c              Picklist         -- "eSIM", "Physical SIM" (customer choice)
EID__c                   Text(255)        -- Required when SIM_Type__c = "eSIM"

-- Add-on Selections (Customer choices, syncs with OrderItems)
SIM_Voice_Mail__c        Checkbox         -- Customer selected Voice Mail add-on
SIM_Call_Waiting__c      Checkbox         -- Customer selected Call Waiting add-on


-- MNP/Porting (when MNP_Application__c = true)
MNP_Application__c       Checkbox         -- Customer wants to port number
MNP_Reservation_Number__c Text(10)        -- 10 digits numeric
MNP_Expiry_Date__c       Date             -- MNP expiry date
MNP_Phone_Number__c      Text(11)         -- 11 digits, no hyphens
MVNO_Account_Number__c   Text(255)        -- Optional
Porting_LastName__c      Text(255)        -- Kanji/Alphabet
Porting_FirstName__c     Text(255)        -- Kanji/Alphabet  
Porting_LastName_Katakana__c Text(255)    -- Katakana
Porting_FirstName_Katakana__c Text(255)   -- Katakana
Porting_Gender__c        Picklist         -- "Male", "Female", "Corporate/Other"
Porting_DateOfBirth__c   Date             -- YYYY/MM/DD

WHMCS Integration Fields

WHMCS_Order_ID__c        Number(18,0)     -- Set after provisioning

Billing/Shipping Snapshot (Set on create, not synced)

-- Billing Address
BillToContactId          Lookup(Contact)
BillToStreet             Text(255)
BillToCity               Text(40)
BillToState              Text(80)
BillToPostalCode         Text(20)
BillToCountry            Text(80)

-- Shipping Address  
ShipToContactId          Lookup(Contact)
ShipToStreet             Text(255)
ShipToCity               Text(40)
ShipToState              Text(80)
ShipToPostalCode         Text(20)
ShipToCountry            Text(80)

OrderItem (clean field structure)

Core Fields (Required for all order items)

-- Salesforce Standard Fields
OrderId                  Lookup(Order)    -- Parent order
PricebookEntryId         Lookup(PricebookEntry) -- Product + pricing
Quantity                 Number(18,2)     -- Usually 1
UnitPrice                Currency         -- Price at time of order

WHMCS Integration Fields

-- Provisioning
WHMCS_Service_ID__c      Number(18,0)     -- Set after provisioning
Billing_Cycle__c         Picklist         -- "Monthly", "Annually", "One-time"

Note: WH_Product_ID__c is stored on Product2, but operator can override it on OrderItem during review for Gold/Platinum plans.

Salesforce Setup Checklist

Custom Fields to Create

Product2 Object

-- Core Fields (All Products)
StockKeepingUnit          Text(255)        External ID, Unique (standard Salesforce field)
Product2Categories1__c    Picklist         Values: Internet, SIM, VPN, Other
Portal_Catalog__c         Checkbox         Default: false
Portal_Accessible__c      Checkbox         Default: true
Item_Class__c             Picklist         Values: Service, Installation, Add-on, Activation
WH_Product_ID__c          Number(18,0)     

-- Internet Fields
Internet_Plan_Tier__c     Picklist         Values: Silver, Gold, Platinum
Internet_Offering_Type__c Picklist         Values: Home 1G, Home 10G, Apartment 1G, Apartment 100M
Internet_Monthly_Price__c Currency         
     

-- SIM Fields
SIM_Data_Size__c          Text(50)         
SIM_Plan_Type__c          Picklist         Values: DataOnly, DataSmsVoice, VoiceOnly
SIM_Has_Family_Discount__c Checkbox        Default: false     

-- VPN Fields
     

Order Object

-- Core Fields
Order_Type__c             Picklist         Values: Internet, SIM, VPN, Other

-- Activation Fields
Activation_Type__c        Picklist         Values: Immediate, Scheduled
Activation_Scheduled_At__c Datetime        
Activation_Status__c      Picklist         Values: Not Started, Activating, Activated, Failed

-- Internet Fields (Independent fields synced with OrderItems)
Internet_Plan_Tier__c     Picklist         Values: Silver, Gold, Platinum
Installation_Type__c      Picklist         Values: Single, 12-Month, 24-Month
Weekend_Install__c        Checkbox         Weekend installation add-on
Access_Mode__c            Picklist         Values: IPoE-BYOR, IPoE-HGW, PPPoE (operator sets)

-- VPN Fields (Independent fields)
VPN_Region__c             Picklist         Values: USA-SF, UK-London (customer chooses)

-- SIM Fields (Customer choices only - plan details come from Product2)
SIM_Type__c               Picklist         Values: eSIM, Physical SIM (customer chooses format)
EID__c                    Text(255)        Required for eSIM activation        

-- MNP Fields (when applicable)
MNP_Application__c        Checkbox         
MNP_Reservation_Number__c Text(10)         
MNP_Expiry_Date__c        Date             
MNP_Phone_Number__c       Text(11)         
MVNO_Account_Number__c    Text(255)        
Porting_LastName__c       Text(255)        
Porting_FirstName__c      Text(255)        
Porting_LastName_Katakana__c Text(255)     
Porting_FirstName_Katakana__c Text(255)    
Porting_Gender__c         Picklist         Values: Male, Female, Corporate/Other
Porting_DateOfBirth__c    Date             

-- WHMCS Integration
WHMCS_Order_ID__c         Number(18,0)     

    

OrderItem Object

-- WHMCS Integration Fields
WHMCS_Service_ID__c       Number(18,0)     Set after provisioning
Billing_Cycle__c          Picklist         Values: Monthly, Annually, One-time

Account Object

-- Portal Integration Fields
Internet_Eligibility__c   Picklist         Values: Home 1G, Home 10G, Apartment 1G, Apartment 100M
SF_Account_No__c          Text(255)        External ID, Unique (Customer Number)

Salesforce Sync Flow: Order Fields ↔ OrderItems

Overview

Independent fields on Order are synced with OrderItems using Salesforce Flow. When operators change Order fields, Flow automatically adds/removes/updates OrderItems. When OrderItems change, Flow updates Order fields.

Weekend Installation Auto-Detection

// Trigger: After Insert, After Update on Order
// When: Installation_Scheduled_Date__c changes

Date installDate = order.Installation_Scheduled_Date__c;
String dayOfWeek = installDate.format('E'); // 'Sat' or 'Sun' for weekends

if (dayOfWeek == 'Sat' || dayOfWeek == 'Sun') {
    // Add weekend installation fee if not exists
    List<OrderItem> existing = [SELECT Id FROM OrderItem 
                               WHERE OrderId = :order.Id 
                               AND Product2.SKU__c = 'INTERNET-INSTALL-WEEKEND'];
    
    if (existing.isEmpty()) {
        Product2 product = [SELECT Id FROM Product2 WHERE SKU__c = 'INTERNET-INSTALL-WEEKEND'];
        PricebookEntry pbe = [SELECT Id, UnitPrice FROM PricebookEntry 
                             WHERE Product2Id = :product.Id AND Pricebook2.Name = 'Portal'];
        
        INSERT new OrderItem(
            OrderId = order.Id,
            PricebookEntryId = pbe.Id,
            Quantity = 1,
            UnitPrice = pbe.UnitPrice
        );
        
        order.Weekend_Install__c = true;
        UPDATE order;
    }
} else {
    // Remove weekend fee if date changed to weekday
    DELETE [SELECT Id FROM OrderItem WHERE OrderId = :order.Id 
            AND Product2.SKU__c = 'INTERNET-INSTALL-WEEKEND'];
    order.Weekend_Install__c = false;
    UPDATE order;
}

Flow 1: Order Fields → OrderItems (When operator changes Order fields)

Internet Plan Tier Change

// Trigger: After Update on Order
// When: Internet_Plan_Tier__c changes

// 1. Remove old Internet service OrderItem
DELETE [SELECT Id FROM OrderItem 
        WHERE OrderId = :order.Id 
        AND Product2.Product2Categories1__c = 'Internet' 
        AND Product2.Item_Class__c = 'Service'];

// 2. Add new Internet service OrderItem
String newSku = 'INTERNET-' + order.Internet_Plan_Tier__c.toUpperCase();
Product2 newProduct = [SELECT Id FROM Product2 WHERE SKU__c = :newSku LIMIT 1];
PricebookEntry pbe = [SELECT Id, UnitPrice FROM PricebookEntry 
                      WHERE Product2Id = :newProduct.Id AND Pricebook2.Name = 'Portal' LIMIT 1];

OrderItem newItem = new OrderItem(
    OrderId = order.Id,
    PricebookEntryId = pbe.Id,
    Quantity = 1,
    UnitPrice = pbe.UnitPrice
);
INSERT newItem;

Installation Type Change

// When: Installation_Type__c changes

// 1. Remove old installation OrderItem
DELETE [SELECT Id FROM OrderItem 
        WHERE OrderId = :order.Id 
        AND Product2.Product2Categories1__c = 'Internet' 
        AND Product2.Item_Class__c = 'Install'];

// 2. Add new installation OrderItem if not null
if (order.Installation_Type__c != null) {
    String installSku = 'INTERNET-INSTALL-' + 
        (order.Installation_Type__c == 'Single' ? 'SINGLE' : 
         order.Installation_Type__c == '12-Month' ? '12M' : '24M');
    
    // Create new installation OrderItem with installSku
}

Weekend Install Toggle

// When: Weekend_Install__c changes

if (order.Weekend_Install__c == true && oldOrder.Weekend_Install__c == false) {
    // Add weekend installation OrderItem
    // SKU: 'INTERNET-INSTALL-WEEKEND'
} else if (order.Weekend_Install__c == false && oldOrder.Weekend_Install__c == true) {
    // Remove weekend installation OrderItem
    DELETE [SELECT Id FROM OrderItem 
            WHERE OrderId = :order.Id 
            AND Product2.SKU__c = 'INTERNET-INSTALL-WEEKEND'];
}

Add-on Field Changes

// When: Hikari_Denwa__c changes
if (order.Hikari_Denwa__c == true && oldOrder.Hikari_Denwa__c == false) {
    // Add Hikari Denwa service and installation OrderItems
    INSERT new OrderItem(Product2.SKU__c = 'INTERNET-ADDON-HOME-PHONE');
    INSERT new OrderItem(Product2.SKU__c = 'INTERNET-ADDON-DENWA-INSTALL');
} else if (order.Hikari_Denwa__c == false && oldOrder.Hikari_Denwa__c == true) {
    // Remove Hikari Denwa OrderItems
    DELETE [SELECT Id FROM OrderItem WHERE OrderId = :order.Id 
            AND Product2.SKU__c IN ('INTERNET-ADDON-HOME-PHONE', 'INTERNET-ADDON-DENWA-INSTALL')];
}

// When: SIM add-on fields change
if (order.SIM_Voice_Mail__c != oldOrder.SIM_Voice_Mail__c) {
    if (order.SIM_Voice_Mail__c) {
        INSERT new OrderItem(Product2.SKU__c = 'SIM-ADDON-VOICE-MAIL');
    } else {
        DELETE [SELECT Id FROM OrderItem WHERE OrderId = :order.Id 
                AND Product2.SKU__c = 'SIM-ADDON-VOICE-MAIL'];
    }
}

// Similar logic for SIM_Call_Waiting__c

Flow 2: OrderItems → Order Fields (When OrderItems change)

Sync Order Fields from OrderItems

// Trigger: After Insert, After Update, After Delete on OrderItem
// Purpose: Keep Order fields in sync with OrderItems

// Get all OrderItems for this Order
List<OrderItem> items = [SELECT Product2.Internet_Plan_Tier__c, Product2.SKU__c,
                                Product2.Item_Class__c, Product2.Product2Categories1__c
                         FROM OrderItem WHERE OrderId = :orderId];

Order orderToUpdate = new Order(Id = orderId);

// Sync Internet fields
for (OrderItem item : items) {
    if (item.Product2.Product2Categories1__c == 'Internet' && item.Product2.Item_Class__c == 'Service') {
        orderToUpdate.Internet_Plan_Tier__c = item.Product2.Internet_Plan_Tier__c;
    }
    if (item.Product2.Product2Categories1__c == 'Internet' && item.Product2.Item_Class__c == 'Installation') {
        if (item.Product2.SKU__c.contains('SINGLE')) orderToUpdate.Installation_Type__c = 'Single';
        else if (item.Product2.SKU__c.contains('12M')) orderToUpdate.Installation_Type__c = '12-Month';
        else if (item.Product2.SKU__c.contains('24M')) orderToUpdate.Installation_Type__c = '24-Month';
    }
    if (item.Product2.SKU__c == 'INTERNET-INSTALL-WEEKEND') {
        orderToUpdate.Weekend_Install__c = true;
    }
    if (item.Product2.SKU__c == 'INTERNET-ADDON-HOME-PHONE') {
        orderToUpdate.Hikari_Denwa__c = true;
    }
    
    // SIM add-on sync
    if (item.Product2.SKU__c == 'SIM-ADDON-VOICE-MAIL') {
        orderToUpdate.SIM_Voice_Mail__c = true;
    }
    if (item.Product2.SKU__c == 'SIM-ADDON-CALL-WAITING') {
        orderToUpdate.SIM_Call_Waiting__c = true;
    }

    
    // VPN fields: Only VPN_Region__c is stored on Order (customer selection)
}

// Set defaults if no items found
if (noInternetService) orderToUpdate.Internet_Plan_Tier__c = null;
if (noInstallation) orderToUpdate.Installation_Type__c = null;
if (noWeekendInstall) orderToUpdate.Weekend_Install__c = false;
if (noHikariDenwa) orderToUpdate.Hikari_Denwa__c = false;
if (noSIMVoiceMail) orderToUpdate.SIM_Voice_Mail__c = false;
if (noSIMCallWaiting) orderToUpdate.SIM_Call_Waiting__c = false;


UPDATE orderToUpdate;

WHMCS fields/IDs used

  • Users & Clients (created/linked at signup)

    • User: firstname, lastname, email, password
    • Client: firstname, lastname, email, optional phonenumber, companyname
    • Address: address1, address2, city, state, postcode, country
    • Custom field: CustomerNumber (maps to Salesforce Account SF_Account_No__c)
    • Link: User ↔ Client recorded in portal mapping table
  • Invoices & PayMethods

    • GetInvoices (by clientid) surfaced in portal
    • GetPayMethods used to gate checkout (must have a method on file)
    • SSO links used to open invoice/payment-methods UI in WHMCS
  • Client linking in portal

    • Portal mapping stores: userId, whmcsClientId, sfAccountId
  • Product IDs (pid) used in AddOrder:

    • Internet (by dwelling/speed): Home 1G SILV=181, GOLD=182, PLAT=183; APT 1G SILV=184, GOLD=185, PLAT=186; APT 100M SILV=187, GOLD=188, PLAT=189
    • Installation: Single=242, 12M=243, 24M=244
    • VPN: USA=33, UK=54, Activation=37
    • SIM/eSIM: see mapping table above (e.g., Data-only 5GB=97, Data+Voice 10GB=216, Voice-only=142)

AddOrder request fields (reference)

  • clientid (Number) required resolved from Order.AccountId via portal mapping to WHMCS client
  • pid[] (Array) required service and install Product2 → WH_Product_ID__c
  • billingcycle (derived) sent to WHMCS based on the SKU type (Onetime for activation/install SKUs; Monthly for service SKUs)
  • promocode (Text) optional
  • notes (Text) should include sfOrderId=<Salesforce Order Id> (templated via Product2.WHMCS_Notes_Template__c)
  • noinvoice (Boolean) optional
  • noemail (Boolean) optional

Catalog requirements

  • Pricebook: create a Portal price book; ensure active PricebookEntry for each visible Product2
  • API dependencies: GET /catalog queries Product2 fields: Id, Name, SKU__c, Product2Categories1__c, Portal_Catalog__c, Portal_Accessible__c
  • Personalized catalog: GET /catalog/personalized (planned)
    • Filters by consolidated offering: include Product2 where Portal_Internet_Offering_Type__c equals Account.Internet_Eligibility__c (fallback to Home 1G when Account field missing/invalid)

Enablement & permissions (Salesforce)

  • Enable Products and Price Books in the org (Setup → Product Settings)
  • Integration user (Named Credential/Connected App user) minimum permissions:
    • Objects (Read): Product2, Pricebook2, PricebookEntry, Order, OrderItem, Account
    • Fields (Readable):
      • Product2.SKU__c, Product2.Portal_Catalog__c, Product2.Portal_Accessible__c, Product2.Product2Categories1__c
      • Optional display: Product2.Portal_Description__c, Product2.Portal_Feature_Bullets__c, Product2.Portal_Hero_Image_URL__c, Product2.Portal_Tags__c, Product2.Portal_Sort_Order__c, Product2.Portal_Valid_From__c, Product2.Portal_Valid_Until__c
      • Optional eligibility: Product2.Portal_Eligibility_Dwelling__c, Product2.Portal_Eligibility_Speed__c, Product2.Portal_Eligibility_Region__c
    • Account eligibility fields per env: dwelling/speed
    • Order custom fields listed above (Type/Activation/Internet/SIM/MNP)
    • OrderItem custom fields: ConfigOptions_JSON__c

Portal field mapping reference (source-of-truth → target)

Activation (Portal → Salesforce)

  • activationType (Immediate | Scheduled) → Order.Activation_Type__c
  • activationScheduledAt (Datetime) → Order.Activation_Scheduled_At__c

Address (Portal → WHMCS/Order snapshot)

  • streetWHMCS.Client.address1; Order.BillToStreet
  • addressLine2WHMCS.Client.address2
  • cityWHMCS.Client.city; Order.BillToCity
  • stateWHMCS.Client.state; Order.BillToState
  • postalCodeWHMCS.Client.postcode; Order.BillToPostalCode
  • country (ISO 2) → WHMCS.Client.country; Order.BillToCountry

Checkout (Portal → Salesforce/WHMCS)

  • billingCycle (UI concept only) → derived server-side from SKU class; WHMCS billingcycle
  • productSKU (Text) → Product2.SKU__c (PBE lookup)
  • promoCode (Text) → WHMCS promocode
  • quantity (Number) → OrderItem.Quantity (validated against Product2.Portal_Max_Quantity__c)

Internet (Portal → Salesforce)

  • accessMode (IPoEHGW | IPoEBYOR | PPPoE) → Order.Access_Mode__c
  • installmentPlan (One-time | 12-Month | 24-Month) → Order.Installment_Plan__c
  • planTier (Platinum | Gold | Silver) → Order.Internet_Plan_Tier__c (derived from SKU)
  • serviceSpeed (Text) → Order.Service_Speed__c
  • weekendInstall (Checkbox) → Order.Weekend_Install__c
  • internetOffering (Picklist) → Order.Internet_Offering_Type__c (defaults from Account when not provided)
    • Also set from product on selection: Order.Internet_Offering_Type__c = Product2.Portal_Internet_Offering_Type__c

VPN (Portal → Salesforce)

  • vpnRegion (Picklist) → Order.VPN_Region__c
  • (optional) vpnType (Picklist) → Order.VPN_Type__c

SIM / eSIM (Portal → Salesforce)

  • simType (eSIM | Physical SIM) → Order.SIM_Type__c
  • eid (Text) → Order.EID__c (required when SIM_Type__c = eSIM)
  • Porting (all optional unless flow requires):
    • mnpApplicationOrder.MNP_Application__c
    • mnpReservationNumberOrder.MNP_Reservation_Number__c
    • mnpExpiryDateOrder.MNP_Expiry_Date__c
    • mnpPhoneNumberOrder.MNP_Phone_Number__c
    • mvnoAccountNumberOrder.MVNO_Account_Number__c
    • portingDobOrder.Porting_DateOfBirth__c
    • portingFirstNameKanjiOrder.Porting_FirstName_Kanji__c
    • portingLastNameKanjiOrder.Porting_LastName_Kanji__c
    • portingFirstNameKatakanaOrder.Porting_FirstName_Katakana__c
    • portingLastNameKatakanaOrder.Porting_LastName_Katakana__c
    • portingGender (Male | Female | Corporate/Other) → Order.Porting_Gender__c

Signup (Portal → WHMCS; plus SF mapping)

  • email, firstName, lastName, password → WHMCS User + Client
  • companyWHMCS.Client.companyname (optional)
  • phoneWHMCS.Client.phonenumber (optional)
  • customerNumber (Salesforce Account number) → WHMCS.Client.customfields.CustomerNumber → BFF links to Salesforce Account.SF_Account_No__c

Notes

  • BFF resolves pricing by Product2.SKU__cPricebookEntry and provisioning by Product2.WH_Product_ID__c → WHMCS pid[]
  • Use SIM as the sole Product2 category for both eSIM and Physical SIM; Order_Type__c retains SIM vs eSIM
  • All Product2 visible in portal must have SKU__c, Portal_Catalog__c = true, and a PricebookEntry