> For the complete documentation index, see [llms.txt](https://docs.beeoclock.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.beeoclock.com/services/customer-management/usecase.md).

# Use Case Documentation

## Overview

This document describes the business use cases and application layer logic for the Customer Management module. Each use case encapsulates business rules, permissions, and orchestrates the interaction between domain entities, repositories, and external integrations within the order and payment ecosystem.

## Architecture Pattern

The module follows the CQRS (Command Query Responsibility Segregation) pattern with the following structure:

* **Use Cases**: Application layer orchestrating business logic
* **Commands**: Write operations (Create, Update, Delete Customer)
* **Queries**: Read operations (Get Customer, Search Customers)
* **Domain Entities**: Business logic and validation
* **Value Objects**: Customer data and relationship objects
* **Integration Services**: Order and payment system integration

## Core Use Cases

### 1. CreateCustomerUseCase

**Purpose:** Creates a new customer record with comprehensive validation and business rule enforcement.

**Input:** `CreateCustomerUseCaseParams`

```typescript
{
  ctx: TenantActorContext,
  customer: CustomerDto
}
```

**Output:** `string` (Customer ID)

**Business Rules:**

1. User must have `CREATE_CUSTOMER` permission
2. At least one of firstName, lastName, email, or phone must be provided
3. Email must be valid format if provided
4. Phone must be valid format if provided (automatically normalized)
5. Customer type defaults to 'regular' if not specified
6. No duplicate customers based on email/phone combination
7. Customer is created with 'active' state

**Process Flow:**

1. Validate user permissions using `PermissionValidatorUseCase`
2. Validate customer data using `CustomerValidator`
3. Execute `AddRegularCustomerCommand` via command bus
4. Command handler validates domain rules and creates entity
5. Persist customer to database with tenant isolation
6. Clear relevant cache entries
7. Publish `CustomerAddedMessage` event
8. Return generated customer ID

**Validation Rules:**

```typescript
// Mandatory field validation
const hasRequiredField = customer.firstName || customer.lastName || 
                        customer.email || customer.phone;
if (!hasRequiredField) {
  throw new ValidationException('At least one field must be filled: phone, email, first name or last name.');
}

// Email format validation
if (customer.email && !isValidEmail(customer.email)) {
  throw new ValidationException('Invalid email format');
}

// Phone format validation and normalization
if (customer.phone) {
  const normalizedPhone = extractNumbers(customer.phone);
  customer.phone = normalizedPhone;
}
```

**Cache Invalidation:** Clears `CustomerCacheKeys.GET_PAGED_CUSTOMERS`

***

### 2. GetCustomerUseCase

**Purpose:** Retrieves detailed customer information by ID with permission validation.

**Input:** `GetCustomerUseCaseParams`

```typescript
{
  ctx: TenantActorContext,
  customerId: string
}
```

**Output:** `CustomerDto`

**Business Rules:**

1. User must have `READ_CUSTOMER` permission
2. Customer must exist and belong to the authenticated tenant
3. Returns complete customer information including state history
4. Respects tenant data isolation

**Process Flow:**

1. Validate user permissions
2. Execute `GetCustomerByIdQuery` via query bus
3. Query handler retrieves customer from repository
4. Transform persistence model to DTO
5. Return customer data or throw exception if not found

**Error Scenarios:**

* Insufficient permissions → `ForbiddenException`
* Customer not found → `CustomerNotFoundException`
* Database errors → Logged and re-thrown

**Caching:** Results are cached using `CustomerCacheKeys.GET_CUSTOMER`

***

### 3. UpdateCustomerUseCase

**Purpose:** Updates existing customer information with partial update support and validation.

**Input:** `UpdateCustomerUseCaseParams`

```typescript
{
  ctx: TenantActorContext,
  customerId: string,
  update: CustomerDto
}
```

**Output:** `void`

**Business Rules:**

1. User must have `EDIT_CUSTOMER` permission
2. Customer must exist and belong to the authenticated tenant
3. Supports partial updates (only provided fields are updated)
4. Email and phone validation applied if provided
5. Customer type can be changed with proper validation
6. Updates increment version number for optimistic locking

**Process Flow:**

1. Validate user permissions
2. Verify customer exists using `GetCustomerByIdQuery`
3. Validate update data using `CustomerValidator`
4. Execute `UpdateCustomerCommand` via command bus
5. Command handler applies domain validation and updates entity
6. Persist changes with optimistic locking
7. Clear relevant cache entries
8. Publish `CustomerUpdatedMessage` event

**Domain Validation:**

```typescript
// Validate email if provided
if (update.email && !Customer.validateEmail(update.email).isSuccessResult()) {
  throw new ValidationException('Invalid email format');
}

// Validate and normalize phone if provided
if (update.phone) {
  const phoneValidation = Customer.validatePhone(update.phone);
  if (phoneValidation.isFailureResult()) {
    throw new ValidationException(phoneValidation.errorValue());
  }
  update.phone = extractNumbers(update.phone);
}
```

**Cache Invalidation:** Clears `CustomerCacheKeys.GET_CUSTOMER` and `CustomerCacheKeys.GET_PAGED_CUSTOMERS`

***

### 4. DeleteCustomerUseCase

**Purpose:** Soft deletes a customer record with business rule validation.

**Input:** `DeleteCustomerUseCaseParams`

```typescript
{
  ctx: TenantActorContext,
  customerId: string
}
```

**Output:** `void`

**Business Rules:**

1. User must have `DELETE_CUSTOMER` permission
2. Customer must exist and belong to the authenticated tenant
3. Performs soft delete (sets state to 'deleted')
4. Validates no active orders exist for the customer
5. Preserves historical data for reporting and compliance

**Process Flow:**

1. Validate user permissions
2. Verify customer exists
3. Check for active orders or dependencies
4. Execute `DeleteCustomerCommand` via command bus
5. Command handler performs soft delete
6. Update state history with deletion reason
7. Clear relevant cache entries
8. Publish `CustomerDeletedMessage` event

**Dependency Validation:**

```typescript
// Check for active orders
const activeOrders = await this.orderService.getActiveOrdersByCustomer(customerId);
if (activeOrders.length > 0) {
  throw new BusinessRuleViolationException('Cannot delete customer with active orders');
}

// Check for pending payments
const pendingPayments = await this.paymentService.getPendingPaymentsByCustomer(customerId);
if (pendingPayments.length > 0) {
  throw new BusinessRuleViolationException('Cannot delete customer with pending payments');
}
```

***

### 5. GetPagedCustomersUseCase

**Purpose:** Retrieves paginated customer list with search and filtering capabilities.

**Input:** `GetPagedCustomersUseCaseParams`

```typescript
{
  ctx: TenantActorContext,
  pagination: CustomerPaginationDto
}
```

**Output:** `PaginationResponseDto<CustomerDto>`

**Business Rules:**

1. User must have `READ_CUSTOMER` permission
2. Results are filtered by tenant for data isolation
3. Supports text search across name and email fields
4. Supports filtering by customer type and state
5. Implements efficient pagination with cursor support
6. Maximum page size limit enforced

**Process Flow:**

1. Validate user permissions
2. Validate pagination parameters
3. Execute `GetPagedCustomersQuery` via query bus
4. Query handler applies filters and pagination
5. Transform results to DTOs
6. Return paginated response with metadata

**Search Implementation:**

```typescript
// MongoDB aggregation pipeline for customer search
const pipeline = [
  // Text search stage
  {
    $match: {
      $or: [
        { firstName: { $regex: searchTerm, $options: 'i' } },
        { lastName: { $regex: searchTerm, $options: 'i' } },
        { email: { $regex: searchTerm, $options: 'i' } },
        { $text: { $search: searchTerm } }
      ],
      tenantId: ctx.tenantId,
      state: { $ne: 'deleted' }
    }
  },
  // Customer type filtering
  ...(customerType ? [{ $match: { customerType } }] : []),
  // Sorting and pagination
  { $sort: getSortCriteria(sortBy, sortDirection) },
  { $skip: (page - 1) * limit },
  { $limit: limit }
];
```

**Caching:** Results cached using `CustomerCacheKeys.GET_PAGED_CUSTOMERS` with pagination context

***

## Order Integration Use Cases

### 6. AddAttendeesUseCase

**Purpose:** Processes customer attendees for order services, creating or updating customer records as needed.

**Input:** `AddAttendeesCommand`

```typescript
{
  tenantId: string,
  attendees: AttendantDto[]
}
```

**Output:** `AttendantDto[]` (Processed attendees with customer IDs)

**Business Rules:**

1. Creates regular customers for attendees with email/phone
2. Reuses existing customers when found by email/phone match
3. Marks first-time visitors based on order history
4. Validates attendee information against business settings
5. Maintains customer snapshots in order data

**Process Flow:**

1. Iterate through provided attendees
2. For each attendee with contact information:
   * Search for existing customer by email/phone
   * If found, use existing customer and mark `firstTime: false`
   * If not found, create new regular customer
   * Validate customer data meets business requirements
3. Create customer snapshots for order persistence
4. Return processed attendee list with customer references

**Customer Matching Logic:**

```typescript
// Find existing customer by email or phone
const existingCustomer = await this.sharedUnitOfWork.customers.findCustomerByEmailOrPhone(
  attendant.customer?.email,
  attendant.customer?.phone
);

if (existingCustomer) {
  // Use existing customer
  attendantDtoArray.push({
    object: 'AttendantDto',
    customer: CustomerMap.toDto({ ...existingCustomer, customerType: CustomerTypeEnum.regular }),
    firstTime: false
  });
} else {
  // Create new regular customer
  const regularCustomer = Customer.createRegular({
    _id: attendant?.customer?._id,
    customerType: CustomerTypeEnum.regular,
    email: attendant.customer?.email,
    firstName: attendant.customer?.firstName,
    lastName: attendant.customer?.lastName,
    phone: attendant.customer?.phone,
  });

  if (regularCustomer.isSuccessResult()) {
    const persistenceCustomer = CustomerMap.toPersistence(regularCustomer.getValue());
    const createdCustomer = await this.sharedUnitOfWork.customers.createCustomer(persistenceCustomer);
    
    attendantDtoArray.push({
      object: 'AttendantDto',
      customer: CustomerMap.toDto(createdCustomer),
      firstTime: true
    });
  }
}
```

***

### 7. AddPublicAttendeesUseCase

**Purpose:** Processes customer information from public order creation with flexible customer handling.

**Input:** `AddPublicAttendeesCommand`

```typescript
{
  tenantId: string,
  attendees: PublicAttendantDto[]
}
```

**Output:** `AttendantDto[]`

**Business Rules:**

1. Handles anonymous and unregistered customers
2. Creates minimal customer records for public orders
3. Validates mandatory attendee properties per business settings
4. Supports guest checkout scenarios
5. Maintains privacy for public customers

**Process Flow:**

1. Validate attendee information against business booking settings
2. For each public attendee:
   * Check if customer exists by contact information
   * Create unregistered customer if sufficient information provided
   * Create anonymous customer for minimal information
   * Apply business mandatory property requirements
3. Return processed attendee list for order creation

**Mandatory Property Validation:**

```typescript
// Validate mandatory attendee properties
const mandatoryProperties = bookingSettings.mandatoryAttendeeProperties || [AttendeePropertyEnum.email];

attendees.forEach((attendee, index) => {
  const missingProperties = mandatoryProperties.filter(prop =>
    attendee[prop] === undefined || attendee[prop] === null || attendee[prop] === ''
  );

  if (missingProperties.length > 0) {
    throw new ValidationException(
      `Attendee #${index + 1} is missing mandatory properties: ${missingProperties.join(', ')}`
    );
  }
});
```

***

## Payment Integration Use Cases

### 8. ProcessPaymentCustomerUseCase

**Purpose:** Handles customer information during payment processing with customer creation as needed.

**Input:** `ProcessPaymentCustomerParams`

```typescript
{
  tenantId: string,
  payerInfo: CustomerDto,
  actor: ActorDto
}
```

**Output:** `CustomerDto` (Processed payer information)

**Business Rules:**

1. Creates customer record for payment if not exists
2. Validates payer information for payment processing
3. Maintains customer snapshots in payment records
4. Supports guest payment scenarios
5. Links payment history to customer records

**Process Flow:**

1. Validate payer information format
2. Search for existing customer by email/phone
3. If customer exists, update payment-relevant information
4. If customer doesn't exist, create new customer record
5. Return customer information for payment processing

**Payment Customer Creation:**

```typescript
// Check if customer exists for payment
const existingCustomer = await this.sharedUnitOfWork.customers.findCustomerByEmailOrPhone(
  payment.payer.email,
  payment.payer.phone
);

