From df4149063f2e9e7bf4166333990a7e1cb5574f0f Mon Sep 17 00:00:00 2001 From: "T. Narantuya" Date: Sat, 6 Sep 2025 10:01:25 +0900 Subject: [PATCH] Add Salesforce event configuration and provisioning diagnostics - Introduced new environment variables for Salesforce platform events, including SF_EVENTS_ENABLED, SF_PROVISION_EVENT_CHANNEL, SF_EVENTS_REPLAY, SF_PUBSUB_ENDPOINT, SF_PUBSUB_NUM_REQUESTED, and SF_PUBSUB_QUEUE_MAX. - Updated SalesforceFieldMap to include optional fields for provisioning diagnostics: lastErrorCode, lastErrorMessage, and lastAttemptAt. - Adjusted installationType field mapping to reflect the correct field name in Salesforce. - Enhanced order query fields to include new diagnostic fields for better tracking and error handling. --- apps/bff/src/common/config/env.validation.ts | 10 +++++ apps/bff/src/common/config/field-map.ts | 44 ++++++++++++++++---- 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/apps/bff/src/common/config/env.validation.ts b/apps/bff/src/common/config/env.validation.ts index a2c08bc2..8e617741 100644 --- a/apps/bff/src/common/config/env.validation.ts +++ b/apps/bff/src/common/config/env.validation.ts @@ -43,6 +43,16 @@ export const envSchema = z.object({ SF_PRIVATE_KEY_PATH: z.string().optional(), SF_WEBHOOK_SECRET: z.string().optional(), + // Salesforce Platform Events (Async Provisioning) + SF_EVENTS_ENABLED: z.enum(["true", "false"]).default("false"), + SF_PROVISION_EVENT_CHANNEL: z + .string() + .default("/event/Order_Fulfilment_Requested__e"), + SF_EVENTS_REPLAY: z.enum(["LATEST", "ALL"]).default("LATEST"), + SF_PUBSUB_ENDPOINT: z.string().default("api.pubsub.salesforce.com:7443"), + SF_PUBSUB_NUM_REQUESTED: z.string().default("50"), + SF_PUBSUB_QUEUE_MAX: z.string().default("100"), + // Email / SendGrid SENDGRID_API_KEY: z.string().optional(), EMAIL_FROM: z.string().email().default("no-reply@example.com"), diff --git a/apps/bff/src/common/config/field-map.ts b/apps/bff/src/common/config/field-map.ts index ecc2344f..8f180a24 100644 --- a/apps/bff/src/common/config/field-map.ts +++ b/apps/bff/src/common/config/field-map.ts @@ -72,6 +72,11 @@ export type SalesforceFieldMap = { // WHMCS integration whmcsOrderId: string; + // Provisioning diagnostics + lastErrorCode?: string; + lastErrorMessage?: string; + lastAttemptAt?: string; + // Address fields addressChanged: string; @@ -137,7 +142,8 @@ export function getSalesforceFieldMap(): SalesforceFieldMap { // Internet fields (independent fields synced with OrderItems) internetPlanTier: process.env.ORDER_INTERNET_PLAN_TIER_FIELD || "Internet_Plan_Tier__c", - installationType: process.env.ORDER_INSTALLATION_TYPE_FIELD || "Installation_Type__c", + + installationType: process.env.ORDER_INSTALLATION_TYPE_FIELD || "Installment_Plan__c", weekendInstall: process.env.ORDER_WEEKEND_INSTALL_FIELD || "Weekend_Install__c", accessMode: process.env.ORDER_ACCESS_MODE_FIELD || "Access_Mode__c", hikariDenwa: process.env.ORDER_HIKARI_DENWA_FIELD || "Hikari_Denwa__c", @@ -171,16 +177,22 @@ export function getSalesforceFieldMap(): SalesforceFieldMap { // WHMCS integration whmcsOrderId: process.env.ORDER_WHMCS_ORDER_ID_FIELD || "WHMCS_Order_ID__c", + // Diagnostics (optional fields) — single source of truth: Activation_* fields + lastErrorCode: process.env.ORDER_ACTIVATION_ERROR_CODE_FIELD || "Activation_Error_Code__c", + lastErrorMessage: + process.env.ORDER_ACTIVATION_ERROR_MESSAGE_FIELD || "Activation_Error_Message__c", + lastAttemptAt: process.env.ORDER_ACTIVATION_LAST_ATTEMPT_AT_FIELD || "ActivatedDate", + // Address fields addressChanged: process.env.ORDER_ADDRESS_CHANGED_FIELD || "Address_Changed__c", - // Billing address snapshot fields + // Billing address snapshot fields — single source of truth: Billing* fields on Order billing: { - street: process.env.ORDER_BILL_TO_STREET_FIELD || "BillToStreet", - city: process.env.ORDER_BILL_TO_CITY_FIELD || "BillToCity", - state: process.env.ORDER_BILL_TO_STATE_FIELD || "BillToState", - postalCode: process.env.ORDER_BILL_TO_POSTAL_CODE_FIELD || "BillToPostalCode", - country: process.env.ORDER_BILL_TO_COUNTRY_FIELD || "BillToCountry", + street: process.env.ORDER_BILLING_STREET_FIELD || "BillingStreet", + city: process.env.ORDER_BILLING_CITY_FIELD || "BillingCity", + state: process.env.ORDER_BILLING_STATE_FIELD || "BillingState", + postalCode: process.env.ORDER_BILLING_POSTAL_CODE_FIELD || "BillingPostalCode", + country: process.env.ORDER_BILLING_COUNTRY_FIELD || "BillingCountry", }, }, orderItem: { @@ -227,6 +239,9 @@ export function getOrderQueryFields(): string { fields.order.activationType, fields.order.activationScheduledAt, fields.order.activationStatus, + fields.order.lastErrorCode, + fields.order.lastErrorMessage, + fields.order.lastAttemptAt, // Internet fields fields.order.internetPlanTier, fields.order.installationType, @@ -244,3 +259,18 @@ export function getOrderQueryFields(): string { fields.order.whmcsOrderId, ].join(", "); } + +// Build a nested select list for PricebookEntry.Product2.* fields used in OrderItem queries +export function getOrderItemProduct2Select(additional: string[] = []): string { + const fields = getSalesforceFieldMap(); + const base = [ + "Id", + "Name", + fields.product.sku, + fields.product.whmcsProductId, + fields.product.itemClass, + fields.product.billingCycle, + ]; + const all = [...base, ...additional]; + return all.map(f => `PricebookEntry.Product2.${f}`).join(", "); +}