47 lines
3.6 KiB
Markdown
47 lines
3.6 KiB
Markdown
|
|
# How the Portal Works (Overview)
|
|||
|
|
|
|||
|
|
Purpose: explain what the portal does, which systems own which data, and how freshness is managed.
|
|||
|
|
|
|||
|
|
## Core Pieces and Responsibilities
|
|||
|
|
|
|||
|
|
- Portal UI (Next.js) + BFF API (NestJS): handles all user traffic and calls external systems.
|
|||
|
|
- Postgres: stores portal users and the cross-system mapping `user_id ↔ whmcs_client_id ↔ sf_account_id`.
|
|||
|
|
- Redis cache: keeps short-lived copies of data to reduce load; keys are always scoped per user to avoid mixing data.
|
|||
|
|
- WHMCS: system of record for billing (clients, addresses, invoices, payment methods, subscriptions).
|
|||
|
|
- Salesforce: system of record for CRM (accounts/contacts), product catalog/pricebook, orders, and support cases.
|
|||
|
|
- Freebit: SIM provisioning only, used during mobile/SIM order fulfillment.
|
|||
|
|
|
|||
|
|
## High-Level Data Flows
|
|||
|
|
|
|||
|
|
- Sign-up: portal verifies the customer number in Salesforce → creates a WHMCS client (billing account) → stores the portal user + mapping → updates Salesforce with portal status + WHMCS ID.
|
|||
|
|
- Login/Linking: existing WHMCS users validate their WHMCS credentials; we create the portal user, map IDs, and mark the Salesforce account as portal-active.
|
|||
|
|
- Catalog & Checkout: products/prices come from the Salesforce portal pricebook; eligibility is checked per account; we require a WHMCS payment method before allowing checkout.
|
|||
|
|
- Orders: created in Salesforce with an address snapshot; Salesforce change events trigger fulfillment, which creates the matching WHMCS order and updates Salesforce statuses.
|
|||
|
|
- Billing: invoices, payment methods, and subscriptions are read from WHMCS; secure SSO links are generated for paying invoices inside WHMCS.
|
|||
|
|
- Support: cases are created/read directly in Salesforce with Origin = “Portal Website.”
|
|||
|
|
|
|||
|
|
## Data Ownership Cheat Sheet
|
|||
|
|
|
|||
|
|
- Identity & session: Portal DB (hashed passwords, no WHMCS/SF credentials stored).
|
|||
|
|
- Billing profile & addresses: WHMCS (authoritative); the portal writes changes back to WHMCS.
|
|||
|
|
- Orders & order status: Salesforce (source of truth); WHMCS receives the billing/provisioning copy during fulfillment.
|
|||
|
|
- Support cases: Salesforce (portal only filters to the account’s cases).
|
|||
|
|
|
|||
|
|
## Caching & Freshness (Redis)
|
|||
|
|
|
|||
|
|
- Catalog: event-driven (Salesforce CDC), no TTL; “volatile” bits use 60s TTL; eligibility per account is cached without TTL and invalidated on change.
|
|||
|
|
- Orders: event-driven (Salesforce CDC), no TTL; invalidated when Salesforce emits order/order-item changes or when we create/provision an order.
|
|||
|
|
- Invoices: list cached 90s; invoice detail cached 5m; invalidated by WHMCS webhooks and by write operations.
|
|||
|
|
- Subscriptions/services: list cached 5m; single subscription cached 10m; invalidated on WHMCS cache busts (webhooks or profile updates).
|
|||
|
|
- Payment methods: cached 15m; payment gateways list cached 1h.
|
|||
|
|
- WHMCS client profile: cached 30m; cleared after profile/address changes.
|
|||
|
|
- Signup account lookup (Salesforce customer number): cached 30s to keep the form responsive.
|
|||
|
|
- Support cases: read live from Salesforce (no cache).
|
|||
|
|
|
|||
|
|
## What Happens on Errors
|
|||
|
|
|
|||
|
|
- We prefer to fail safely with clear messages: for example, missing Customer Number, duplicate account, or missing payment method stops the action and tells the user what to fix.
|
|||
|
|
- If WHMCS or Salesforce is briefly unavailable, the portal surfaces a friendly “try again later” message rather than partial data.
|
|||
|
|
- Fulfillment writes error codes/messages back to Salesforce (e.g., missing payment method) so the team can see why a provision was paused.
|
|||
|
|
- Caches are cleared on writes and key webhooks so stale data is minimized; when cache access fails, we fall back to live reads.
|