if (!existingCustomer) {
  // Create customer for payment
  const customerDomain = Customer.createRegular(
    CustomerMap.toPersistenceFromDto(payment.payer)
  );

  if (customerDomain.isSuccessResult()) {
    await this.sharedUnitOfWork.customers.createCustomer(payment.payer);
  }
}
```

***

## Query Handlers

### GetCustomerByIdHandler

**Responsibilities:**

1. Customer retrieval with tenant filtering
2. State validation and access control
3. Data transformation to DTO format
4. Cache management and optimization

**Implementation:**

```typescript
async execute(query: GetCustomerByIdQuery): Promise<CustomerDto | null> {
  try {
    const customer = await this.sharedUnitOfWork.customers.findCustomerById(
      query.customerId,
      query.tenantId
    );

    if (!customer) {
      return null;
    }

    // Validate customer state
    if (customer.state === 'deleted') {
      return null;
    }

    return CustomerMap.toDto(customer);
  } catch (error) {
    this.logger.error(`Error getting customer by id: ${query.customerId}`, error);
    throw error;
  }
}
```

### GetPagedCustomersHandler

**Responsibilities:**

1. Advanced filtering and search implementation
2. Efficient pagination with cursor support
3. Sort optimization and index utilization
4. Result transformation and metadata

**Search Strategy:**

```typescript
// MongoDB search implementation
const searchFilter = query.search ? {
  $or: [
    { firstName: { $regex: query.search, $options: 'i' } },
    { lastName: { $regex: query.search, $options: 'i' } },
    { email: { $regex: query.search, $options: 'i' } },
    { 
      $expr: {
        $regexMatch: {
          input: { $concat: ['$firstName', ' ', '$lastName'] },
          regex: query.search,
          options: 'i'
        }
      }
    }
  ]
} : {};

