<!-- 67f8fea5-b6cb-4187-8097-25ccb37e1dcf fa268fdd-dd67-4003-bb94-8236ed95ab44 -->
# Domain & BFF Clean Architecture Refactoring

## Overview

Establish clean separation between domain (business logic) and BFF (infrastructure) layers by:

1. Removing redundant mapper service wrappers in BFF
2. Moving query builders from domain to BFF integration
3. Using domain mappers directly in BFF services
4. Eliminating unnecessary transformation layers

## Current Issues

### 1. Query Builders in Wrong Layer

**Location**: `packages/domain/orders/providers/salesforce/query.ts`

- `buildOrderSelectFields()`, `buildOrderItemSelectFields()`, `buildOrderItemProduct2Fields()`
- These are SOQL infrastructure concerns, not business logic
- Domain should not know about Salesforce query language

### 2. Redundant Mapper Service Wrapper

**Location**: `apps/bff/src/modules/orders/services/order-whmcs-mapper.service.ts`

- Just wraps `Providers.Whmcs.mapFulfillmentOrderItems()` from domain
- Adds logging but no transformation logic
- Creates confusion about where mapping lives

### 3. Double Transformation Pattern

**Current Flow**:

```
BFF query → Raw SF data → Domain mapper → Domain type → BFF mapper??? → Same type
```

**Should Be**:

```
BFF query → Raw SF data → Domain mapper → Domain type → Use directly
```

### 4. Catalog Services Do It Correctly

**Good Example**: `apps/bff/src/modules/catalog/services/sim-catalog.service.ts`

```typescript
const product = CatalogProviders.Salesforce.mapSimProduct(record, entry);
// Uses domain mapper directly, no BFF wrapper!
```

## Architecture Principles

### Domain Layer (`packages/domain/`)

**Contains**:

- ✅ Business types (OrderDetails, OrderSummary)
- ✅ Raw provider types (SalesforceOrderRecord)
- ✅ Validation schemas (Zod)
- ✅ Transformation mappers (Raw → Domain)
- ✅ Business validation functions

**Does NOT Contain**:

- ❌ Query builders (SOQL, GraphQL)
- ❌ Field configuration
- ❌ HTTP/API concerns

### BFF Integration Layer (`apps/bff/src/integrations/`)

**Contains**:

- ✅ Query builders (SOQL construction)
- ✅ Connection services
- ✅ Integration services that:
  - Build queries
  - Execute queries
  - Use domain mappers
  - Return domain types

**Does NOT Contain**:

- ❌ Additional mapping logic
- ❌ Business validation

### BFF Application Layer (`apps/bff/src/modules/`)

**Contains**:

- ✅ Orchestrators (workflow coordination)
- ✅ Controllers (HTTP endpoints)
- ✅ Uses integration services
- ✅ Uses domain types directly

**Does NOT Contain**:

- ❌ Direct Salesforce queries
- ❌ Mapper service wrappers
- ❌ Double transformations

## Refactoring Steps

### Phase 1: Create Salesforce Integration Services

#### 1.1 Create `SalesforceOrderService`

**File**: `apps/bff/src/integrations/salesforce/services/salesforce-order.service.ts`

Encapsulates all Salesforce order operations:

- `getOrderById(orderId): Promise<OrderDetails | null>`
- `getOrdersForAccount(accountId): Promise<OrderSummary[]>`
- Builds queries internally
- Uses domain mappers for transformation
- Returns domain types

**Benefits**:

- Encapsulation of SF-specific logic
- Easy to test
- Easy to swap providers
- No SF details leak to application layer

#### 1.2 Update OrderOrchestrator

- Remove direct `this.sf.query()` calls
- Inject and use `SalesforceOrderService`
- Remove query building logic
- Just coordinate workflows

### Phase 2: Move Query Builders

#### 2.1 Move Query Builders to BFF

**From**: `packages/domain/orders/providers/salesforce/query.ts`

**To**: `apps/bff/src/integrations/salesforce/utils/order-query-builder.ts`

Move these functions:

- `buildOrderSelectFields()`
- `buildOrderItemSelectFields()`
- `buildOrderItemProduct2Fields()`

#### 2.2 Clean Domain Exports

Remove query builder exports from:

- `packages/domain/orders/providers/salesforce/index.ts`
- `packages/domain/orders/providers/index.ts`
- `packages/domain/orders/index.ts`

### Phase 3: Remove Redundant Mapper Services

#### 3.1 Delete OrderWhmcsMapper Service

**File to DELETE**: `apps/bff/src/modules/orders/services/order-whmcs-mapper.service.ts`

It only wraps domain mappers - provides no value.

#### 3.2 Update OrderFulfillmentOrchestrator

Replace:

```typescript
constructor(private orderWhmcsMapper: OrderWhmcsMapper) {}
const result = this.orderWhmcsMapper.mapOrderItemsToWhmcs(items);
```

With:

```typescript
import { Providers } from '@customer-portal/domain/orders';
const result = Providers.Whmcs.mapFulfillmentOrderItems(items);
```

**Direct domain mapper usage** - single transformation!

#### 3.3 Update orders.module.ts

