# Tài liệu Tham chiếu Nhanh cho Ghi nhật ký Kiểm toán Module Admin

## ĐỌC TRƯỚC (tổng cộng 15 phút)

### 1. Các Controller Chính (Xác định những hành động cần kiểm toán)
- ✅ `apps/api/src/modules/admin/presentation/controllers/admin.controller.ts` (155 dòng)
  - Quản lý người dùng: cấm, cập nhật trạng thái, điều chỉnh gói đăng ký
  - Tất cả các endpoint đều có decorator @CurrentUser() để ghi lại ID admin
  
- ✅ `apps/api/src/modules/admin/presentation/controllers/admin-moderation.controller.ts` (157 dòng)
  - Duyệt/từ chối tin đăng
  - Duyệt/từ chối KYC
  - Kiểm duyệt hàng loạt

### 2. Các Command Handler (Nơi để gắn ghi nhật ký kiểm toán)
Mỗi command phát ra một sự kiện domain. Listener ghi nhật ký kiểm toán nên lắng nghe các sự kiện này.

**Luồng Cấm Người Dùng:**
- Đầu vào: `apps/api/src/modules/admin/presentation/dto/ban-user.dto.ts`
- Command: `apps/api/src/modules/admin/application/commands/ban-user/ban-user.command.ts`
- Handler: `apps/api/src/modules/admin/application/commands/ban-user/ban-user.handler.ts` (70 dòng)
  - Dòng 62: `this.eventBus.publish(new UserBannedEvent(...))`

**Luồng Duyệt Tin Đăng:**
- Đầu vào: `apps/api/src/modules/admin/presentation/dto/approve-listing.dto.ts`
- Command: `apps/api/src/modules/admin/application/commands/approve-listing/approve-listing.command.ts`
- Handler: `apps/api/src/modules/admin/application/commands/approve-listing/approve-listing.handler.ts` (52 dòng)
  - Dòng 42-44: `this.eventBus.publish(new ListingApprovedEvent(...))`

### 3. Các Sự kiện Domain (Thông tin được phát ra)
```
apps/api/src/modules/admin/domain/events/
  ├── user-banned.event.ts
  ├── user-unbanned.event.ts
  ├── listing-approved.event.ts
  ├── listing-rejected.event.ts
  ├── subscription-adjusted.event.ts
  ├── kyc-approved.event.ts
  └── kyc-rejected.event.ts
```

Mỗi sự kiện có:
- `eventName` (ví dụ: 'user.banned')
- `occurredAt` (dấu thời gian)
- `aggregateId` (userId hoặc listingId)
- `adminId` (admin đã thực hiện hành động)
- Ngữ cảnh bổ sung (lý do, ghi chú, v.v.)

### 4. Mẫu Event Listener Hiện có (Template)
- ✅ `apps/api/src/modules/admin/application/listeners/user-banned.listener.ts` (52 dòng)
  - Minh hoạ decorator @OnEvent()
  - Minh hoạ cách truy cập dữ liệu sự kiện
  - Minh hoạ các hiệu ứng phụ (vô hiệu hoá tin đăng, gửi thông báo)
  - **ĐÂY LÀ TEMPLATE CHO AUDIT LOGGING LISTENER CỦA BẠN**

### 5. Logger Service (Nơi ghi log)
- ✅ `apps/api/src/modules/shared/infrastructure/logger.service.ts` (65 dòng)
  - Ghi log có cấu trúc dựa trên Pino
  - Tự động che giấu thông tin PII
  - Các phương thức: log(), error(), warn(), debug(), verbose()

### 6. Exception Filter (Để ghi log lỗi)
- ✅ `apps/api/src/modules/shared/infrastructure/filters/global-exception.filter.ts` (145 dòng)
  - Bắt tất cả các ngoại lệ
  - Ghi log kèm correlationId
  - Có thể ghi lại các hành động admin thất bại

---

## THAM CHIẾU KIẾN TRÚC

### Mẫu Repository
- Giao diện Domain: `apps/api/src/modules/admin/domain/repositories/admin-query.repository.ts`
- Triển khai Prisma: `apps/api/src/modules/admin/infrastructure/repositories/prisma-admin-query.repository.ts`
- **TUÂN THEO MẪU NÀY** cho AuditLog repository