const filter = {
  tenantId: query.tenantId,
  state: { $ne: 'deleted' },
  ...searchFilter,
  ...(query.customerType && { customerType: query.customerType })
};
```

### IsCustomerExistHandler

**Responsibilities:**

1. Duplicate customer detection
2. Email and phone uniqueness validation
3. Performance-optimized existence checks
4. Multi-field search support

**Existence Check:**

```typescript
async execute(query: IsCustomerExistQuery): Promise<boolean> {
  const filter: any = { tenantId: query.tenantId, state: { $ne: 'deleted' } };
  
  const orConditions = [];
  if (query.email) orConditions.push({ email: query.email });
  if (query.phone) orConditions.push({ phone: extractNumbers(query.phone) });
  
  if (orConditions.length > 0) {
    filter.$or = orConditions;
  }
  
  const count = await this.model.countDocuments(filter);
  return count > 0;
}
```

***

## Command Handlers

### AddRegularCustomerHandler

**Responsibilities:**

1. Domain entity creation and validation
2. Business rule enforcement
3. Database persistence with tenant ID
4. Event publishing and cache invalidation

**Customer Creation Process:**

```typescript
async execute(command: AddRegularCustomerCommand): Promise<string> {
  try {
    // Create domain entity with validation
    const customerDomain = Customer.createRegular({
      ...command.customer,
      customerType: CustomerTypeEnum.regular
    });

    if (customerDomain.isFailureResult()) {
      throw new CustomerCreationException(customerDomain.errorValue());
    }

    // Convert to persistence model
    const persistenceModel = CustomerMap.toPersistence(customerDomain.getValue());
    persistenceModel.tenantId = command.tenantId;

    // Persist to database
    const createdCustomer = await this.sharedUnitOfWork.customers.createCustomer(persistenceModel);

    // Publish event
    await this.messageQueueService.sendMessage(
      new CustomerAddedMessage({
        tenantId: command.tenantId,
        customer: CustomerMap.toDto(createdCustomer),
        createdBy: { /* actor info */ },
        timestamp: new Date().toISOString()
      })
    );

    return createdCustomer._id.toString();
  } catch (error) {
    this.logger.error('Error creating customer', error);
    throw new CustomerCreationException(error.message);
  }
}
```

### UpdateCustomerHandler

**Responsibilities:**

1. Customer existence validation
2. Partial update processing
3. Domain validation enforcement
4. Optimistic locking support

### DeleteCustomerHandler

**Responsibilities:**

1. Soft delete implementation
2. Dependency validation
3. State history maintenance
4. Cleanup operations

***

## Domain Validation Rules

### Customer Entity Validation

```typescript
// Customer creation validation
static create(props: ICustomer): Result<Customer> {
  const validationErrors: string[] = [];

  // Validate mandatory fields
  const requiredFields: (keyof ICustomer)[] = ['firstName', 'lastName', 'phone', 'email', 'customerType'];
  const fieldValidation = this.validateMandatoryFields(props, requiredFields);
  if (fieldValidation.isFailureResult()) {
    validationErrors.push(fieldValidation.errorValue());
  }

  // Validate email format
  const emailValidation = this.validateEmail(props.email);
  if (emailValidation.isFailureResult()) {
    validationErrors.push(emailValidation.errorValue());
  }

  // Validate phone format
  const phoneValidation = this.validatePhone(props.phone);
  if (phoneValidation.isFailureResult()) {
    validationErrors.push(phoneValidation.errorValue());
  }

  if (validationErrors.length > 0) {
    return Result.fail<Customer>(validationErrors.join('\n'));
  }

  // Normalize phone number
  if (props.phone) {
    props.phone = extractNumbers(props.phone);
  }

  return Result.ok(new Customer(props));
}

