# Portal – Data Model & Mappings This document lists the objects, custom fields, and mappings used across Salesforce, WHMCS, and the Portal BFF. ## Object inventory (what's standard vs custom) - Salesforce standard objects - `Product2` (catalog) - `Pricebook2` / `PricebookEntry` (pricing) - `Order` (header) - `OrderItem` (line) - Salesforce custom fields - Added on `Product2`, `Order`, and `OrderItem` only (listed below with proposed API names). - WHMCS - Use native User (login identity), Client (billing profile), Order, Invoice, and Service (Product/Service) entities and API parameters. We do not create custom tables in WHMCS. ## Salesforce ### Product2 (catalog source of truth) - Visibility & display - `Portal_Visible__c` (Checkbox) - `Portal_Category__c` (Picklist: Internet | eSIM | VPN | Other) - `Portal_Description__c` (Long Text) - `Portal_Feature_Bullets__c` (Long Text) - `Portal_Hero_Image_URL__c` (URL) - `Portal_Tags__c` (Text) - `Portal_Sort_Order__c` (Number) - `Portal_Valid_From__c` (Date) - `Portal_Valid_Until__c` (Date) - Eligibility (Internet) - `Portal_Eligibility_Dwelling__c` (Picklist: Home | Apartment | Any) - `Portal_Eligibility_Tier__c` (Picklist: 1G | 100Mb | Any) - `Portal_Eligibility_Region__c` (Text) - Terms & options - `Portal_Billing_Cycle__c` (Picklist) - `Portal_Max_Quantity__c` (Number) - `Portal_Requires_Payment_Method__c` (Checkbox) - (Avoid using configurable options for pricing; see Replica Product Strategy below) - WHMCS mapping - `WHMCS_Product_Id__c` (Number) - `WHMCS_Notes_Template__c` (Long Text) - `eSIM_Settings_JSON__c` (Long Text) ### PricebookEntry - Use a dedicated “Portal” pricebook; ensure entries exist for all visible Product2 records ### Order (header) - Required - `AccountId` - `EffectiveDate` - `Status` (Pending Review) - `Order_Type__c` (Picklist: Internet | eSIM | SIM | VPN | Other) - Billing/Shipping snapshot (set on create; no ongoing sync) - `BillToContactId` (Lookup Contact) - `BillToStreet` - `BillToCity` - `BillToState` - `BillToPostalCode` - `BillToCountry` - `ShipToContactId` (Lookup Contact) - `ShipToStreet` - `ShipToCity` - `ShipToState` - `ShipToPostalCode` - `ShipToCountry` - Service configuration (since one Order = one service) - Source category → `Order_Type__c` is auto-set from `Product2.Portal_Category__c` of the main service SKU at checkout. - eSIM/SIM - `SIM_Type__c` (Picklist: Physical SIM | eSIM) - `EID__c` (Text; masked; required when SIM_Type\_\_c = eSIM) - MNP (port-in) - `MNP_Application__c` (Checkbox) - `MNP_Reservation_Number__c` (Text, 10) - `MNP_Expiry_Date__c` (Date) - `MNP_Phone_Number__c` (Text, 11) - `Porting_LastName_Kanji__c` (Text) - `Porting_FirstName_Kanji__c` (Text) - `Porting_LastName_Katakana__c` (Text) - `Porting_FirstName_Katakana__c` (Text) - `Porting_Gender__c` (Picklist: Male | Female | Corporate/Other) - `Porting_DateOfBirth__c` (Date) - `MVNO_Account_Number__c` (Text) - Internet (service line config) - `Internet_Plan_Tier__c` (Picklist: Platinum_Gold | Silver) - `Access_Mode__c` (Picklist: IPoE‑HGW | IPoE‑BYOR | PPPoE) - `Service_Speed__c` (Text, e.g., "1Gbps") - Installation (separate line derived from these) - `Installment_Plan__c` (Picklist: One‑time | 12‑Month | 24‑Month) - `Installment_Months__c` (Number: 0 | 12 | 24) - `Weekend_Install__c` (Checkbox) - Provisioning & results - `Activation_Status__c` (Not Started | Activating | Activated | Failed) - `Activation_Type__c` (Picklist: Immediate | Scheduled) - `Activation_Scheduled_At__c` (Date/Time; required when Activation_Type\_\_c = Scheduled) - `Activation_Error_Code__c` (Text) - `Activation_Error_Message__c` (Text) - `WHMCS_Order_ID__c` (Text/Number) - `Last_Activation_At__c` (Datetime) - `Activation_Attempt_Count__c` (Number) ### OrderItem (line) - Standard - `OrderId` - `Product2Id` - `PricebookEntryId` - `Quantity` - `UnitPrice` - Custom - `Billing_Cycle__c` (Picklist) - `ConfigOptions_JSON__c` (Long Text) (optional; not used for pricing) - `Item_Type__c` (Picklist: Service | Installation | Add‑on) Notes - Since one Order represents one service, all service configuration fields live on the Order header. OrderItems are generated from the header: - Item_Type = Service: Product2 = main service SKU; Billing_Cycle\_\_c typically Monthly. - Item_Type = Installation: Product2 = installation SKU selected from `Installment_Plan__c`/`Weekend_Install__c`; Billing_Cycle\_\_c = Onetime or Monthly (for installments). - Item_Type = Add‑on (e.g., Hikari Denwa): separate OrderItem with its own Product2. ## WHMCS ### Users & Clients (created on signup) - Create WHMCS User (User-level identity and login) - `firstname` ← portal signup `firstName` - `lastname` ← portal signup `lastName` - `email` ← portal signup `email` - `password` ← portal signup `password` - Create WHMCS Client (billing profile) - `firstname` ← portal signup `firstName` - `lastname` ← portal signup `lastName` - `email` ← portal signup `email` - `phonenumber?` ← portal signup `phone?` - `companyname?` ← portal signup `company?` - Link User ↔ Client - `user_id` ← created User id - `client_id` ← created Client id - Set Client address - `address1` ← portal address `street` - `address2` ← portal address `addressLine2` - `city` ← portal address `city` - `state` ← portal address `state` - `postcode` ← portal address `postalCode` - `country` (ISO 2-letter) ← portal address `country` - Set Client custom field - `CustomerNumber` (id/name to confirm) ← Salesforce Account Customer Number (provided via SF Number) - Payment methods - Managed in WHMCS UI; portal uses SSO and checks via `GetPayMethods`; no PAN stored in portal ### Orders & provisioning - Replica Product Strategy (preferred) - Each sellable SKU is its own Product2 and WHMCS product (e.g., Internet Platinum vs Silver, IPoE‑HGW vs BYOR, Installment plan variants, Hikari Denwa, etc.). - Pricing and terms come from the chosen product; we avoid config option–based pricing. - AddOrder (parameters used) - `clientid` ← portal mapping `sfAccountId` → `whmcsClientId` - `pid[]` ← for each OrderItem (Service/Installation/Add‑on) `Product2.WHMCS_Product_Id__c` - `billingcycle` ← OrderItem `Billing_Cycle__c` - `promocode?` ← Salesforce `Order.Promo_Code__c` or line-level - `notes` ← include `sfOrderId=` - `noinvoice?` ← typically `0` - `noemail?` ← typically `0` - (Gateway) We do not pass `paymentmethod`; WHMCS uses the client's default gateway/payment method on file. - AcceptOrder (no body fields; runs against created order) - Results → Salesforce - `orderid` → `Order.WHMCS_Order_ID__c` ### Invoices & pay methods - GetInvoices (surface in portal) - `clientid` ← portal mapping `whmcsClientId` - filters as needed (date/status) - GetPayMethods (gate checkout) - `clientid` ← portal mapping `whmcsClientId` - SSO links (open WHMCS UI) - invoice view/pay/download, payment methods screen ## Portal BFF - Mappings table - `userId`, `whmcsClientId`, `sfAccountId`, timestamps - Orchestration record (internal) - `sfOrderId`, `status`, `items/config`, `whmcsOrderId?`, `whmcsServiceIds?`, idempotency keys, timestamps ## Mappings Summary - Order header → WHMCS - `sfOrderId` goes into WHMCS `notes` for idempotency tracing - `AccountId` resolves to `clientid` via mapping table - OrderItem line → WHMCS - `Product2.WHMCS_Product_Id__c` → `pid[]` - `OrderItem.Billing_Cycle__c` → `billingcycle` - Identity/porting fields (EID, MNP, MVNO, etc.) live on Order and are used only for activation API, not stored in WHMCS - Price mapping: Product2 encodes plan tier/access mode/apt type in the SKU; we select the corresponding `PricebookEntry` in the Portal pricebook. - Post-provisioning write-back - `WHMCS_Order_ID__c` on Order; `WHMCS_Service_ID__c` on each OrderItem ## Business Rules (data implications) - Home Internet address - Billing address equals service address; no separate service address fields in portal. - Snapshot billing to Order BillTo\* at checkout; do not sync ongoing changes to Salesforce. - Single Internet per account - Enforced in BFF: before creating an Order with Internet Product2, check WHMCS `GetClientsProducts` for existing Internet services (active/pending/suspended). - Optional SF guardrail: validation/Flow prevents OrderItem with Internet Product2 when account already has an Internet service (based on WHMCS write-backs or nightly sync). - One fulfillment type per Order - BFF groups cart items by fulfillment type and creates separate Orders (e.g., one for eSIM, one for Home Internet) so Order-level activation fields remain consistent.