### Khởi tạo Module
- `apps/api/src/modules/admin/admin.module.ts` (64 dòng)
  - Minh hoạ cách đăng ký repository qua DI
  - Minh hoạ cách đăng ký listener
  - Minh hoạ cách import CQRS module

### Cấu hình App Toàn cục
- `apps/api/src/app.module.ts` (100+ dòng)
  - Minh hoạ đăng ký APP_FILTER, APP_GUARD, APP_INTERCEPTOR
  - Minh hoạ cấu hình CqrsModule.forRoot()
  - Minh hoạ cấu hình middleware

---

## PRISMA SCHEMA

### Các Model Hiện tại (Những gì chúng ta đang kiểm toán)
- `prisma/schema.prisma` (602 dòng tổng cộng)

**User Model** (dòng 34-71):
- Các trường cần kiểm toán: isActive, kycStatus, role

**Listing Model** (dòng 227-276):
- Các trường cần kiểm toán: status, moderationScore, moderationNotes

**CHƯA CÓ AUDIT MODEL** - Cơ hội để tạo từ đầu

---

## CÁC ENDPOINT CẦN KIỂM TOÁN (Từ Controllers)

### Hành động của AdminController:
1. `PATCH /admin/users/status` - Cập nhật trạng thái hoạt động của người dùng
2. `POST /admin/users/ban` - Cấm/bỏ cấm người dùng
3. `POST /admin/subscriptions/adjust` - Điều chỉnh gói đăng ký

### Hành động của AdminModerationController:
1. `POST /admin/moderation/approve` - Duyệt tin đăng
2. `POST /admin/moderation/reject` - Từ chối tin đăng
3. `POST /admin/moderation/bulk` - Kiểm duyệt hàng loạt tin đăng
4. `POST /admin/kyc/approve` - Duyệt KYC
5. `POST /admin/kyc/reject` - Từ chối KYC

Mỗi hành động:
- Đã ghi lại ID admin từ JWT
- Đã phát ra sự kiện domain
- Đã có command handler
- Cần: Audit logging listener để lưu vào cơ sở dữ liệu

---

## CÁC PHỤ THUỘC ĐÃ ĐƯỢC IMPORT

### Trong AdminModule:
```typescript
// Đã sẵn sàng:
- CqrsModule (from @nestjs/cqrs)
- AuthModule (auth guards/decorators)
- ListingsModule (for listing operations)
- SubscriptionsModule (for subscription operations)

// Trong providers:
- CommandHandlers (8 tổng cộng)
- QueryHandlers (6 tổng cộng)
- Event Listeners (2 hiện có + cần thêm AuditLoggingListener)
```

### Từ SharedModule:
- `PrismaService` (cơ sở dữ liệu)
- `LoggerService` (ghi log)
- Các loại ngoại lệ (NotFoundException, ValidationException, v.v.)

---

## DANH SÁCH KIỂM TRA TRIỂN KHAI

### Giai đoạn 1: Cơ sở dữ liệu & Repository
- [ ] Tạo AuditLog Prisma model trong schema.prisma
- [ ] Tạo interface IAuditLogRepository
- [ ] Tạo triển khai PrismaAuditLogRepository
- [ ] Thêm vào providers của AdminModule

### Giai đoạn 2: Events & Listeners
- [ ] Tạo AuditEvent domain event (nếu cần làm wrapper)
- [ ] Tạo AuditLoggingListener để @OnEvent() cho tất cả các sự kiện admin
- [ ] Inject AuditLogRepository vào listener
- [ ] Lưu bản ghi kiểm toán khi có sự kiện

### Giai đoạn 3: Query & API
- [ ] Tạo GetAuditLogsQuery
- [ ] Tạo GetAuditLogsHandler
- [ ] Tạo phương thức IAuditLogQueryRepository
- [ ] Thêm vào QueryHandlers trong module

### Giai đoạn 4: Endpoint Controller
- [ ] Thêm endpoint GET /admin/audit-logs
- [ ] Thêm các DTO lọc (dateRange, adminId, actionType, resourceId)
- [ ] Thêm hỗ trợ phân trang