// Regular customer validation (stricter rules)
static createRegular(props: ICustomer): Result<Customer> {
  const validationErrors: string[] = [];

  // Validate mandatory fields for regular customers
  const requiredFields: (keyof ICustomer)[] = ['phone', 'email'];
  const fieldValidation = this.validateMandatoryFields(props, requiredFields);
  if (fieldValidation.isFailureResult()) {
    validationErrors.push(fieldValidation.errorValue());
  }

  const emailValidation = this.validateEmail(props.email);
  if (emailValidation.isFailureResult()) {
    validationErrors.push(emailValidation.errorValue());
  }

  const phoneValidation = this.validatePhone(props.phone);
  if (phoneValidation.isFailureResult()) {
    validationErrors.push(phoneValidation.errorValue());
  }

  if (validationErrors.length > 0) {
    return Result.fail<Customer>(validationErrors.join('\n'));
  }

  // Set customer type and normalize phone
  props.customerType = CustomerTypeEnum.regular;
  if (props.phone) {
    props.phone = extractNumbers(props.phone);
  }

  return Result.ok(new Customer(props));
}
```

### Validation Helper Methods

```typescript
// Email validation
private static validateEmail(email?: string): Result<void> {
  if (email && !/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(email)) {
    return Result.fail<void>('Invalid email format: ' + email);
  }
  return Result.ok();
}