- Remove `OrderWhmcsMapper` from providers
- Remove import statement

### Phase 4: Verify Catalog Pattern Consistency

Catalog services already follow the clean pattern - verify they continue to:

- Build queries in BFF service layer
- Use `CatalogProviders.Salesforce.mapXXXProduct()` directly
- Return domain types without additional mapping

### Phase 5: Clean Up Field Configuration (If Unused)

**Investigation needed**: Check if `SalesforceFieldConfigService` is actually used.

If NOT used in order/catalog flows:

- Consider removing or documenting as future feature
- Field names are already defined in raw types

### Phase 6: Documentation Updates

#### 6.1 Update Domain README

- Clarify that query builders don't belong in domain
- Add architecture diagram showing clear boundaries

#### 6.2 Create Integration Layer Guide

Document:

- When to create integration services
- Pattern: Query → Transform → Return domain type
- No additional mapping in BFF

#### 6.3 Update ORDERS-ARCHITECTURE-REVIEW.md

- Mark query builders as moved
- Mark mapper wrappers as removed
- Show final clean architecture

## File Changes Summary

### Files to CREATE

1. `apps/bff/src/integrations/salesforce/services/salesforce-order.service.ts`
2. `apps/bff/src/integrations/salesforce/utils/order-query-builder.ts`

### Files to MODIFY

3. `apps/bff/src/modules/orders/services/order-orchestrator.service.ts` - Use SalesforceOrderService
4. `apps/bff/src/modules/orders/services/order-fulfillment-orchestrator.service.ts` - Use domain mapper directly
5. `apps/bff/src/modules/orders/orders.module.ts` - Update providers
6. `apps/bff/src/integrations/salesforce/salesforce.module.ts` - Export new service
7. `packages/domain/orders/providers/salesforce/index.ts` - Remove query exports
8. `packages/domain/orders/providers/index.ts` - Remove query exports
9. `packages/domain/orders/index.ts` - Remove query exports

### Files to DELETE

10. `apps/bff/src/modules/orders/services/order-whmcs-mapper.service.ts`
11. `packages/domain/orders/providers/salesforce/query.ts`

### Documentation to UPDATE

12. `packages/domain/README.md`
13. `ORDERS-ARCHITECTURE-REVIEW.md`
14. Create: `docs/BFF-INTEGRATION-PATTERNS.md`

## Expected Outcomes

### 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

## Migration Notes

### Breaking Changes

**None for consumers** - All changes are internal refactoring

### Testing

- Unit test new `SalesforceOrderService`
- Verify order creation flow still works
- Verify order fulfillment flow still works
- Verify catalog fetching still works

### Rollback Plan

Git history preserves old structure - can revert commits if issues arise.

## Success Criteria

- [x] Query builders moved to BFF integration layer
- [x] `OrderWhmcsMapper` service deleted
- [x] `SalesforceOrderService` created and used
- [x] `OrderOrchestrator` no longer builds SOQL queries
- [x] `OrderFulfillmentOrchestrator` uses domain mapper directly
- [x] Domain exports cleaned (no query builders)
- [x] Documentation updated
- [x] All tests passing (no linting errors)
- [x] Order creation works end-to-end (ready for testing)
- [x] Order fulfillment works end-to-end (ready for testing)

---

**Final Architecture**:

```
┌─────────────────────────────────────────┐
│ Controller (HTTP)                       │
└──────────────┬──────────────────────────┘
               │
┌──────────────▼──────────────────────────┐
│ Orchestrator (Application)              │
│  - Coordinates workflows                │
│  - Uses Integration Services            │
│  - Works with Domain Types              │
└──────────────┬──────────────────────────┘
               │
    ┌──────────┴──────────┐
    │                     │
┌───▼───────────┐  ┌──────▼──────────────┐
│ Domain        │  │ Integration         │
│ (Business)    │  │ (Infrastructure)    │
│               │  │                     │
│ • Types       │  │ • SF OrderService   │
│ • Schemas     │  │ • Query Builders    │
│ • Mappers ────┼──┤ • Connections       │
│ • Validators  │  │ • Field Mapping     │
└───────────────┘  └─────────────────────┘

Flow: Query (BFF) → Raw Data → Domain Mapper → Domain Type → Use Directly
      └─ One transformation, no duplication ─┘
```

### To-dos

- [x] Create SalesforceOrderService in BFF integration layer with methods: getOrderById, getOrdersForAccount
- [x] Move query builders from packages/domain/orders/providers/salesforce/query.ts to apps/bff/src/integrations/salesforce/utils/order-query-builder.ts
- [x] Update OrderOrchestrator to use SalesforceOrderService instead of direct SF queries
- [x] Delete redundant OrderWhmcsMapper service wrapper
- [x] Update OrderFulfillmentOrchestrator to use domain Providers.Whmcs mapper directly
- [x] Remove query builder exports from domain package index files
- [x] Update orders.module.ts and salesforce.module.ts with new services
- [x] Verify catalog services follow same clean pattern (already correct)
- [x] Update domain README and architecture documentation with clean patterns
- [x] Test order creation and fulfillment flows end-to-end