### Giai đoạn 5: Kiểm thử
- [ ] Unit tests cho AuditLoggingListener
- [ ] Integration tests cho việc lưu kiểm toán
- [ ] E2E tests cho việc truy xuất nhật ký kiểm toán

---

## CÁC MẪU QUAN TRỌNG CẦN TUÂN THEO

### 1. Command Pattern (Đã được sử dụng)
```typescript
// DTO xác thực đầu vào
// Command đóng gói ý định nghiệp vụ
// Handler thực thi + phát sự kiện
// Event kích hoạt hiệu ứng phụ qua listener
```

### 2. Cấu trúc Tầng DDD
```
Presentation (xác thực DTO)
    ↓
Application (thực thi Command/Query + phát Event)
    ↓
Domain (định nghĩa Event, giao diện Repository)
    ↓
Infrastructure (triển khai cơ sở dữ liệu)
```

### 3. Dependency Injection
```typescript
// Luôn dùng Symbol cho token:
export const AUDIT_LOG_REPOSITORY = Symbol('AUDIT_LOG_REPOSITORY');

// Đăng ký trong module:
{ provide: AUDIT_LOG_REPOSITORY, useClass: PrismaAuditLogRepository }

// Inject vào service:
constructor(
  @Inject(AUDIT_LOG_REPOSITORY) private readonly auditRepo: IAuditLogRepository,
) {}
```

### 4. Mẫu Event Listener
```typescript
@Injectable()
export class AuditLoggingListener {
  constructor(
    @Inject(AUDIT_LOG_REPOSITORY) private readonly auditRepo: IAuditLogRepository,
    private readonly logger: LoggerService,
  ) {}

  @OnEvent('user.banned', { async: true })
  async handleUserBanned(event: UserBannedEvent): Promise<void> {
    // Trích xuất dữ liệu từ sự kiện
    // Lưu vào cơ sở dữ liệu
    // Ghi log nếu thành công/thất bại
  }
}
```

---

## NƠI THÊM CODE

```
apps/api/src/modules/admin/
├── domain/
│   ├── events/
│   │   └── audit-logged.event.ts (MỚI - wrapper tuỳ chọn)
│   └── repositories/
│       ├── audit-log.repository.ts (MỚI - interface)
│       └── index.ts (cập nhật exports)
│
├── application/
│   ├── queries/
│   │   ├── get-audit-logs/ (MỚI)
│   │   │   ├── get-audit-logs.query.ts
│   │   │   └── get-audit-logs.handler.ts
│   │   └── index.ts (cập nhật exports)
│   │
│   └── listeners/
│       ├── audit-logging.listener.ts (MỚI)
│       └── index.ts (cập nhật nếu cần)
│
├── infrastructure/
│   └── repositories/
│       ├── prisma-audit-log.repository.ts (MỚI)
│       └── index.ts (cập nhật exports)
│
└── presentation/
    ├── controllers/
    │   ├── admin.controller.ts (THÊM ENDPOINT)
    │   └── admin-moderation.controller.ts (CẬP NHẬT nếu cần)
    │
    └── dto/
        ├── get-audit-logs-query.dto.ts (MỚI)
        └── index.ts (cập nhật exports)

prisma/
└── schema.prisma (THÊM AuditLog MODEL)
```

---

## CÁC SỰ KIỆN CẦN LẮNG NGHE

1. 'user.banned' - từ UserBannedEvent
2. 'user.unbanned' - từ UserUnbannedEvent  
3. 'listing.approved' - từ ListingApprovedEvent
4. 'listing.rejected' - từ ListingRejectedEvent
5. 'kyc.approved' - từ KycApprovedEvent
6. 'kyc.rejected' - từ KycRejectedEvent
7. 'subscription.adjusted' - từ SubscriptionAdjustedEvent
8. 'user.deactivated' - (nếu tồn tại trong auth module)

Mỗi sự kiện được ghi lại kèm:
- ID Admin (từ sự kiện)
- ID Tài nguyên (aggregateId từ sự kiện)
- Loại Tài nguyên (suy ra từ eventName)
- Dấu thời gian (từ event.occurredAt)
- Ngữ cảnh bổ sung (lý do, ghi chú, v.v.)