// Phone validation
private static validatePhone(phone?: string): Result<void> {
  if (phone && !/^(\+?\d{1,3}[-.\s]?)?(\(?\d{1,4}\)?[-.\s]?)?\d{1,4}[-.\s]?\d{1,4}[-.\s]?\d{1,9}$/.test(phone)) {
    return Result.fail<void>('Invalid phone number format: ' + phone);
  }
  return Result.ok();
}

// Mandatory fields validation
private static validateMandatoryFields(props: ICustomer, fields: (keyof ICustomer)[]): Result<void> {
  const hasAtLeastOneProperty = fields.some(field => 
    props[field] !== undefined && props[field] !== '' && props[field] !== null
  );
  
  return hasAtLeastOneProperty ? 
    Result.ok() : 
    Result.fail<void>('At least one of the following properties must be provided: ' + fields.join(', '));
}
```

***

## Cache Management

### Cache Keys and Strategy

```typescript
// Cache key definitions
export enum CustomerCacheKeys {
  GET_CUSTOMER = 'customer:get',
  GET_PAGED_CUSTOMERS = 'customer:paged',
  CUSTOMER_SEARCH = 'customer:search',
  CUSTOMER_VALIDATION = 'customer:validation'
}

// Cache TTL settings
const CACHE_TTL = {
  CUSTOMER_DETAILS: 300,    // 5 minutes
  CUSTOMER_LIST: 60,        // 1 minute  
  SEARCH_RESULTS: 180,      // 3 minutes
  VALIDATION_RESULTS: 600   // 10 minutes
};
```

### Cache Invalidation Strategy

```typescript
// Customer update invalidates related caches
@DeleteCache([
  CustomerCacheKeys.GET_CUSTOMER,
  CustomerCacheKeys.GET_PAGED_CUSTOMERS,
  CustomerCacheKeys.CUSTOMER_SEARCH
])
async updateCustomer(command: UpdateCustomerCommand): Promise<void> {
  // Update implementation
}

