# Kiến Trúc Wallet Service

## Tổng Quan

Wallet Service quản lý ví điện tử và tài khoản điểm thưởng cho GoodGo Platform.

```mermaid
flowchart TB
    subgraph API["🌐 API Layer"]
        Controllers["Controllers"]
        Commands["Commands"]
        Queries["Queries"]
    end
    
    subgraph Domain["💎 Domain Layer"]
        Wallet["Wallet Aggregate"]
        PointAccount["PointAccount Aggregate"]
    end
    
    subgraph Infra["⚙️ Infrastructure Layer"]
        Repos["Repositories"]
        EF["EF Core"]
    end
    
    subgraph DB["💾 PostgreSQL"]
        Tables["Tables"]
    end
    
    API --> Domain
    Domain --> Infra
    Infra --> DB
    
    style API fill:#3498DB,color:#ECF0F1,stroke:#2980B9,stroke-width:3px
    style Domain fill:#8E44AD,color:#ECF0F1,stroke:#7D3C98,stroke-width:2px
    style Infra fill:#E67E22,color:#ECF0F1,stroke:#D35400,stroke-width:2px
    style DB fill:#34495E,color:#ECF0F1,stroke:#2C3E50,stroke-width:2px
```

## Các Pattern Kiến Trúc

### Domain-Driven Design (DDD)

- **Aggregates**: Wallet, PointAccount
- **Entities**: WalletTransaction, PointTransaction, HoldItem, WalletItem
- **Value Objects**: Money, CurrencyType
- **Domain Events**: WalletCreated, BalanceChanged, PointsEarned, EscrowHeld, EscrowExecuted

### CQRS Pattern

```mermaid
flowchart LR
    subgraph Commands["Commands (Ghi)"]
        C1["CreateWallet"]
        C2["Deposit/Withdraw"]
        C3["Exchange"]
        C4["Hold/Execute/Release"]
        C5["EarnPoints/SpendPoints"]
        C6["Admin Commands"]
    end
    
    subgraph Queries["Queries (Đọc)"]
        Q1["GetWallet"]
        Q2["GetTransactions"]
        Q3["GetPointAccount"]
        Q4["GetStatistics"]
        Q5["Admin Queries"]
    end
    
    style Commands fill:#27AE60,color:#ECF0F1,stroke:#229954,stroke-width:2px
    style Queries fill:#3498DB,color:#ECF0F1,stroke:#2980B9,stroke-width:2px
```

## Domain Model

### Wallet Aggregate

```mermaid
classDiagram
    class Wallet {
        +Guid Id
        +Guid UserId
        +WalletStatus Status
        +CurrencyType DefaultCurrency
        +List~WalletItem~ Items
        +List~HoldItem~ Holds
        +Deposit(amount, currency, desc, ref)
        +Withdraw(amount, currency, desc, ref)
        +Exchange(fromAmount, fromCurrency, toCurrency)
        +Hold(amount, currency, refType, refId, desc)
        +ExecuteHold(holdId, amount, ref)
        +ReleaseHold(holdId, amount)
        +Freeze()
        +Unfreeze()
    }
    
    class WalletItem {
        +Guid Id
        +CurrencyType Currency
        +decimal Balance
        +decimal HeldBalance
        +decimal AvailableBalance
    }
    
    class HoldItem {
        +Guid Id
        +decimal OriginalAmount
        +decimal RemainingAmount
        +decimal ExecutedAmount
        +decimal ReleasedAmount
        +HoldStatus Status
        +string ReferenceType
        +Guid ReferenceId
        +Execute(amount, ref)
        +Release(amount)
        +Cancel()
    }
    
    class WalletTransaction {
        +Guid Id
        +TransactionType Type
        +decimal Amount
        +CurrencyType Currency
        +decimal BalanceAfter
        +string Description
        +DateTime CreatedAt
    }
    
    class CurrencyType {
        +int Id
        +string Name
        +decimal BaseExchangeRate
        +VND
        +USD
        +PPoint
        +GetExchangeRateTo(currency)
        +ConvertTo(amount, currency)
    }
    
    Wallet "1" --> "*" WalletItem
    Wallet "1" --> "*" HoldItem
    Wallet "1" --> "*" WalletTransaction
    WalletItem --> CurrencyType
    HoldItem --> CurrencyType
```

### PointAccount Aggregate

```mermaid
classDiagram
    class PointAccount {
        +Guid Id
        +Guid UserId
        +long TotalPoints
        +long AvailablePoints
        +long PendingPoints
        +EarnPoints(points, source, desc, expires)
        +SpendPoints(points, source, desc)
        +AdjustPoints(points, source, desc)
    }
    
    class PointTransaction {
        +Guid Id
        +PointTransactionType Type
        +long Points
        +long BalanceAfter
        +string Source
        +DateTime? ExpiresAt
    }
    
    PointAccount "1" --> "*" PointTransaction
```

## Database Schema

### Các Bảng

| Bảng | Mô Tả |
|------|-------|
| `Wallets` | Tài khoản ví người dùng |
| `WalletItems` | Số dư tiền tệ mỗi ví |
| `WalletTransactions` | Lịch sử giao dịch ví |
| `HoldItems` | Các lệnh ký quỹ |
| `PointAccounts` | Tài khoản điểm người dùng |
| `PointTransactions` | Lịch sử giao dịch điểm |

### Indexes Chính

