# Orders Domain & BFF Integration - Architecture Review ## Executive Summary **Date**: October 2025 **Status**: ✅ **REFACTORED - CLEAN ARCHITECTURE** After comprehensive review and refactoring, the architecture now follows clean separation of concerns with a single source of truth for data transformations. --- ## ✅ Refactoring Complete ### What Was Fixed 1. **✅ Query Builders Moved to BFF Integration** - FROM: `packages/domain/orders/providers/salesforce/query.ts` - TO: `apps/bff/src/integrations/salesforce/utils/order-query-builder.ts` - **Reason**: SOQL is infrastructure, not business logic 2. **✅ SalesforceOrderService Created** - **Location**: `apps/bff/src/integrations/salesforce/services/salesforce-order.service.ts` - Encapsulates all Salesforce order operations - Uses domain mappers for transformation - Returns domain types 3. **✅ Redundant Mapper Service Removed** - **Deleted**: `apps/bff/src/modules/orders/services/order-whmcs-mapper.service.ts` - **Reason**: Only wrapped domain mappers, provided no value - Now use `Providers.Whmcs.mapFulfillmentOrderItems()` directly 4. **✅ OrderOrchestrator Refactored** - Removed direct Salesforce queries - Uses `SalesforceOrderService` for data fetching - Simplified from 150+ lines to clean delegation 5. **✅ Domain Exports Cleaned** - Removed query builder exports from domain package - Domain now only exports business logic --- ## 🎯 Current Architecture ### Clean Separation of Concerns ``` ┌─────────────────────────────────────────┐ │ Controller (HTTP) │ │ - API endpoints │ │ - Request/Response formatting │ └──────────────────┬──────────────────────┘ │ ┌──────────────────▼──────────────────────┐ │ Orchestrator (Application) │ │ - Coordinates workflows │ │ - Uses Integration Services │ │ - Works with Domain Types │ └──────────────────┬──────────────────────┘ │ ┌──────────────┴──────────────┐ │ │ ┌───▼───────────┐ ┌──────────────▼──────────┐ │ Domain │ │ Integration │ │ (Business) │ │ (Infrastructure) │ │ │ │ │ │ • Types │ │ • SalesforceOrderService │ │ • Schemas │ │ • Query Builders │ │ • Mappers ────┼──┤ • Connections │ │ • Validators │ │ • API Clients │ └───────────────┘ └──────────────────────────┘ Flow: Query (BFF) → Raw Data → Domain Mapper → Domain Type → Use Directly └────────── Single transformation, no duplication ──────────┘ ``` ### Domain Layer (`packages/domain/orders/`) **Contains**: - ✅ Business types (OrderDetails, OrderSummary) - ✅ Raw provider types (SalesforceOrderRecord) - ✅ Validation schemas (Zod) - ✅ Transformation mappers (Raw → Domain) - ✅ Business validation functions **Does NOT Contain**: - ❌ Query builders (moved to BFF) - ❌ Field configuration - ❌ HTTP/API concerns ### Integration Layer (`apps/bff/src/integrations/salesforce/`) **Contains**: - ✅ `SalesforceOrderService` - Encapsulates order operations - ✅ Query builders (`order-query-builder.ts`) - ✅ Connection services - ✅ Uses domain mappers for transformation **Does NOT Contain**: - ❌ Additional mapping logic (uses domain mappers) - ❌ Business validation ### Application Layer (`apps/bff/src/modules/orders/`) **Contains**: - ✅ `OrderOrchestrator` - Workflow coordination - ✅ `OrderFulfillmentOrchestrator` - Fulfillment workflows - ✅ Controllers (HTTP endpoints) - ✅ Uses integration services - ✅ Uses domain mappers directly **Does NOT Contain**: - ❌ Direct Salesforce queries - ❌ Mapper service wrappers (deleted) - ❌ Double transformations --- ## 📊 Key Improvements ### Before: Mixed Concerns ```typescript // OrderOrchestrator building SOQL directly (❌ Wrong) const soql = `SELECT ${buildOrderSelectFields().join(", ")} FROM Order...`; const result = await this.sf.query(soql); const order = DomainMapper.transform(result); // OrderWhmcsMapper wrapping domain mapper (❌ Redundant) mapOrderItemsToWhmcs(items) { return Providers.Whmcs.mapFulfillmentOrderItems(items); } ``` ### After: Clean Architecture ```typescript // OrderOrchestrator delegates to integration service (✅ Correct) return this.salesforceOrderService.getOrderById(orderId); // Direct domain mapper usage (✅ Clean) const whmcsItems = Providers.Whmcs.mapFulfillmentOrderItems(items); ``` --- ## ✅ Benefits Achieved ### Architecture Cleanliness - ✅ Single source of truth for transformations (domain mappers) - ✅ Clear separation: domain = business, BFF = infrastructure - ✅ No redundant mapping layers - ✅ Query logic in correct layer (BFF integration) ### Code Quality - ✅ Easier to test (clear boundaries) - ✅ Easier to maintain (no duplication) - ✅ Easier to understand (one transformation path) - ✅ Easier to swap providers (integration services encapsulate) ### Developer Experience - ✅ Clear patterns to follow - ✅ No confusion about where code goes - ✅ Consistent with catalog services - ✅ Self-documenting architecture --- ## 📁 File Structure ### Created Files 1. ✅ `apps/bff/src/integrations/salesforce/services/salesforce-order.service.ts` 2. ✅ `apps/bff/src/integrations/salesforce/utils/order-query-builder.ts` 3. ✅ `docs/BFF-INTEGRATION-PATTERNS.md` ### Modified Files 1. ✅ `apps/bff/src/modules/orders/services/order-orchestrator.service.ts` 2. ✅ `apps/bff/src/modules/orders/services/order-fulfillment-orchestrator.service.ts` 3. ✅ `apps/bff/src/modules/orders/orders.module.ts` 4. ✅ `apps/bff/src/integrations/salesforce/salesforce.module.ts` 5. ✅ `packages/domain/orders/providers/salesforce/index.ts` 6. ✅ `packages/domain/orders/index.ts` ### Deleted Files 1. ✅ `apps/bff/src/modules/orders/services/order-whmcs-mapper.service.ts` 2. ✅ `packages/domain/orders/providers/salesforce/query.ts` --- ## 🎓 Architecture Principles Followed ### Single Transformation Principle **One transformation path** - raw data flows through domain mapper exactly once: ``` Query (BFF) → Raw Data → Domain Mapper → Domain Type → Use Directly ``` ### Encapsulation Principle Integration services hide external system complexity: ```typescript // Application layer doesn't see Salesforce details const order = await this.salesforceOrderService.getOrderById(id); ``` ### Separation of Concerns Each layer has a single responsibility: - **Domain**: Business logic, types, validation - **Integration**: External system interaction - **Application**: Workflow coordination - **HTTP**: API endpoints --- ## 🔍 Pattern Examples ### Example 1: Fetching Orders ```typescript // OrderOrchestrator (Application Layer) async getOrder(orderId: string): Promise { // Clean delegation - no SF-specific code! return this.salesforceOrderService.getOrderById(orderId); } // SalesforceOrderService (Integration Layer) async getOrderById(orderId: string): Promise { // 1. Build query (infrastructure) const soql = buildOrderQuery(orderId); // 2. Execute query const rawData = await this.sf.query(soql); // 3. Use domain mapper (single transformation!) return Providers.Salesforce.transformSalesforceOrderDetails(rawData); } ``` ### Example 2: Order Fulfillment ```typescript // OrderFulfillmentOrchestrator { id: "mapping", description: "Map OrderItems to WHMCS format", execute: () => { // Use domain mapper directly - no service wrapper! const result = OrderProviders.Whmcs.mapFulfillmentOrderItems( context.orderDetails.items ); return Promise.resolve(result); }, } ``` --- ## ✅ 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. ✅ Domain mappers provide single transformation 5. ✅ Raw provider types (SalesforceOrderRecord) are in domain 6. ✅ Catalog services already follow this pattern --- ## 📖 Related Documentation - [BFF Integration Patterns](./docs/BFF-INTEGRATION-PATTERNS.md) - [Domain Package README](./packages/domain/README.md) - [Schema-First Approach](./packages/domain/SCHEMA-FIRST-COMPLETE.md) --- ## 🎯 Future Considerations ### Potential Enhancements 1. **Field Configuration**: Currently not used - consider removing or implementing consistently 2. **Query Caching**: Add caching layer in integration services 3. **Query Optimization**: Review SOQL queries for performance 4. **Integration Tests**: Add tests for SalesforceOrderService ### Monitoring - Track order query performance - Monitor transformation errors - Log integration service calls --- ## Conclusion **Status**: ✅ **COMPLETE** The architecture now follows clean separation of concerns: - **Domain**: Pure business logic (no infrastructure) - **Integration**: External system encapsulation (SF, WHMCS) - **Application**: Workflow coordination (orchestrators) **Key Achievement**: Single source of truth for transformations with no redundant mapping layers. --- **Last Updated**: October 2025 **Refactored By**: Architecture Review Team