// Smart cache invalidation based on changes
private async invalidateCustomerCaches(tenantId: string, customerId: string, changedFields: string[]) {
  // Always invalidate customer detail cache
  await this.cacheService.delete(`${CustomerCacheKeys.GET_CUSTOMER}:${tenantId}:${customerId}`);
  
  // Invalidate search cache if searchable fields changed
  const searchableFields = ['firstName', 'lastName', 'email'];
  if (changedFields.some(field => searchableFields.includes(field))) {
    await this.cacheService.deletePattern(`${CustomerCacheKeys.CUSTOMER_SEARCH}:${tenantId}:*`);
  }
  
  // Invalidate paged results cache
  await this.cacheService.deletePattern(`${CustomerCacheKeys.GET_PAGED_CUSTOMERS}:${tenantId}:*`);
}
```

***

## Permission Integration

### Permission Validation

All customer use cases integrate with the `PermissionValidatorUseCase`:

```typescript
await this.permissionValidator.execute({
  actor: ctx.actor,
  requiredPermissions: [ModulePermissionEnum.CREATE_CUSTOMER],
});
```

### Required Permissions

* **READ\_CUSTOMER**: View customer information and lists
* **CREATE\_CUSTOMER**: Create new customer records
* **EDIT\_CUSTOMER**: Modify existing customer information
* **DELETE\_CUSTOMER**: Delete customer records

### Permission Matrix

| Operation           | Permission       | Scope  | Notes                        |
| ------------------- | ---------------- | ------ | ---------------------------- |
| Get Customer        | READ\_CUSTOMER   | Tenant | Read access to customer data |
| Get Paged Customers | READ\_CUSTOMER   | Tenant | List and search customers    |
| Create Customer     | CREATE\_CUSTOMER | Tenant | Create new customer records  |
| Update Customer     | EDIT\_CUSTOMER   | Tenant | Modify customer information  |
| Delete Customer     | DELETE\_CUSTOMER | Tenant | Soft delete customer records |
| Add Attendees       | EDIT\_CUSTOMER   | Tenant | Process order attendees      |

***

## Error Handling

### Exception Types

```typescript
// Customer-specific exceptions
export class CustomerNotFoundException extends NotFoundException {
  constructor(customerId: string) {
    super(`Customer not found: ${customerId}`);
  }
}

