# Domain-Driven Design (DDD)

## Overview

The Building Management System implements Domain-Driven Design principles to organize complex business logic into cohesive, bounded contexts. Each domain represents a distinct business capability with its own models, services, and rules.

## Bounded Contexts

```
┌─────────────────────────────────────────────────────────────────────────────┐
│                         Building Management System                           │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│  ┌──────────────┐   ┌──────────────┐   ┌──────────────┐   ┌──────────────┐ │
│  │ Construction │   │  Accounting  │   │ Maintenance  │   │  Management  │ │
│  │    Domain    │   │    Domain    │   │    Domain    │   │    Domain    │ │
│  │              │   │              │   │              │   │              │
│  │ - Projects   │   │ - Invoices   │   │ - Assets     │   │ - Employees  │ │
│  │ - Materials  │   │ - Payments   │   │ - Visits     │   │ - Payroll    │ │
│  │ - Estimates  │   │ - Reports    │   │ - Checklists │   │ - Attendance │ │
│  └──────────────┘   └──────────────┘   └──────────────┘   └──────────────┘ │
│                                                                              │
│  ┌──────────────┐   ┌──────────────┐   ┌──────────────┐   ┌──────────────┐ │
│  │ Procurement  │   │   Catalog    │   │    Supply    │   │     CRM      │ │
│  │    Domain    │   │    Domain    │   │    Domain    │   │    Domain    │ │
│  │              │   │              │   │              │   │              │
│  │ - Suppliers  │   │ - Products   │   │ - Deliveries │   │ - Customers  │ │
│  │ - Orders     │   │ - Services   │   │ - Drivers    │   │ - Events     │ │
│  │ - Quotations │   │ - Inventory  │   │ - Tracking   │   │ - Contacts   │ │
│  └──────────────┘   └──────────────┘   └──────────────┘   └──────────────┘ │
│                                                                              │
│  ┌──────────────┐                                                           │
│  │     Core     │  (Shared Kernel - Cross-cutting concerns)                 │
│  │    Domain    │                                                           │
│  │              │                                                           │
│  │ - Users      │                                                           │
│  │ - Branches   │                                                           │
│  │ - Settings   │                                                           │
│  └──────────────┘                                                           │
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘
```

## Domain Structure

Each domain follows a consistent internal structure:

```
app/Domains/{DomainName}/
├── Models/                 # Eloquent models (Entities/Aggregates)
├── Services/               # Domain services
├── DTOs/                   # Data Transfer Objects
├── Events/                 # Domain events
├── Listeners/              # Event listeners
├── Policies/               # Authorization policies
├── Contracts/              # Repository interfaces
├── Observers/              # Model observers
├── Http/
│   ├── Controllers/        # Domain-specific controllers
│   └── Requests/           # Domain-specific form requests
├── Routes/                 # Domain route definitions
└── Database/
    ├── Migrations/         # Domain migrations
    └── Seeders/            # Domain seeders
```

## Domain Descriptions

### 1. Construction Domain

**Purpose**: Manages construction projects, cost estimation, and material tracking.

**Key Aggregates**:
- `Project` - Root aggregate for construction projects
- `CostEstimate` - Project cost estimations
- `MaterialRequisition` - Material requests for projects

**Relationships**:
- Consumes from: Catalog (products), Procurement (suppliers)
- Provides to: Accounting (invoices), Management (labor costs)

### 2. Accounting Domain

**Purpose**: Handles financial operations, invoicing, and reporting.

**Key Aggregates**:
- `Invoice` - Customer invoices
- `Payment` - Payment records
- `Account` - Chart of accounts
- `JournalEntry` - Financial transactions

**Relationships**:
- Consumes from: All domains (billable items)
- Provides to: Management (financial reports)

### 3. Maintenance Domain

**Purpose**: Manages asset maintenance, service visits, and inspections.

**Key Aggregates**:
- `MaintenanceAsset` - Equipment and assets
- `MaintenanceVisit` - Scheduled service visits
- `Checklist` - Inspection checklists
- `MaintenanceContract` - Service contracts

**Relationships**:
- Consumes from: CRM (customers), Catalog (parts)
- Provides to: Accounting (maintenance invoices)

### 4. Management Domain

