# Orders Domain & BFF Integration - Architecture Review ## Executive Summary After comprehensive review, there are **significant architectural issues** that need addressing. The current structure mixes infrastructure concerns with business logic, has types in wrong locations, and the field configuration system is problematic. --- ## 🚨 Critical Issues Found ### 1. **Field Configuration in Domain (WRONG PLACE)** **Issue:** `SalesforceOrdersFieldConfig` interfaces are defined in the domain package. **Location:** `packages/domain/orders/contract.ts` (lines 98-177) ```typescript // Currently in domain - THIS IS WRONG export interface SalesforceOrderMnpFieldConfig { ... } export interface SalesforceOrderFieldConfig { ... } export interface SalesforceOrdersFieldConfig { ... } ``` **Why This Is Wrong:** - These are **infrastructure configuration**, not business types - They map logical field names to Salesforce custom field API names - They're deployment-specific (which fields exist in which Salesforce org) - They're NOT business concepts - customers don't care about field mappings - Domain should be provider-agnostic **What Should Happen:** - ❌ Domain defines: "Here are the Salesforce field names you must use" - βœ… Domain defines: "Here are the business concepts" - βœ… BFF/Integration layer: "Here's how we map those concepts to Salesforce" **Correct Location:** `apps/bff/src/integrations/salesforce/types/field-config.types.ts` --- ### 2. **SalesforceFieldConfigService Location (CORRECT NOW)** **Current Location:** `apps/bff/src/integrations/salesforce/services/salesforce-field-config.service.ts` βœ… **Status:** **This is CORRECT!** You were right to question it. **Why:** - Reads from environment variables (ConfigService) - Deployment/environment specific - Infrastructure concern, not business logic - Belongs in BFF integration layer --- ### 3. **Pub/Sub Event Types (CORRECT)** **Current Location:** `apps/bff/src/integrations/salesforce/types/pubsub-events.types.ts` βœ… **Status:** **This is CORRECT!** **Why:** - Salesforce-specific infrastructure types - Platform event structure, not business events - Integration concern, not domain concern - Belongs in BFF integration layer --- ### 4. **Type Duplication & Confusion** **Found Multiple Similar Types:** ```typescript // In BFF order services export interface OrderItemMappingResult { ... } // order-whmcs-mapper.service.ts export interface OrderFulfillmentStep { ... } // order-fulfillment-orchestrator.service.ts export interface OrderFulfillmentContext { ... } // order-fulfillment-orchestrator.service.ts export interface SimFulfillmentRequest { ... } // sim-fulfillment.service.ts // In Domain export type FulfillmentOrderProduct { ... } export type FulfillmentOrderItem { ... } export type FulfillmentOrderDetails { ... } ``` **Issue:** Clear separation between: - **Business/Domain types** (what an order *is*) - **Workflow/Process types** (how fulfillment *works*) - **Integration types** (how we talk to external systems) --- ## πŸ“‹ Recommended Architecture ### **Domain Layer** (`packages/domain/orders/`) **Should contain:** ```typescript // Business entities - OrderDetails - OrderSummary - OrderItemDetails - OrderItemSummary - FulfillmentOrderDetails (if this is a business concept) // Business rules - Order validation schemas - Business constants (ORDER_TYPE, ORDER_STATUS, etc.) - Order lifecycle states // Provider contracts (interfaces only, no config) - What data structure do Salesforce/WHMCS need? - NOT which fields to use ``` **Should NOT contain:** - ❌ Field configuration interfaces - ❌ Environment-specific mappings - ❌ Query helpers (buildOrderSelectFields, etc.) - ❌ Integration-specific types --- ### **BFF Integration Layer** (`apps/bff/src/integrations/salesforce/`) **Should contain:** ```typescript // Infrastructure configuration - SalesforceFieldConfigService βœ… (already here) - Field mapping types (currently in domain ❌) - Query builders (should move from domain) - Connection management - Pub/Sub types βœ… (already here) // Integration adapters - Transform business types β†’ Salesforce records - Transform Salesforce records β†’ business types ``` **Structure:** ``` apps/bff/src/integrations/salesforce/ β”œβ”€β”€ services/ β”‚ β”œβ”€β”€ salesforce-connection.service.ts β”‚ β”œβ”€β”€ salesforce-field-config.service.ts βœ… β”‚ β”œβ”€β”€ salesforce-account.service.ts β”‚ └── salesforce-order.service.ts ← NEW (extract from modules/orders) β”œβ”€β”€ types/ β”‚ β”œβ”€β”€ field-config.types.ts ← MOVE HERE from domain β”‚ β”œβ”€β”€ pubsub-events.types.ts βœ… β”‚ └── query-builder.types.ts ← NEW └── utils/ β”œβ”€β”€ soql.util.ts └── query-builder.util.ts ← MOVE buildOrderSelectFields here ``` --- ### **BFF Order Module** (`apps/bff/src/modules/orders/`) **Should contain:** ```typescript // HTTP/API layer - OrdersController (API endpoints) // Application services (orchestration) - OrderOrchestrator (coordinates everything) - OrderValidator (business + integration validation) - OrderFulfillmentOrchestrator // Workflow types (NOT business types) - OrderFulfillmentContext - OrderFulfillmentStep - SimFulfillmentRequest ``` **Should NOT directly call:** - ❌ Direct Salesforce queries (use SalesforceOrderService) - ❌ Field mapping logic (use SalesforceFieldConfigService) --- ## πŸ”§ Specific Refactorings Needed ### **1. Move Field Config Types Out of Domain** **FROM:** `packages/domain/orders/contract.ts` ```typescript export interface SalesforceOrderMnpFieldConfig { ... } export interface SalesforceOrderBillingFieldConfig { ... } export interface SalesforceOrderFieldConfig { ... } export interface SalesforceOrderItemFieldConfig { ... } export interface SalesforceOrdersFieldConfig { ... } ``` **TO:** `apps/bff/src/integrations/salesforce/types/field-config.types.ts` ```typescript /** * Salesforce Field Configuration Types * Maps logical business field names to Salesforce custom field API names */ export interface SalesforceOrderFieldConfig { ... } export interface SalesforceOrdersFieldConfig { ... } // etc. ``` --- ### **2. Move Query Builders Out of Domain** **FROM:** `packages/domain/orders/providers/salesforce/query.ts` ```typescript export function buildOrderSelectFields(...) export function buildOrderItemSelectFields(...) export function buildOrderItemProduct2Fields(...) ``` **TO:** `apps/bff/src/integrations/salesforce/utils/order-query-builder.ts` ```typescript /** * SOQL Query builders for Orders * Uses field configuration to build dynamic queries */ export function buildOrderSelectFields(...) export function buildOrderItemSelectFields(...) // etc. ``` **Why:** These are SOQL-specific, infrastructure concerns, not business logic. --- ### **3. Create SalesforceOrderService** **NEW:** `apps/bff/src/integrations/salesforce/services/salesforce-order.service.ts` ```typescript @Injectable() export class SalesforceOrderService { constructor( private connection: SalesforceConnection, private fieldConfig: SalesforceFieldConfigService, private logger: Logger ) {} async getOrderById(orderId: string): Promise { // Contains Salesforce-specific query logic // Uses field config to build queries // Transforms SF records β†’ domain types } async createOrder(orderData: CreateOrderRequest): Promise<{ id: string }> { // Transform domain β†’ SF record // Create in Salesforce } async listOrders(params: OrderQueryParams): Promise { // Query logic } } ``` **Benefits:** - Encapsulates all Salesforce order operations - OrderOrchestrator doesn't need to know about Salesforce internals - Easier to test - Easier to swap providers --- ### **4. Consolidate WHMCS Mapping** **Current:** Duplicate mapping logic in: - `packages/domain/orders/providers/whmcs/mapper.ts` (domain βœ…) - `apps/bff/src/modules/orders/services/order-whmcs-mapper.service.ts` (BFF wrapper) **Issue:** The service is just a thin wrapper that calls domain mapper. Either: **Option A:** Keep mapper in domain, remove BFF service **Option B:** Move mapper to BFF integration layer **Recommendation:** **Option A** - Domain mapper is fine for data transformation. --- ## πŸ“Š Layering Principles ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ HTTP Layer (Controller) β”‚ β”‚ - API endpoints β”‚ β”‚ - Request/Response formatting β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Application Layer (Orchestrators) β”‚ β”‚ - OrderOrchestrator β”‚ β”‚ - OrderFulfillmentOrchestrator β”‚ β”‚ - Workflow coordination β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Domain Layer β”‚ β”‚ Integration Layer β”‚ β”‚ (Business) β”‚ β”‚ (Infrastructure) β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ - OrderDetails β”‚ β”‚ - SF Order Serviceβ”‚ β”‚ - Validation β”‚ β”‚ - WHMCS Service β”‚ β”‚ - Rules β”‚ β”‚ - Field Config β”‚ β”‚ - Schemas β”‚ β”‚ - Query Builders β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` **Rules:** 1. βœ… Domain can depend on: Nothing external 2. βœ… Integration can depend on: Domain 3. βœ… Application can depend on: Domain + Integration 4. βœ… HTTP can depend on: Application **Anti-patterns currently present:** - ❌ Domain exports query builders (infrastructure concern) - ❌ Domain defines field configuration types (deployment concern) - ❌ Application services directly query Salesforce (should go through integration service) --- ## 🎯 Recommended Action Plan ### **Phase 1: Move Infrastructure Types Out of Domain** (High Priority) 1. Create `apps/bff/src/integrations/salesforce/types/field-config.types.ts` 2. Move all `Salesforce*FieldConfig` interfaces from domain to BFF 3. Update imports across codebase 4. Update `SalesforceFieldConfigService` to export types from new location ### **Phase 2: Extract Salesforce Order Service** (Medium Priority) 1. Create `SalesforceOrderService` in integration layer 2. Move all Salesforce query logic from `OrderOrchestrator` to new service 3. Move query builders from domain to integration utils 4. Update orchestrator to use new service ### **Phase 3: Clean Up Type Exports** (Medium Priority) 1. Review all domain exports 2. Remove infrastructure types from domain exports 3. Create clear separation: business types vs workflow types vs integration types 4. Document what belongs where ### **Phase 4: Consolidate Mappers** (Low Priority) 1. Decide: Keep WHMCS mappers in domain or move to integration 2. Remove redundant service wrappers 3. Standardize mapper patterns --- ## πŸ’‘ Key Insights ### **Your Questions Answered:** 1. **"Should SalesforceFieldConfigService be in domain or BFF?"** - **Answer:** BFF integration layer βœ… (already correct!) - It's environment-specific configuration, not business logic 2. **"Should PubSub types be in domain?"** - **Answer:** No, BFF integration layer βœ… (already correct!) - They're Salesforce platform events, not business events 3. **"There are so many overlapping types and wrong used"** - **Answer:** YES! Field config interfaces should NOT be in domain - Query builders should NOT be in domain - These are infrastructure concerns masquerading as business logic --- ## βœ… What's Already Good 1. βœ… Core business types (OrderDetails, OrderSummary) are in domain 2. βœ… Validation schemas are in domain 3. βœ… Business constants (ORDER_TYPE, ORDER_STATUS) are in domain 4. βœ… SalesforceFieldConfigService is in BFF (correct location) 5. βœ… Pub/Sub types are in BFF (correct location) 6. βœ… Raw provider types (SalesforceOrderRecord) are in domain (for portability) --- ## πŸŽ“ Architecture Philosophy **Domain Layer:** > "What does the business care about? What are the rules?" **Integration Layer:** > "How do we talk to external systems? How do we map our concepts to theirs?" **Application Layer:** > "What workflows do we support? How do we coordinate services?" **HTTP Layer:** > "How do we expose functionality via API?" --- ## Conclusion The order domain needs refactoring to properly separate: - **Business logic** (domain) - **Infrastructure configuration** (BFF integration) - **Workflow orchestration** (BFF application) The most critical issue is that **field configuration types are in the domain** when they should be in the BFF integration layer. This violates domain-driven design principles and creates unwanted coupling. The good news: You were 100% right to question this, and the major pieces (service locations) are already correct. We just need to move the type definitions to match.