- `IX_Wallets_UserId` - Tra cứu theo user
- `IX_WalletItems_WalletId_CurrencyTypeId` - Số dư theo tiền tệ
- `IX_WalletTransactions_WalletId` - Lịch sử giao dịch
- `IX_HoldItems_WalletId_Status` - Các hold đang hoạt động
- `IX_PointAccounts_UserId` - Tra cứu theo user

## API Flow

### Luồng Nạp Tiền

```mermaid
sequenceDiagram
    participant C as Client
    participant API as Controller
    participant H as Handler
    participant W as Wallet
    participant DB as Database
    
    C->>API: POST /wallets/{userId}/deposit
    API->>H: DepositCommand
    H->>W: wallet.Deposit(amount)
    W->>W: Tạo Transaction
    W->>W: Raise DomainEvent
    H->>DB: SaveChanges
    DB-->>API: Thành công
    API-->>C: Số dư cập nhật
```

### Luồng Escrow

```mermaid
sequenceDiagram
    participant C as Client
    participant API as Controller
    participant W as Wallet
    participant H as HoldItem
    
    C->>API: POST /holds (Tạo)
    API->>W: wallet.Hold(amount)
    W->>H: Tạo HoldItem
    W-->>C: HoldId
    
    C->>API: POST /holds/{id}/execute
    API->>W: wallet.ExecuteHold(id, amount)
    W->>H: hold.Execute(amount)
    H-->>C: Số tiền đã thực thi
    
    C->>API: POST /holds/{id}/release
    API->>W: wallet.ReleaseHold(id, amount)
    W->>H: hold.Release(amount)
    H-->>C: Số tiền đã giải phóng
```

### Luồng Quy Đổi Tiền Tệ

```mermaid
sequenceDiagram
    participant C as Client
    participant API as Controller
    participant W as Wallet
    participant CT as CurrencyType
    
    C->>API: POST /exchange
    API->>W: wallet.Exchange(100 USD, VND)
    W->>CT: GetExchangeRate(USD → VND)
    CT-->>W: Tỷ giá = 25000
    W->>W: Rút 100 USD
    W->>W: Nạp 2.500.000 VND
    W->>W: Raise WalletExchangedEvent
    W-->>C: Kết quả quy đổi
```

## Domain Events

| Event | Kích Hoạt | Dữ Liệu |
|-------|-----------|---------|
| `WalletCreatedDomainEvent` | Tạo ví | WalletId, UserId |
| `WalletBalanceChangedDomainEvent` | Nạp/Rút | WalletId, Amount, Type |
| `WalletExchangedDomainEvent` | Quy đổi tiền tệ | FromCurrency, ToCurrency, Rate |
| `EscrowHeldDomainEvent` | Tạo hold | HoldId, Amount, RefType |
| `EscrowExecutedDomainEvent` | Thực thi hold | HoldId, Amount |
| `EscrowReleasedDomainEvent` | Giải phóng hold | HoldId, Amount |
| `PointsEarnedDomainEvent` | Tích điểm | AccountId, Points |
| `PointsSpentDomainEvent` | Tiêu điểm | AccountId, Points |

## Tích Hợp Giữa Các Service

### Tích Hợp IAM Service

```mermaid
flowchart LR
    WS["🔐 Wallet Service"] --> IAM["👤 IAM Service"]
    IAM --> UV["Xác thực User"]
    IAM --> JV["Kiểm tra JWT"]
    
    style WS fill:#3498DB,color:#ECF0F1,stroke:#2980B9,stroke-width:2px
    style IAM fill:#8E44AD,color:#ECF0F1,stroke:#7D3C98,stroke-width:2px
    style UV fill:#27AE60,color:#ECF0F1,stroke:#229954,stroke-width:2px
    style JV fill:#27AE60,color:#ECF0F1,stroke:#229954,stroke-width:2px
```

### Luồng Xác Thực

1. Client gửi JWT token trong Authorization header
2. Wallet Service xác thực JWT với IAM Service
3. Trích xuất userId từ JWT claims
4. Xử lý thao tác ví cho user

## Triển Khai

### Cấu Hình Docker Compose

```yaml
wallet-service:
  build:
    context: ../..
    dockerfile: services/wallet-service-net/Dockerfile
  environment:
    - DATABASE_URL=${WALLET_DATABASE_URL}
    - JWT_AUTHORITY=${IAM_SERVICE_URL}
  labels:
    - traefik.http.routers.wallet.rule=PathPrefix(`/api/v1/wallets`)
```

### Health Checks

| Endpoint | Kiểm Tra |
|----------|----------|
| `/health/live` | Service đang chạy |
| `/health/ready` | Database kết nối |
| `/health` | Trạng thái đầy đủ |

## Bảo Mật

### Xác Thực
- Xác thực JWT Bearer token
- Tích hợp IAM Service

### Phân Quyền
- User chỉ truy cập được ví của mình
- Admin endpoints yêu cầu role Admin/SuperAdmin

### Bảo Vệ Dữ Liệu
- Lưu số tiền với độ chính xác cao
- Audit trail giao dịch
- Soft delete cho ví

## Hiệu Năng

### Tối Ưu
- Connection pooling (EF Core)
- Index cho các queries thường xuyên
- Phân trang cho lịch sử giao dịch

### Mở Rộng
- Horizontal scaling với load balancer
- Read replicas cho queries
- Redis caching (tương lai)

## Giám Sát

### Metrics
- Thời gian request
- Số lượng giao dịch
- Tỷ lệ lỗi

### Logging
- Serilog structured logging
- Correlation IDs cho tracing
- Tích hợp Seq/Loki