export class CustomerCreationException extends BadRequestException {
  constructor(message: string) {
    super(`Customer creation failed: ${message}`);
  }
}

export class CustomerAlreadyExistsException extends ConflictException {
  constructor(field: string, value: string) {
    super(`Customer already exists with ${field}: ${value}`);
  }
}

export class CustomerValidationException extends BadRequestException {
  constructor(errors: string[]) {
    super(`Customer validation failed: ${errors.join(', ')}`);
  }
}
```

### Error Logging

All use cases implement comprehensive error logging:

```typescript
catch (error) {
  this.logger.error('Error in customer operation', {
    operation: 'createCustomer',
    tenantId: ctx.tenantId,
    customerId: customer._id,
    error: error.message,
    stack: error.stack
  });
  throw error;
}
```

***

## Testing Considerations

### Unit Testing

```typescript
describe('CreateCustomerUseCase', () => {
  test('should create customer with valid data', async () => {
    const customer = {
      firstName: 'John',
      lastName: 'Doe',
      email: 'john.doe@example.com',
      phone: '+1234567890'
    };

    const customerId = await createCustomerUseCase.execute({
      ctx: mockContext,
      customer
    });

    expect(customerId).toBeDefined();
    expect(mockCommandBus.execute).toHaveBeenCalledWith(
      expect.any(AddRegularCustomerCommand)
    );
  });

  test('should validate mandatory fields', async () => {
    const invalidCustomer = {};

    await expect(
      createCustomerUseCase.execute({
        ctx: mockContext,
        customer: invalidCustomer
      })
    ).rejects.toThrow('At least one field must be filled');
  });

  test('should validate email format', async () => {
    const customer = {
      firstName: 'John',
      email: 'invalid-email'
    };

    await expect(
      createCustomerUseCase.execute({
        ctx: mockContext,
        customer
      })
    ).rejects.toThrow('Invalid email format');
  });
});
```

### Integration Testing

```typescript
describe('Customer Integration Tests', () => {
  test('should create customer and retrieve by ID', async () => {
    // Create customer
    const customerId = await createCustomerUseCase.execute({
      ctx: testContext,
      customer: testCustomerData
    });

    // Retrieve customer
    const retrievedCustomer = await getCustomerUseCase.execute({
      ctx: testContext,
      customerId
    });

    expect(retrievedCustomer._id).toBe(customerId);
    expect(retrievedCustomer.email).toBe(testCustomerData.email);
  });

  test('should handle order attendee creation', async () => {
    const attendees = [{
      customer: {
        firstName: 'Jane',
        lastName: 'Smith',
        email: 'jane.smith@example.com'
      }
    }];

    const processedAttendees = await commandBus.execute(
      new AddAttendeesCommand(tenantId, attendees)
    );

    expect(processedAttendees).toHaveLength(1);
    expect(processedAttendees[0].customer._id).toBeDefined();
    expect(processedAttendees[0].firstTime).toBe(true);
  });
});
```

***

## Business Workflow Integration

### Customer Lifecycle Workflow

1. **Customer Creation**: Initial customer registration or first order
2. **Profile Completion**: Adding additional information and preferences
3. **Order Association**: Linking customers to orders as payers and attendees
4. **Payment Processing**: Customer information in payment records
5. **Relationship Management**: Ongoing customer interaction and updates

### Order Integration Workflow

1. **Attendee Processing**: Convert order attendees to customer records
2. **Customer Matching**: Find existing customers or create new ones
3. **Snapshot Creation**: Preserve customer data in order records
4. **First-Time Detection**: Mark new customers for special handling
5. **History Tracking**: Maintain customer order history

### Payment Integration Workflow

1. **Payer Identification**: Link payment to customer record
2. **Customer Creation**: Create customer if not exists for payment
3. **Payment History**: Track customer payment patterns
4. **Billing Information**: Manage customer billing preferences

***

## Performance Considerations

### Database Optimization

1. **Indexing Strategy**: Optimize for common query patterns
2. **Query Optimization**: Efficient filtering and sorting
3. **Batch Processing**: Handle bulk customer operations
4. **Connection Pooling**: Manage database connections efficiently

### Query Patterns

```typescript
// Optimized customer search with indexes
db.customer.createIndex({ 
  tenantId: 1, 
  email: 1 
}, { 
  sparse: true 
});