**Purpose**: Human resources, payroll, and organizational management.

**Key Aggregates**:
- `Employee` - Employee records
- `PayrollRun` - Payroll processing
- `Attendance` - Time tracking
- `Leave` - Leave management
- `Recruitment` - Hiring pipeline

**Relationships**:
- Consumes from: Core (users), Accounting (salaries)
- Provides to: All domains (employee data)

### 5. Procurement Domain

**Purpose**: Supplier management, purchasing, and quotations.

**Key Aggregates**:
- `Supplier` - Supplier records
- `PurchaseOrder` - Purchase orders
- `Quotation` - Supplier quotations
- `GoodsReceipt` - Receiving inventory

**Relationships**:
- Consumes from: Catalog (products)
- Provides to: Accounting (payables), Supply (inventory)

### 6. Catalog Domain

**Purpose**: Product and service catalog management.

**Key Aggregates**:
- `Product` - Product definitions
- `Service` - Service definitions
- `Category` - Product categories
- `Unit` - Units of measure
- `Inventory` - Stock tracking

**Relationships**:
- Provides to: All domains (product/service data)

### 7. Supply Domain

**Purpose**: Supply chain, logistics, and delivery management.

**Key Aggregates**:
- `Delivery` - Delivery orders
- `Driver` - Driver management
- `Route` - Delivery routes
- `Warehouse` - Warehouse locations

**Relationships**:
- Consumes from: Procurement (goods), Catalog (products)
- Provides to: Accounting (delivery costs)

### 8. CRM Domain

**Purpose**: Customer relationship management.

**Key Aggregates**:
- `Customer` - Customer records
- `Contact` - Customer contacts
- `Event` - Customer events/interactions
- `Opportunity` - Sales opportunities

**Relationships**:
- Provides to: All customer-facing domains

### 9. Core Domain (Shared Kernel)

**Purpose**: Cross-cutting concerns shared across all domains.

**Key Aggregates**:
- `User` - System users
- `Branch` - Business branches
- `Setting` - System settings
- `Role` / `Permission` - Access control

**Relationships**:
- Provides to: All domains

## Domain Communication

### Synchronous Communication

Direct service calls within the same request:

```php
// Construction domain calling Catalog domain
class ProjectService
{
    public function __construct(
        private ProductService $productService
    ) {}

    public function addMaterial(Project $project, int $productId): void
    {
        $product = $this->productService->find($productId);
        // Add to project materials
    }
}
```

### Asynchronous Communication

Event-driven communication between domains:

```php
// Accounting domain listening to Procurement events
class InvoicePaymentListener
{
    public function handle(PurchaseOrderApproved $event): void
    {
        // Create payable invoice
    }
}
```

## Aggregate Design Rules

1. **Reference by Identity**: Aggregates reference other aggregates by ID only
2. **Transactional Boundary**: Each aggregate is a transactional boundary
3. **Consistency Boundary**: Invariants are enforced within the aggregate
4. **Root Entity**: External access only through the aggregate root

```php
// Good: Reference by ID
class MaintenanceVisit extends Model
{
    protected $fillable = ['customer_id', 'asset_id'];

    public function customer(): BelongsTo
    {
        return $this->belongsTo(Customer::class);
    }
}

// Avoid: Deep object graph manipulation
// $visit->customer->contacts[0]->email = 'new@email.com';
```

## Domain Events

Events communicate changes between domains:

```php
// Event definition
class OrderApproved
{
    public function __construct(
        public readonly int $orderId,
        public readonly int $customerId,
        public readonly float $totalAmount
    ) {}
}

// Publishing
event(new OrderApproved($order->id, $order->customer_id, $order->total));

// Listening (different domain)
class CreateInvoiceOnOrderApproval
{
    public function handle(OrderApproved $event): void
    {
        // Create invoice in Accounting domain
    }
}
```

## Best Practices

### Do

- Keep domains focused on single business capability
- Use DTOs for cross-domain data transfer
- Define clear contracts for domain interfaces
- Use events for loose coupling between domains
- Maintain domain-specific validation rules

### Don't

- Access another domain's database tables directly
- Create circular dependencies between domains
- Put business logic in controllers
- Bypass the aggregate root for modifications
- Share Eloquent models between domains without DTOs
