Assist_Design/docs/PORTAL-ORDERING-PROVISIONING.md
T. Narantuya f305ee6e1a Implement Salesforce Platform Events for Order Provisioning
- Added support for Salesforce Platform Events, specifically subscribing to `OrderProvisionRequested__e` to trigger provisioning jobs.
- Introduced new environment variables for Salesforce event configuration, including SF_EVENTS_ENABLED, SF_PROVISION_EVENT_CHANNEL, and SF_PUBSUB_ENDPOINT.
- Refactored order fulfillment process to utilize event-driven architecture, enhancing reliability and scalability.
- Updated documentation to reflect changes in the provisioning workflow and environment variable requirements.
- Removed deprecated webhook handling code to streamline the integration.
2025-09-06 10:01:44 +09:00

463 lines
25 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Portal Ordering & Provisioning Complete Reference
*This document consolidates the complete ordering and provisioning specification, integrating architecture, flows, and implementation details.*
**Related Documents:**
- `ORDER-FULFILLMENT-COMPLETE-GUIDE.md` **Complete implementation guide with examples**
- `SALESFORCE-WHMCS-MAPPING-REFERENCE.md` **Comprehensive field mapping reference**
- `PORTAL-DATA-MODEL.md` Field mappings and data structures
- `PRODUCT-CATALOG-ARCHITECTURE.md` SKU architecture and catalog implementation
- `SALESFORCE-PRODUCTS.md` Complete product setup guide
> **📖 For complete implementation details, see `ORDER-FULFILLMENT-COMPLETE-GUIDE.md`**
- Backend: NestJS BFF (`apps/bff`) with existing integrations: WHMCS, Salesforce
- Frontend: Next.js portal (`apps/portal`)
- Billing: WHMCS (invoices, payment methods, subscriptions)
- Control plane: Salesforce (review/approval, provisioning trigger)
- Logging: centralized logger "dino" do not introduce alternate loggers
We require a Customer Number (SF Number) at signup and gate checkout on the presence of a WHMCS payment method. Orchestration runs in the BFF; Salesforce reviews and triggers provisioning.
## 0) Architecture at a Glance
- Source of truth
- Salesforce: Catalog (Product2 + PricebookEntry with portal fields), eligibility, order review/trigger, reporting
- WHMCS: Customer profile, payment methods, invoices, subscriptions (authoritative)
- Portal BFF: Orchestration + ID mappings (no customer data authority)
- Salesforce data model (three-object pattern)
- `Product2` (+ `PricebookEntry`) with portal fields (catalog + WHMCS mapping)
- `Order` (header; one per checkout)
- `OrderItem` (child; one per selected product) → references `Product2` (and PricebookEntry)
- Provisioning
- Operator approves in Salesforce → RecordTriggered Flow publishes Platform Event → BFF reads Order + OrderItems, dereferences `Product2` portal fields, calls WHMCS `AddOrder``AcceptOrder`, then writes back WHMCS IDs to Order/OrderItems
## 1) Customer Experience
1. Signup (Customer Number required)
- User provides: Email, Confirm Email, Password, Confirm Password, First/Last Name, optional Company/Phone, and Customer Number (SF Number).
- Portal validates and links to the existing Salesforce Account using the SF Number; if email differs, proceed and auto-create a Salesforce Case for CS (details in data model doc).
- WHMCS client is always created on signup (no pre-existing clients expected). WHMCS custom field for Customer Number must be set to the SF Number.
- Mapping is stored: `portalUserId ↔ whmcsClientId ↔ sfAccountId`.
2. Add payment method (required before checkout)
- Portal shows an “Add payment method” CTA that opens WHMCS payment methods via SSO (`POST /auth/sso-link``index.php?rp=/account/paymentmethods`).
- Portal checks `GET /billing/payment-methods/summary` to confirm presence before enabling checkout.
3. Browse catalog and configure
- `/catalog` lists products from BFF `GET /catalog` (reads Salesforce Product2 via BFF).
- Product detail pages collect configurable options; checkout button disabled until payment method exists.
4. Place order
- `POST /orders` creates a Salesforce Order (Pending Review) and stores orchestration state in BFF. Portal shows “Awaiting review”.
5. Review & Provision (operator in Salesforce)
- Recommended (async): Operator reviews/approves. A Record-Triggered Flow publishes Platform Event `OrderProvisionRequested__e`.
- BFF subscribes to the event and enqueues a provisioning job. Worker validates payment method, (for eSIM) calls activation API, then `AddOrder` and `AcceptOrder` in WHMCS, updates Salesforce Order fields/status.
- Legacy (webhook): previously called `POST /orders/{sfOrderId}/fulfill`. This path has been removed.
6. Completion
- Subscriptions and invoices appear in portal (`/subscriptions`, `/billing/invoices`). Pay via WHMCS SSO links.
## 1.1 Email Notifications
We will send operational emails at key events (no email validation step required at signup):
- Signup success: send Welcome email to customer; CC support.
- eSIM activation: send Activation email to customer; CC support.
- Order activated: send Activated/Next steps email to customer.
Implementation notes:
- Reuse centralized logger; no sensitive data in logs.
- Add a lightweight `EmailService` abstraction in BFF using existing modules style; queue via BullMQ jobs for reliability (Jobs module already present). Transport to be configured (SMTP/SendGrid) via env.
- Templates stored server-side; configurable CC list via env.
## 2) Backend Contracts (BFF)
### 2.1 Auth & Identity
- Modify `POST /auth/signup` (exists) to require `sfNumber: string` (Customer Number).
- Steps:
- Validate request; check portal user exists by email; if exists → error (prompt login/reset).
- Salesforce: find Account by Customer Number (SF Number). If not found → error.
- WHMCS: create client unconditionally for this flow. Set Customer Number custom field to SF Number.
- Create portal user and store mapping.
- Send Welcome email (to customer) with support on CC.
- If email mismatch is detected between inputs/systems (e.g., SF Account email vs signup email), automatically create a Salesforce Case to notify CS team and include both emails and Account reference.
- Security: sanitize errors; never log passwords; use centralized logger.
- `POST /auth/claim` (optional future): If we ever separate claim flow from signup.
### 2.2 Identity & Data Mapping (Portal ↔ Salesforce ↔ WHMCS)
- Systems of Record
- Salesforce: Catalog (Product2/PricebookEntry) and process control (Order approvals/status), account eligibility fields. Read-only from portal at runtime except Order creations/updates.
- WHMCS: Customer details, payment methods, invoices, subscriptions, provisioning outcomes. Source of truth for customer contact/billing data.
- Portal (BFF): Orchestration state and ID mappings only.
- Mapping Records (existing):
- `portalUserId ↔ whmcsClientId ↔ sfAccountId` stored in BFF mappings service.
- Customer Number (SF Number) is provided once at signup to create the mapping; we do not ask again.
- Portal User → Salesforce Account (lookup only)
- Authoritative lookup key: Customer Number on Account (provided via SF Number at signup).
- We do not sync profile/address changes from portal to Salesforce.
- Portal User → WHMCS Client (authoritative for customer profile)
- Email → `email`
- First/Last Name → `firstname`, `lastname`
- Company → `companyname` (optional)
- Phone → `phonenumber`
- Address: `address1`, `address2`, `city`, `state`, `postcode`, `country` (ISO 2-letter)
- Custom Field (Customer Number) → set to SF Number (id/name TBD; currently used in mapping)
- Notes (optional) → include correlation IDs / SF refs
- Discrepancy handling
- If SF Account email differs from signup email, proceed and auto-create a Salesforce Case for CS with both emails and Account reference (for review). No sync/write to SF.
### 2.3 Address Capture (WHMCS only)
- Capture Requirements
- Required: `street`, `city`, `state`, `postalCode`, `country`
- Optional: `addressLine2`, `buildingName`, `roomNumber`, `phone`
- Validation: client-side + server-side; normalize country to ISO code.
- UX Flow
- After signup, prompt to complete Address before catalog/checkout.
- Dashboard banner if address incomplete.
- API Usage
- Extend `PATCH /api/me/billing` to update WHMCS address fields only. No write to Salesforce.
- Centralized logging; redact PII.
### 2.4 Billing
- `GET /billing/payment-methods/summary` (new)
- Returns `{ hasPaymentMethod: boolean }` using WHMCS `GetPayMethods` for mapped client.
- `POST /auth/sso-link` (exists)
- Used to open WHMCS payment methods and invoice/pay pages.
### 2.5 Catalog (Salesforce Product2 as Source of Truth)
We will not expose WHMCS catalog directly. Instead, Salesforce `Product2` (with `PricebookEntry`) will be the catalog, augmented with a small set of custom fields used by the portal and BFF.
Custom fields on `Product2` (proposal; confirm API names):
- Identity & Display
- `Product2Categories1__c` (Picklist): Internet | SIM | 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_Catalog__c` (Checkbox, default false)
- `Portal_Valid_From__c` / `Portal_Valid_Until__c` (Date)
- Terms/Options
- `Portal_Billing_Cycle__c` (Picklist): Monthly | Onetime (default)
- `Portal_Max_Quantity__c` (Number, default 1)
- `Portal_Requires_Payment_Method__c` (Checkbox, default true)
- `Portal_ConfigOptions_JSON__c` (Long Text) defaults and allowed values
- Eligibility (Internet personalization)
- `Portal_Eligibility_Dwelling__c` (Picklist): Home | Apartment | Any
- `Portal_Eligibility_Tier__c` (Picklist): 1G | 100Mb | Any
- `Portal_Eligibility_Region__c` (Text) (optional)
- WHMCS Mapping
- `WHMCS_Product_Id__c` (Number)
- `WHMCS_Notes_Template__c` (Long Text)
- `eSIM_Settings_JSON__c` (Long Text)
Endpoints (BFF)
- `GET /catalog` (exists): return public offerings from `Product2` where `Portal_Catalog__c = true` and within validity dates; price via `PricebookEntry` for the portal pricebook.
- `GET /catalog/personalized` (new):
- Authenticated: infer `sfAccountId` from mapping. We only check the SF Number once during signup to create the mapping.
- Query `Product2` filtered by `Portal_Catalog__c` and validity, then apply eligibility filters using Account fields (e.g., dwelling/tier). eSIM/VPN are always included.
- Caching & Invalidation
- Cache global catalog 15m; cache personalized results per `sfAccountId` 5m.
- Optional Salesforce CDC/Platform Event to bust cache on `Product_Offering__c` changes.
### 2.6 Orders & Provisioning
- `POST /orders` (new)
- Body: `{ items: { productId, billingCycle, configOptions?, notes? }[], promoCode?, notes? }`
- Server-side checks: require WHMCS mapping; require `hasPaymentMethod=true`.
- Actions: Create Salesforce Order (Pending Review), persist orchestration record (sfOrderId, items/config, status=Pending Review, idempotency), return `{ sfOrderId, status }`.
- `GET /orders/:sfOrderId` (new)
- Returns orchestration status and relevant IDs; portal polls for updates.
- Async Provisioning (Platform Events)
- Event: `OrderProvisionRequested__e` with `{ OrderId__c, IdemKey__c?, CorrelationId__c? }`
- BFF autosubscribes when `SF_EVENTS_ENABLED=true`; enqueues provisioning job; returns 202 immediately (no inbound SF call).
- Worker performs the same steps as above and updates Salesforce.
## 3) Salesforce
### 3.1 Account matching
- Personalization Fields (Internet Eligibility)
- Use the Accounts serviceability/plan eligibility field(s) to decide which Internet product variants to show.
- Examples (to confirm API names and values):
- `Dwelling_Type__c`: `Home` | `Apartment`
- `Internet_Tier__c`: `1G` | `100Mb`
- The BFF personalization endpoint maps these to curated catalog SKUs.
- Customer Number (SF Number) is authoritative. Signup requires it. We find Account by that number.
- Mirror SF Number to WHMCS client custom field.
- If a discrepancy is found (e.g., Account has a different email than signup), create a Salesforce Case automatically with context so CS can triage; proceed with signup (no hard block), but flag the portal user for review.
### 3.2 Order fields
- Add the following fields to `Order`:
- `Activation_Status__c` (Pending Review, Activating, Provisioned, Failed)
- `WHMCS_Order_ID__c`
- Optional (if needed): `ESIM_ICCID__c`
#### 3.2.1 Salesforce Order API & Required Fields (to confirm)
- Object: `Order`
- Required fields for creation (proposal):
- `AccountId` (from SF Number lookup)
- `EffectiveDate` (today)
- `Status` (org-specific; code currently sets "Pending Review" — use your org's draft/review value)
- `Description` (optional: include product summary)
- Custom: `Activation_Status__c = Not Started`
- Optional link: `OpportunityId` (if created/available)
- On updates during provisioning:
- Set `Activation_Status__c` → Activating → Activated/Failed
- Store `WHMCS_Order_ID__c`
- For eSIM: masked `ESIM_ICCID__c`
#### 3.2.2 Order Line Representation (Salesforce-side, to confirm)
Options (pick one):
1. Use standard `OrderItem` with `Product2` and Pricebooks (recommended)
- Pros: native SF pricing and reporting; clean standard model
- Cons: maintain `Product2` and `PricebookEntry` for all offerings
- Fields per `OrderItem` (standard):
- `OrderId`, `Product2Id`, `PricebookEntryId`, `Quantity`, `UnitPrice`
- Custom fields to add on `OrderItem`:
- (Derived billing cycle from SKU class; no custom field)
- `ConfigOptions_JSON__c` (Long Text)
2. Custom child object `Order_Offering__c`
- Not used; we standardize on `OrderItem`.
Decision: Use standard `OrderItem` with `Product2` and portal fields for mapping.
We will build the BFF payload for WHMCS from these line records plus the Order header.
#### 3.2.3 Salesforce ↔ WHMCS Order Mapping
- Header mapping
- SF `Order.Id` → included in WHMCS `notes` as `sfOrderId=<Id>`
- SF `AccountId` → via portal mapping to `whmcsClientId``AddOrder.clientid`
- SF `Promo_Code__c` (if on header) → `AddOrder.promocode`
- SF `Activation_Status__c` controls operator flow; not sent to WHMCS
- Line mapping (per OrderItem)
- Product2 `WHMCS_Product_Id__c``AddOrder.pid[]`
- Derived billing cycle (Service=Monthly, Activation/Install=Onetime) → `AddOrder.billingcycle`
- SF `ConfigOptions_JSON__c``AddOrder.configoptions`
- Quantity → replicate product ID in `pid[]` or use config option/quantity if applicable
- After `AddOrder`:
- Call `AcceptOrder` to provision; capture `orderid` from response
- Update SF `WHMCS_Order_ID__c`; set `Activation_Status__c = Activated` on success
- On error, set `Activation_Status__c = Failed`
### 3.3 Flow (Provisioning Trigger)
- RecordTriggered Flow publishes `OrderProvisionRequested__e` on Order approval.
### 3.4 UI
### 3.5 Catalog → Order → Provisioning Linkage (Clean Mapping)
- Single source of mapping truth: Product2 portal fields
- `WHMCS_Product_Id__c`, `Portal_ConfigOptions_JSON__c`, and `Provisioning_Flow__c` live on Product2.
- Do not duplicate these fields on `OrderItem`; each line references Product2 and price from PricebookEntry.
- Snapshot only what can change over time: `UnitPrice` and `Quantity` on the line.
- Order construction (by portal at checkout)
- Create `Order` header with `Activation_Status__c = Not Started`.
- For each cart item, create a line (either `OrderItem` with custom fields or `Order_Offering__c`) that includes:
- `Product2Id` and `PricebookEntryId`
- `Quantity`, `UnitPrice__c`
- Item type is inferred from SKU class (Service vs Activation/Install); no custom field needed.
- Optional overrides in `ConfigOptions_JSON__c` (e.g., size, add-ons) based on user selection
- Provisioning (triggered from Salesforce)
- BFF receives `sfOrderId`, loads `Order` and its lines.
- For each line, dereference Product2 to fetch `WHMCS_Product_Id__c` and default config options, then merge with any line-level overrides in `ConfigOptions_JSON__c`.
- Build `AddOrder` payload using the mapping above; place `sfOrderId` in WHMCS `notes`.
- After `AcceptOrder`, write back:
- Header: `WHMCS_Order_ID__c`
- Header: `Activation_Status__c = Activated` on success
- Subscriptions linkage
- The authoritative subscription record lives in WHMCS.
This keeps the mapping clean and centralized in Product2 portal fields, while Orders/OrderItems act as a snapshot of the customers selection and price at time of checkout.
## 3.5 Flow Sanity Check
1. Catalog comes from Salesforce Product2 (filtered/personalized by Account eligibility).
2. Customer signs up with SF Number; portal creates WHMCS client and mapping; address/profile managed in WHMCS.
3. Checkout creates an SF `Order` and child lines (no provisioning yet).
4. Operator approves in SF; Flow publishes Platform Event.
5. BFF subscriber enqueues job and provisions: recheck payment method (WHMCS), handle eSIM activation if needed, then `AddOrder` + `AcceptOrder` in WHMCS using mappings from Product2 portal fields referenced by the OrderItems.
6. BFF updates SF Order fields (`WHMCS_Order_ID__c`, etc.) and status; emails are sent as required.
7. Customer sees completed order; subscriptions/invoices appear from WHMCS data in the portal.
- LWC on `Order` to display provisioning status, errors, WHMCS IDs, and a Retry button.
## 4) Frontend (Portal)
- Signup page: add `sfNumber` field; validation and error messages for missing/invalid SF Number.
- Payment banner: dashboard shows CTA to add a payment method if none.
- Catalog: `/catalog` page using existing BFF endpoint.
- Product detail + Checkout:
- Checkout button disabled until `hasPaymentMethod=true` (via `GET /billing/payment-methods/summary`).
- On submit, call `POST /orders` and redirect to order status page with polling.
- Order status page: shows statuses (Not Started → Activating → Activated/Failed), with links to Subscriptions and Invoices.
### 4.1 eSIM Self-service Actions (Service Detail)
- Actions available on an active eSIM subscription:
- Reissue eSIM: triggers BFF endpoint to call activation provider for a new profile, updates WHMCS notes/custom fields, sends email to customer.
- Top-up: triggers BFF to call provider top-up API; invoice/charges handled via WHMCS (AddOrder for add-on or gateway charge depending on implementation), sends email confirmation.
- UI: buttons gated by subscription status; confirmations and progress states.
## 5) Security, Idempotency, Observability
- Secrets in env/KMS, HTTPS-only, strict timeouts and retries with backoff in BFF external calls.
- Signed Salesforce → BFF requests with short TTL; IP allowlisting of Salesforce egress ranges.
- Idempotency keys for order creation and provisioning; include `sfOrderId` marker in WHMCS order notes.
- Logging: use centralized logger "dino" only; redact sensitive values; no payment data.
- Metrics: activation latency, WHMCS API error rates, provisioning success/failure, retries; alerts on anomalies.
## 6) Data Storage (minimal in BFF)
- Orchestration record: `sfOrderId`, items/config, status, masked eSIM identifiers, WHMCS order/service IDs, timestamps, idempotency keys.
- Mappings: `userId ↔ whmcsClientId ↔ sfAccountId`.
- No PANs, CVVs, or gateway tokens stored.
## 7) Work Items
Prerequisites for WHMCS provisioning
- Each Salesforce Product2 used by the portal must map to a WHMCS Product (pid): set `Product2.WHMCS_Product_Id__c` accordingly for:
- Main service SKUs (Internet, SIM/eSIM, VPN)
- Installation/activation SKUs (Internet install variants, VPN activation)
- BFF uses `Product2.StockKeepingUnit` to select PricebookEntry and `Product2.WHMCS_Product_Id__c` to build the `pid[]` list for WHMCS AddOrder.
1. Auth: require `sfNumber` in `SignupDto` and signup flow; lookup SF Account by Customer Number; align WHMCS custom field.
2. Billing: add `GET /billing/payment-methods/summary` and frontend gating.
3. Catalog UI: `/catalog` + product details pages.
4. Orders API: implement `POST /orders`, `GET /orders/:sfOrderId`.
5. Salesforce: fields, RecordTriggered Flow to publish `OrderProvisionRequested__e`; LWC for status.
6. WHMCS: add wrappers for `AddOrder`, `AcceptOrder`, `GetPayMethods` (if not already exposed).
7. Observability: correlation IDs, metrics, alerts; CDC or Platform Events for cache busting (optional).
8. Email: implement `EmailService` with provider; add BullMQ jobs for async sending; add templates for Signup, eSIM Activation, Activated.
9. eSIM Actions: implement `POST /subscriptions/:id/reissue-esim` and `POST /subscriptions/:id/topup` endpoints with BFF provider calls and WHMCS updates.
10. Future: Cancellations form → Salesforce Cancellations object submission (no immediate service cancel by customer).
## 8) Acceptance Criteria
- Signup requires Customer Number (SF Number) and links to the correct Salesforce Account and WHMCS client.
- Portal blocks checkout until a WHMCS payment method exists; SSO to WHMCS to add card.
- Orders are created in Salesforce and provisioned via BFF after operator trigger; idempotent and retriable.
- Customer sees clear order status and resulting subscriptions/invoices; sensitive details are not exposed.
## 9) WHMCS Field Mapping (Order Creation)
- `AddOrder` parameters to use:
- `clientid`: from user mapping
- `pid[]`: array of WHMCS product IDs (map from our catalog selection)
- `billingcycle`: `monthly` | `quarterly` | `semiannually` | `annually` | etc.
- `configoptions`: key/value for configurable options (from product detail form)
- `customfields`: include Customer Number (SF Number) and any order-specific data
- `paymentmethod`: WHMCS gateway system name (optional if default)
- `promocode`: if provided
- `notes`: include `sfOrderId=<Salesforce Order Id>` for idempotency tracing
- `noinvoice` / `noemail`: set to 0 to allow normal invoice + emails unless we handle emails ourselves
- After creation, call `AcceptOrder` to provision services and generate invoice/subscription as per WHMCS settings.
### 9.1 WHMCS Updates for eSIM Actions
- On Reissue:
- Update service custom fields (store masked new ICCID/EID if applicable), append to service notes with correlation ID and SF Order/Case references if any.
- Optionally create a zero-priced order for traceability or a billable add-on as business rules dictate.
- On Top-up:
- Create an add-on order or billable item/invoice through WHMCS; capture payment via existing payment method.
- Record top-up details in notes/custom fields.
## 10) Endpoint DTOs (Proposed)
- `POST /auth/signup`
- Request: `{ email, password, firstName, lastName, company?, phone?, sfNumber }`
- Response: `{ user, accessToken, refreshToken }`
- `GET /billing/payment-methods/summary`
- Response: `{ hasPaymentMethod: boolean }`
- `POST /orders`
- Request: `{ items: { productId: number; billingCycle: string; configOptions?: Record<string,string>; notes?: string }[]; promoCode?: string; notes?: string }`
- Response: `{ sfOrderId: string; status: 'Pending Review' }`
- `GET /orders/:sfOrderId`
- Response: `{ sfOrderId, status, whmcsOrderId?, whmcsServiceIds?: number[], lastUpdatedAt }`
// No SF → portal endpoint is required; provisioning is triggered via Platform Events.
- `POST /subscriptions/:id/reissue-esim`
- Request: `{ reason?: string }`
- Response: `{ status: 'InProgress' | 'Completed' | 'Failed', activationRef?, maskedIccid?, errorMessage? }`
- `POST /subscriptions/:id/topup`
- Request: `{ amount?: number; packageCode?: string }`
- Response: `{ status: 'Completed' | 'Failed', invoiceId?, errorMessage? }`
## 11) Email Requirements
- Transport: configurable (SMTP/SendGrid) via env; no secrets logged.
- Events & templates (to be provided):
- Signup Welcome (customer, CC support)
- eSIM Activation (customer, CC support)
- Order Provisioned (customer)
- Include correlation ID and minimal order/service context; no sensitive values.
### 11.1 Email Provider Recommendation
- Primary: SendGrid API (robust deliverability, templates, analytics). Use API key via env; send via BullMQ job for resiliency.
- Fallback: SMTP (e.g., SES SMTP or company SMTP relay) for environments without SendGrid.
- Rationale: SendGrid simplifies templating and CC/BCC handling; API-based sending reduces SMTP variability. Keep centralized logging without leaking PII.
## 12) Open Questions (to confirm)
1. Salesforce
- Confirm the Customer Number field API name on `Account` used for lookup.
- Confirm the exact custom field API names on `Order` (`Provisioning_Status__c`, etc.).
- Should `OpportunityId` be mandatory for Orders we create?
2. WHMCS
- Confirm the custom field id/name for Customer Number (currently used in mapping; assumed id 198).
- Provide product ID mapping for Home Internet/eSIM/VPN and their configurable options keys.
- Preferred default `paymentmethod` gateway system name.
3. Email
- Preferred provider (SMTP vs SendGrid) and from/reply-to addresses.
- Support CC distribution list for ops; any BCC requirements?
- Provide or approve email templates (copy + branding).
4. eSIM Activation API
- Endpoint(s), auth scheme, required payload, success/failed response shapes.
- Which identifiers to store/mask (ICCID, EID, MSISDN) and masking rules.
5. Provisioning Trigger
- Trigger via Flow on status change to Approved; optional manual retry publishes event again.
- Retry/backoff limits expected from SF side?
6. Cancellations
- Cancellation object API name in Salesforce; required fields; desired intake fields in portal form; who should be notified.