db.customer.createIndex({ 
  tenantId: 1, 
  phone: 1 
}, { 
  sparse: true 
});

db.customer.createIndex({
  tenantId: 1,
  firstName: 'text',
  lastName: 'text',
  email: 'text'
});

// Compound index for pagination
db.customer.createIndex({
  tenantId: 1,
  state: 1,
  createdAt: -1
});
```

### Memory Management

1. **Selective Field Projection**: Load only required fields
2. **Streaming Results**: Handle large result sets efficiently
3. **Cache Optimization**: Balance memory usage and performance
4. **Connection Management**: Proper resource cleanup

***

## Security Considerations

### Data Protection

1. **PII Handling**: Secure processing of personal information
2. **Encryption**: Protect sensitive customer data
3. **Access Logging**: Track customer data access
4. **Data Retention**: Comply with retention policies

### Privacy Compliance

1. **GDPR Support**: Data portability and deletion rights
2. **Consent Management**: Track customer consent preferences
3. **Data Minimization**: Store only necessary information
4. **Audit Trail**: Complete change history for compliance

### Access Control

1. **Permission Validation**: Enforce role-based access
2. **Tenant Isolation**: Strict multi-tenant data separation
3. **Rate Limiting**: Prevent abuse and DoS attacks
4. **Input Validation**: Sanitize all customer inputs

***

## Business Rules Summary

### Customer Data Rules

1. **Mandatory Information**: At least one identifying field required
2. **Data Validation**: Email and phone format validation
3. **Normalization**: Phone numbers stored in normalized format
4. **Uniqueness**: Prevent duplicate customers per tenant
5. **State Management**: Soft deletion preserves historical data

### Order Integration Rules

1. **Attendee Matching**: Smart customer matching by email/phone
2. **Customer Creation**: Automatic customer creation for orders
3. **Snapshot Preservation**: Historical customer data in orders
4. **First-Time Tracking**: Identify new customer visits
5. **Multi-Attendee Support**: Multiple customers per order service

### Business Logic Rules

1. **Tenant Isolation**: Complete data separation per business
2. **Permission Enforcement**: Role-based operation access
3. **Cache Consistency**: Proper cache invalidation on updates
4. **Event Publishing**: Async notification of customer changes
5. **Error Recovery**: Graceful handling of validation and system errors

***

## Future Enhancements

### Planned Features

1. **Customer Segmentation**: Advanced customer categorization
2. **Preference Management**: Detailed customer preferences
3. **Communication History**: Track all customer interactions
4. **Analytics Integration**: Customer behavior analysis
5. **Loyalty Programs**: Customer loyalty and rewards
6. **Marketing Automation**: Automated customer communication

### Scalability Improvements

1. **Read Replicas**: Optimize read performance
2. **Sharding Strategy**: Handle large customer datasets
3. **Event Sourcing**: Complete audit trail with events
4. **CQRS Optimization**: Separate read/write models
5. **Microservice Decomposition**: Split by business domains

***

## Summary

The Customer Management use cases provide a comprehensive foundation for handling customer operations within the Bee O'clock ecosystem. Key capabilities include:

* **Complete Customer Lifecycle**: From creation to deletion with validation
* **Order Integration**: Seamless customer handling in order processing
* **Payment Integration**: Customer information in payment workflows
* **Advanced Search**: Efficient customer discovery and management
* **Multi-Tenant Security**: Proper data isolation and access control
* **Performance Optimization**: Caching and efficient query patterns
* **Business Rule Enforcement**: Comprehensive validation and business logic
* **Event-Driven Architecture**: Async communication for scalability

The use cases support complex business scenarios while maintaining high performance, data integrity, and security standards across the customer management domain.
