chore: update project documentation, audit reports, and initialize IDE configuration files
Some checks failed
CI / Lint → Typecheck → Test → Build (22) (push) Failing after 29s
CI / E2E Tests (push) Has been skipped
CodeQL Analysis / CodeQL (javascript-typescript) (push) Failing after 2m42s
Deploy / Build Web Image (push) Failing after 27s
Deploy / Build AI Services Image (push) Failing after 29s
E2E Tests / Playwright E2E (push) Failing after 43s
Deploy / Build API Image (push) Failing after 1m31s
Security Scanning / Dependency Audit (pnpm) (push) Failing after 6s
Security Scanning / Trivy Scan — API Image (push) Failing after 5m35s
Security Scanning / Trivy Scan — AI Services Image (push) Failing after 3m45s
Deploy / Deploy to Staging (push) Has been skipped
Deploy / Smoke Test Staging (push) Has been skipped
Deploy / Deploy to Production (push) Has been skipped
Deploy / Smoke Test Production (push) Has been skipped
Deploy / Rollback Staging (push) Has been skipped
Deploy / Rollback Production (push) Has been skipped
Security Scanning / Trivy Scan — Web Image (push) Failing after 13m51s
Security Scanning / Trivy Filesystem Scan (push) Failing after 14m46s
Security Scanning / Security Gate (push) Has been cancelled

This commit is contained in:
Ho Ngoc Hai
2026-04-19 03:12:54 +07:00
parent 3be106074d
commit 11f2bf26e6
101 changed files with 21312 additions and 20672 deletions

View File

@@ -1,21 +1,21 @@
# Inquiries Module - Complete File Index
# Inquiries Module - Chỉ Mục File Đầy Đủ
**Generated:** April 11, 2026
**Tạo lúc:** Ngày 11 tháng 4 năm 2026
**Module:** `apps/api/src/modules/inquiries/`
**Total Files:** 25
**Tổng số file:** 25
---
## 📋 COMPLETE FILE LISTING BY PATH
## 📋 DANH SÁCH FILE ĐẦY ĐỦ THEO ĐƯỜNG DẪN
### **1. APPLICATION LAYER**
### **1. TẦNG ỨNG DỤNG (APPLICATION LAYER)**
#### Commands (4 files)
```
📄 apps/api/src/modules/inquiries/application/commands/create-inquiry/create-inquiry.command.ts
Type: Command (CQRS)
Purpose: Input DTO for create inquiry use case
Purpose: Input DTO cho use case tạo yêu cầu tư vấn
Exports: CreateInquiryCommand class
Properties: userId, listingId, message, phone
Lines: ~8
@@ -24,14 +24,14 @@
```
📄 apps/api/src/modules/inquiries/application/commands/create-inquiry/create-inquiry.handler.ts
Type: Command Handler (CQRS)
Purpose: Orchestrates inquiry creation
Purpose: Điều phối quá trình tạo yêu cầu tư vấn
Implements: ICommandHandler<CreateInquiryCommand>
Returns: CreateInquiryResult { id, listingId, createdAt }
Key Logic:
Validate listing exists (Prisma.listing.findUnique)
Create InquiryEntity via factory method
Save to repository
• Publish InquiryCreatedEvent via EventBus
Xác thực tin đăng tồn tại (Prisma.listing.findUnique)
Tạo InquiryEntity qua phương thức factory
Lưu vào repository
• Phát sự kiện InquiryCreatedEvent qua EventBus
Lines: ~60
Dependencies:
• INQUIRY_REPOSITORY (injected)
@@ -43,7 +43,7 @@
```
📄 apps/api/src/modules/inquiries/application/commands/mark-inquiry-read/mark-inquiry-read.command.ts
Type: Command (CQRS)
Purpose: Input DTO for mark inquiry as read
Purpose: Input DTO để đánh dấu yêu cầu tư vấn đã đọc
Exports: MarkInquiryReadCommand class
Properties: inquiryId, agentUserId
Lines: ~6
@@ -52,20 +52,20 @@
```
📄 apps/api/src/modules/inquiries/application/commands/mark-inquiry-read/mark-inquiry-read.handler.ts
Type: Command Handler (CQRS)
Purpose: Orchestrates mark as read operation
Purpose: Điều phối thao tác đánh dấu đã đọc
Implements: ICommandHandler<MarkInquiryReadCommand>
Returns: void (no return value)
Returns: void (không có giá trị trả về)
Key Logic:
Load inquiry entity from repository
Load listing and verify agent ownership
Call inquiry.markAsRead() to update state
Persist via repository.markAsRead()
• Publish InquiryReadEvent via EventBus
Tải entity yêu cầu tư vấn từ repository
Tải tin đăng và xác minh quyền sở hữu của môi giới
Gọi inquiry.markAsRead() để cập nhật trạng thái
Lưu qua repository.markAsRead()
• Phát sự kiện InquiryReadEvent qua EventBus
Authorization Checks:
Inquiry exists
Listing exists
User is registered as agent
Agent ID matches listing.agentId
Yêu cầu tư vấn tồn tại
Tin đăng tồn tại
Người dùng đã đăng ký làm môi giới
ID môi giới khớp với listing.agentId
Lines: ~50
Dependencies:
• INQUIRY_REPOSITORY (injected)
@@ -79,7 +79,7 @@
```
📄 apps/api/src/modules/inquiries/application/queries/get-inquiries-by-agent/get-inquiries-by-agent.query.ts
Type: Query (CQRS)
Purpose: Input DTO for listing agent's inquiries
Purpose: Input DTO để lấy danh sách yêu cầu tư vấn của môi giới
Exports: GetInquiriesByAgentQuery class
Properties: agentUserId, page, limit
Lines: ~6
@@ -88,13 +88,13 @@
```
📄 apps/api/src/modules/inquiries/application/queries/get-inquiries-by-agent/get-inquiries-by-agent.handler.ts
Type: Query Handler (CQRS)
Purpose: Resolves paginated inquiries for an agent
Purpose: Phân giải danh sách yêu cầu tư vấn phân trang cho một môi giới
Implements: IQueryHandler<GetInquiriesByAgentQuery>
Returns: PaginatedResult<InquiryReadDto>
Key Logic:
Resolve agent ID from userId via Prisma
Throw NotFoundException if user not an agent
Delegate to repository.findByAgent()
Phân giải ID môi giới từ userId qua Prisma
Ném NotFoundException nếu người dùng không phải môi giới
Ủy quyền cho repository.findByAgent()
Lines: ~30
Dependencies:
• INQUIRY_REPOSITORY (injected)
@@ -104,7 +104,7 @@
```
📄 apps/api/src/modules/inquiries/application/queries/get-inquiries-by-listing/get-inquiries-by-listing.query.ts
Type: Query (CQRS)
Purpose: Input DTO for listing inquiries
Purpose: Input DTO để lấy danh sách yêu cầu tư vấn của tin đăng
Exports: GetInquiriesByListingQuery class
Properties: listingId, page, limit
Lines: ~6
@@ -113,11 +113,11 @@
```
📄 apps/api/src/modules/inquiries/application/queries/get-inquiries-by-listing/get-inquiries-by-listing.handler.ts
Type: Query Handler (CQRS)
Purpose: Resolves paginated inquiries for a listing
Purpose: Phân giải danh sách yêu cầu tư vấn phân trang cho một tin đăng
Implements: IQueryHandler<GetInquiriesByListingQuery>
Returns: PaginatedResult<InquiryReadDto>
Key Logic:
Direct delegation to repository.findByListing()
Ủy quyền trực tiếp cho repository.findByListing()
Lines: ~20
Dependencies:
• INQUIRY_REPOSITORY (injected)
@@ -128,12 +128,12 @@
```
📄 apps/api/src/modules/inquiries/application/__tests__/create-inquiry.handler.spec.ts
Type: Unit Tests (Jest/Vitest)
Test Framework: Vitest with Mock functions (vi.fn)
Test Framework: Vitest với hàm Mock (vi.fn)
Test Count: 4
Tests:
creates an inquiry successfully
throws NotFoundException when listing not found
✓ publishes domain events after saving
tạo yêu cầu tư vấn thành công
ném NotFoundException khi không tìm thấy tin đăng
✓ phát sự kiện domain sau khi lưu
Mocks:
• mockInquiryRepo (IInquiryRepository implementation)
• mockEventBus
@@ -146,11 +146,11 @@
Type: Unit Tests (Jest/Vitest)
Test Count: 5
Tests:
marks an inquiry as read successfully
throws NotFoundException when inquiry not found
throws NotFoundException when listing not found
throws ForbiddenException when user is not the listing agent
throws ForbiddenException when agent not found for user
đánh dấu yêu cầu tư vấn là đã đọc thành công
ném NotFoundException khi không tìm thấy yêu cầu tư vấn
ném NotFoundException khi không tìm thấy tin đăng
ném ForbiddenException khi người dùng không phải môi giới của tin đăng
ném ForbiddenException khi không tìm thấy môi giới cho người dùng
Mocks:
• mockInquiryRepo
• mockEventBus
@@ -164,8 +164,8 @@
Type: Unit Tests (Jest/Vitest)
Test Count: 2
Tests:
returns paginated results
returns empty data when no inquiries found
trả về kết quả phân trang
trả về dữ liệu rỗng khi không tìm thấy yêu cầu tư vấn nào
Mocks:
• mockInquiryRepo.findByListing
Lines: ~69
@@ -176,8 +176,8 @@
Type: Unit Tests (Jest/Vitest)
Test Count: 2
Tests:
returns paginated results
throws NotFoundException when agent not found for user
trả về kết quả phân trang
ném NotFoundException khi không tìm thấy môi giới cho người dùng
Mocks:
• mockInquiryRepo.findByAgent
• mockPrisma.agent.findUnique
@@ -186,7 +186,7 @@
---
### **2. DOMAIN LAYER**
### **2. TẦNG DOMAIN (DOMAIN LAYER)**
#### Entities (1 file)
@@ -194,7 +194,7 @@
📄 apps/api/src/modules/inquiries/domain/entities/inquiry.entity.ts
Type: Aggregate Root (DDD)
Extends: AggregateRoot<string>
Purpose: Core business logic for inquiries
Purpose: Logic nghiệp vụ cốt lõi cho yêu cầu tư vấn
Properties (Private):
• _listingId: string
@@ -212,14 +212,14 @@
Factory Method:
• static createNew(id, listingId, userId, message, phone): InquiryEntity
- Creates new inquiry with isRead=false
- Emits InquiryCreatedEvent
- Returns entity instance
- Tạo yêu cầu tư vấn mới với isRead=false
- Phát InquiryCreatedEvent
- Trả về instance của entity
Domain Methods:
• markAsRead(): void
- Sets _isRead to true
- Emits InquiryReadEvent
- Đặt _isRead thành true
- Phát InquiryReadEvent
Lines: ~63
Dependencies:
@@ -234,7 +234,7 @@
📄 apps/api/src/modules/inquiries/domain/events/inquiry-created.event.ts
Type: Domain Event (DDD)
Implements: DomainEvent interface
Purpose: Signals that an inquiry was created
Purpose: Báo hiệu rằng một yêu cầu tư vấn đã được tạo
Properties:
• eventName: string = 'inquiry.created'
@@ -250,7 +250,7 @@
📄 apps/api/src/modules/inquiries/domain/events/inquiry-read.event.ts
Type: Domain Event (DDD)
Implements: DomainEvent interface
Purpose: Signals that an inquiry was marked as read
Purpose: Báo hiệu rằng một yêu cầu tư vấn đã được đánh dấu là đã đọc
Properties:
• eventName: string = 'inquiry.read'
@@ -267,7 +267,7 @@
```
📄 apps/api/src/modules/inquiries/domain/repositories/inquiry.repository.ts
Type: Repository Interface + Symbol (DDD)
Purpose: Defines persistence contract
Purpose: Định nghĩa hợp đồng persistence
Exports:
• INQUIRY_REPOSITORY: Symbol (DI token)
@@ -295,7 +295,7 @@
```
📄 apps/api/src/modules/inquiries/domain/repositories/inquiry-read.dto.ts
Type: Data Transfer Object (Read Model)
Purpose: DTO for query results
Purpose: DTO cho kết quả truy vấn
Exports: InquiryReadDto interface
InquiryReadDto Properties:
@@ -320,18 +320,18 @@
Type: Unit Tests (Jest/Vitest)
Test Count: 5
Tests:
✓ createNew() creates an inquiry with correct properties
✓ createNew() creates an inquiry with null phone
✓ createNew() emits InquiryCreatedEvent
✓ markAsRead() sets isRead to true
✓ markAsRead() emits InquiryReadEvent
Focus: Entity behavior and domain event emission
✓ createNew() tạo yêu cầu tư vấn với các thuộc tính đúng
✓ createNew() tạo yêu cầu tư vấn với phone là null
✓ createNew() phát InquiryCreatedEvent
✓ markAsRead() đặt isRead thành true
✓ markAsRead() phát InquiryReadEvent
Focus: Hành vi entity và việc phát sự kiện domain
Lines: ~96
```
---
### **3. INFRASTRUCTURE LAYER**
### **3. TẦNG HẠ TẦNG (INFRASTRUCTURE LAYER)**
#### Repository Implementation (1 file)
@@ -340,7 +340,7 @@
Type: Repository Implementation (Service)
Implements: IInquiryRepository
Decorator: @Injectable()
Purpose: Prisma-based persistence
Purpose: Persistence dựa trên Prisma
Methods:
1. findById(id: string): Promise<InquiryEntity | null>
@@ -349,21 +349,21 @@
2. save(entity: InquiryEntity): Promise<void>
- Query: prisma.inquiry.create({ data: {...} })
- Maps entity properties to Prisma model
- Ánh xạ thuộc tính entity sang Prisma model
3. markAsRead(id: string): Promise<void>
- Query: prisma.inquiry.update({ where: { id }, data: { isRead: true } })
4. findByListing(listingId, page, limit): Promise<PaginatedResult<InquiryReadDto>>
- Query: prisma.inquiry.findMany() with joins
- Query: prisma.inquiry.findMany() với joins
- Includes: listing.property.title, user.fullName, user.phone
- Pagination: skip/take pattern
- Pagination: mô hình skip/take
- Sorting: orderBy: { createdAt: 'desc' }
- Returns: Mapped InquiryReadDto array with pagination info
- Returns: Mảng InquiryReadDto đã ánh xạ kèm thông tin phân trang
5. findByAgent(agentId, page, limit): Promise<PaginatedResult<InquiryReadDto>>
- Query: prisma.inquiry.findMany() filtered by listing.agentId
- Same includes and pagination as findByListing
- Query: prisma.inquiry.findMany() lọc theo listing.agentId
- Cùng includes và phân trang như findByListing
- Filter: { listing: { agentId } }
6. countUnreadByAgent(agentId): Promise<number>
@@ -372,7 +372,7 @@
Helper Method:
• toDomain(raw: PrismaInquiry): InquiryEntity
- Maps database record to domain entity
- Ánh xạ bản ghi cơ sở dữ liệu sang domain entity
Lines: ~146
Dependencies:
@@ -383,7 +383,7 @@
---
### **4. PRESENTATION LAYER**
### **4. TẦNG TRÌNH BÀY (PRESENTATION LAYER)**
#### Controller (1 file)
@@ -392,7 +392,7 @@
Type: NestJS Controller
Decorator: @Controller('inquiries')
Decorator: @ApiTags('inquiries')
Purpose: HTTP API endpoints
Purpose: Các endpoint HTTP API
Endpoints:
@@ -404,8 +404,8 @@
Returns: CreateInquiryResult { id, listingId, createdAt }
Status Codes: 201 Created, 400 Bad Request, 401 Unauthorized, 404 Not Found
Logic:
Dispatch CreateInquiryCommand via CommandBus
Pass user.sub as userId
Điều phối CreateInquiryCommand qua CommandBus
Truyền user.sub làm userId
2. GET /inquiries/listing/:listingId
Decorator: @Get('listing/:listingId')
@@ -415,8 +415,8 @@
Returns: PaginatedResult<InquiryReadDto>
Status Codes: 200 OK, 401 Unauthorized
Logic:
Dispatch GetInquiriesByListingQuery via QueryBus
Default page=1, limit=20
Điều phối GetInquiriesByListingQuery qua QueryBus
Mặc định page=1, limit=20
3. GET /inquiries/agent/me
Decorator: @Get('agent/me')
@@ -427,9 +427,9 @@
Returns: PaginatedResult<InquiryReadDto>
Status Codes: 200 OK, 401 Unauthorized, 403 Forbidden
Logic:
Dispatch GetInquiriesByAgentQuery via QueryBus
Pass user.sub as agentUserId
Default page=1, limit=20
Điều phối GetInquiriesByAgentQuery qua QueryBus
Truyền user.sub làm agentUserId
Mặc định page=1, limit=20
4. PATCH /inquiries/:id/read
Decorator: @Patch(':id/read')
@@ -439,9 +439,9 @@
Returns: { success: boolean }
Status Codes: 200 OK, 401 Unauthorized, 403 Forbidden, 404 Not Found
Logic:
Dispatch MarkInquiryReadCommand via CommandBus
Pass user.sub as agentUserId
Return { success: true }
Điều phối MarkInquiryReadCommand qua CommandBus
Truyền user.sub làm agentUserId
Trả về { success: true }
Lines: ~121
Dependencies:
@@ -456,7 +456,7 @@
```
📄 apps/api/src/modules/inquiries/presentation/dto/create-inquiry.dto.ts
Type: Data Transfer Object (Validation)
Purpose: Validate POST /inquiries request body
Purpose: Xác thực body của request POST /inquiries
Decorators: @ApiProperty, @ApiPropertyOptional
Properties:
@@ -467,7 +467,7 @@
• message: string (required)
Validators: @IsString(), @IsNotEmpty(), @MaxLength(2000)
API Doc: "Tin nhắn yêu cầu tư vấn" (Consultation request message)
Max: 2000 characters
Max: 2000 ký tự
• phone?: string (optional)
Validators: @IsOptional(), @IsString()
@@ -480,18 +480,18 @@
```
📄 apps/api/src/modules/inquiries/presentation/dto/list-inquiries.dto.ts
Type: Data Transfer Object (Validation)
Purpose: Validate query parameters for list endpoints
Purpose: Xác thực query parameter cho các endpoint danh sách
Decorators: @ApiPropertyOptional, @Type
Properties:
• page?: number (optional)
Validators: @IsOptional(), @IsInt(), @Min(1), @Type(() => Number)
API Doc: "Page number", default: 1
API Doc: "Số trang", mặc định: 1
Example: 1
• limit?: number (optional)
Validators: @IsOptional(), @IsInt(), @Min(1), @Max(100), @Type(() => Number)
API Doc: "Items per page", default: 20
API Doc: "Số mục mỗi trang", mặc định: 20
Example: 20
Max: 100
@@ -507,16 +507,16 @@
Test Count: 6
Tests:
✓ POST /inquiries dispatches CreateInquiryCommand with correct parameters
✓ POST /inquiries passes null phone when not provided
✓ GET /listing/:id dispatches GetInquiriesByListingQuery with defaults
✓ GET /listing/:id passes custom pagination
✓ GET /agent/me dispatches GetInquiriesByAgentQuery with current user
✓ PATCH /:id/read dispatches MarkInquiryReadCommand and returns success
✓ POST /inquiries điều phối CreateInquiryCommand với tham số đúng
✓ POST /inquiries truyền phone là null khi không được cung cấp
✓ GET /listing/:id điều phối GetInquiriesByListingQuery với giá trị mặc định
✓ GET /listing/:id truyền phân trang tùy chỉnh
✓ GET /agent/me điều phối GetInquiriesByAgentQuery với người dùng hiện tại
✓ PATCH /:id/read điều phối MarkInquiryReadCommand và trả về thành công
Mocks:
• mockCommandBus with execute() mock function
• mockQueryBus with execute() mock function
• mockCommandBus với hàm mock execute()
• mockQueryBus với hàm mock execute()
• mockBuyer user object (sub='buyer-1', role='BUYER')
• mockAgent user object (sub='agent-1', role='AGENT')
@@ -525,25 +525,25 @@
---
### **5. MODULE LAYER**
### **5. TẦNG MODULE (MODULE LAYER)**
```
📄 apps/api/src/modules/inquiries/inquiries.module.ts
Type: NestJS Module
Decorator: @Module()
Purpose: Configure module, declare dependencies, exports
Purpose: Cấu hình module, khai báo phụ thuộc, xuất khẩu
Imports: [CqrsModule]
Controllers: [InquiriesController]
Providers:
• { provide: INQUIRY_REPOSITORY, useClass: PrismaInquiryRepository }
- Dependency injection token mapping
- Ánh xạ token dependency injection
• CommandHandlers array: [CreateInquiryHandler, MarkInquiryReadHandler]
• QueryHandlers array: [GetInquiriesByListingHandler, GetInquiriesByAgentHandler]
Exports: [INQUIRY_REPOSITORY]
- Makes repository available to other modules
- Cung cấp repository cho các module khác
Lines: ~29
Dependencies:
@@ -555,7 +555,7 @@
```
📄 apps/api/src/modules/inquiries/index.ts
Type: Barrel Export (Public API)
Purpose: Define public module interface
Purpose: Định nghĩa giao diện công khai của module
Exports:
• InquiriesModule (default export for app imports)
@@ -568,31 +568,31 @@
---
## 📊 FILE STATISTICS
## 📊 THỐNG KÊ FILE
### By Layer
### Theo Tầng
| Layer | Files | Type | Purpose |
|-------|-------|------|---------|
| **Presentation** | 5 | Controller + DTOs + Tests | HTTP endpoints and input validation |
| **Application** | 8 | Commands/Queries + Handlers + Tests | Use case orchestration |
| **Domain** | 6 | Entities + Events + Repository Interface + Tests | Business logic and contracts |
| **Infrastructure** | 1 | Repository Implementation | Database persistence |
| **Module** | 2 | Module + Exports | Configuration and public API |
| **TOTAL** | 25 | - | - |
| Tầng | Files | Loại | Mục đích |
|------|-------|------|----------|
| **Presentation** | 5 | Controller + DTOs + Tests | Endpoint HTTP và xác thực đầu vào |
| **Application** | 8 | Commands/Queries + Handlers + Tests | Điều phối use case |
| **Domain** | 6 | Entities + Events + Repository Interface + Tests | Logic nghiệp vụ và hợp đồng |
| **Infrastructure** | 1 | Repository Implementation | Lưu trữ cơ sở dữ liệu |
| **Module** | 2 | Module + Exports | Cấu hình và API công khai |
| **TỔNG** | 25 | - | - |
### By Type
### Theo Loại
| Type | Count |
|------|-------|
| Source Files (.ts, no tests) | 19 |
| Test Files (.spec.ts) | 6 |
| **Total** | **25** |
| Loại | Số lượng |
|------|----------|
| File nguồn (.ts, không phải test) | 19 |
| File test (.spec.ts) | 6 |
| **Tổng** | **25** |
### By Purpose
### Theo Mục Đích
| Purpose | Count | Files |
|---------|-------|-------|
| Mục đích | Số lượng | Files |
|----------|----------|-------|
| Controllers | 1 | inquiries.controller.ts |
| DTOs | 2 | create-inquiry.dto.ts, list-inquiries.dto.ts |
| Commands | 2 | create-inquiry.command.ts, mark-inquiry-read.command.ts |
@@ -601,39 +601,39 @@
| Entities | 1 | inquiry.entity.ts |
| Events | 2 | inquiry-created.event.ts, inquiry-read.event.ts |
| Repositories | 3 | interface + 2 DTOs + 1 implementation |
| Tests | 6 | 5 test suites across layers |
| Tests | 6 | 5 bộ test trải rộng các tầng |
| Module | 2 | inquiries.module.ts, index.ts |
---
## 🔍 FILE DISCOVERY GUIDE
## 🔍 HƯỚNG DẪN TÌM KIẾM FILE
### Looking for Business Logic?
**`domain/entities/inquiry.entity.ts`** - Core business rules
**`domain/events/*.event.ts`** - Business events
### Tìm kiếm Logic Nghiệp Vụ?
**`domain/entities/inquiry.entity.ts`** - Quy tắc nghiệp vụ cốt lõi
**`domain/events/*.event.ts`** - Sự kiện nghiệp vụ
### Looking for Use Cases?
**`application/commands/*/`** - Write operations
**`application/queries/*/`** - Read operations
**`application/[type]/__tests__/`** - Test cases
### Tìm kiếm Use Case?
**`application/commands/*/`** - Thao tác ghi
**`application/queries/*/`** - Thao tác đọc
**`application/[type]/__tests__/`** - Các test case
### Looking for HTTP Endpoints?
**`presentation/controllers/inquiries.controller.ts`** - All 4 endpoints
### Tìm kiếm HTTP Endpoint?
**`presentation/controllers/inquiries.controller.ts`** - Toàn bộ 4 endpoint
### Looking for Input Validation?
**`presentation/dto/`** - All DTOs with validators
### Tìm kiếm Xác Thực Đầu Vào?
**`presentation/dto/`** - Tất cả DTOs kèm validator
### Looking for Database Logic?
**`infrastructure/repositories/prisma-inquiry.repository.ts`** - All Prisma queries
### Tìm kiếm Logic Cơ Sở Dữ Liệu?
**`infrastructure/repositories/prisma-inquiry.repository.ts`** - Tất cả Prisma query
### Looking for Tests?
**`domain/__tests__/`** - Domain behavior
**`application/__tests__/`** - Handler tests
**`presentation/__tests__/`** - Controller tests
### Tìm kiếm Tests?
**`domain/__tests__/`** - Hành vi domain
**`application/__tests__/`** - Test handler
**`presentation/__tests__/`** - Test controller
---
## 🔗 DEPENDENCY GRAPH
## 🔗 ĐỒ THỊ PHỤ THUỘC (DEPENDENCY GRAPH)
```
presentation/controllers/inquiries.controller.ts
@@ -671,27 +671,27 @@ inquiries.module.ts
---
## 📝 FILE CROSS-REFERENCES
## 📝 THAM CHIẾU CHÉO FILE
### Files Using INQUIRY_REPOSITORY Symbol
- `inquiries.module.ts` - Provides implementation
### Các File Sử Dụng Symbol INQUIRY_REPOSITORY
- `inquiries.module.ts` - Cung cấp implementation
- `application/commands/create-inquiry/create-inquiry.handler.ts` - Injects
- `application/commands/mark-inquiry-read/mark-inquiry-read.handler.ts` - Injects
- `application/queries/get-inquiries-by-agent/get-inquiries-by-agent.handler.ts` - Injects
- `application/queries/get-inquiries-by-listing/get-inquiries-by-listing.handler.ts` - Injects
### Files Creating/Modifying InquiryEntity
- `domain/entities/inquiry.entity.ts` - Defines
- `application/commands/create-inquiry/create-inquiry.handler.ts` - Creates
- `application/commands/mark-inquiry-read/mark-inquiry-read.handler.ts` - Modifies
- `infrastructure/repositories/prisma-inquiry.repository.ts` - Maps to/from
### Các File Tạo/Chỉnh Sửa InquiryEntity
- `domain/entities/inquiry.entity.ts` - Định nghĩa
- `application/commands/create-inquiry/create-inquiry.handler.ts` - Tạo mới
- `application/commands/mark-inquiry-read/mark-inquiry-read.handler.ts` - Chỉnh sửa
- `infrastructure/repositories/prisma-inquiry.repository.ts` - Ánh xạ đến/từ
### Files Publishing Events
- `domain/entities/inquiry.entity.ts` - Emits (via addDomainEvent)
- `application/commands/create-inquiry/create-inquiry.handler.ts` - Publishes
- `application/commands/mark-inquiry-read/mark-inquiry-read.handler.ts` - Publishes
### Các File Phát Sự Kiện
- `domain/entities/inquiry.entity.ts` - Phát ra (qua addDomainEvent)
- `application/commands/create-inquiry/create-inquiry.handler.ts` - Xuất bản
- `application/commands/mark-inquiry-read/mark-inquiry-read.handler.ts` - Xuất bản
### Files with Tests
### Các File Có Tests
- `domain/entities/inquiry.entity.ts``domain/__tests__/inquiry-domain.spec.ts`
- `application/commands/create-inquiry/create-inquiry.handler.ts``application/__tests__/create-inquiry.handler.spec.ts`
- `application/commands/mark-inquiry-read/mark-inquiry-read.handler.ts``application/__tests__/mark-inquiry-read.handler.spec.ts`
@@ -701,35 +701,35 @@ inquiries.module.ts
---
## 🎯 ENTRY POINTS FOR MODIFICATIONS
## 🎯 ĐIỂM VÀO CHO VIỆC CHỈNH SỬA
### To Add a New Endpoint
1. Add method to `presentation/controllers/inquiries.controller.ts`
2. Create command/query in `application/[type]/[name]/`
3. Create handler: `[name].handler.ts`
4. Add tests in `application/__tests__/`
5. Optional: Update domain if new business logic needed
### Thêm Endpoint Mới
1. Thêm phương thức vào `presentation/controllers/inquiries.controller.ts`
2. Tạo command/query trong `application/[type]/[name]/`
3. Tạo handler: `[name].handler.ts`
4. Thêm tests trong `application/__tests__/`
5. Tuỳ chọn: Cập nhật domain nếu cần logic nghiệp vụ mới
### To Add a New Command
1. Create `application/commands/[name]/[name].command.ts` (DTO)
2. Create `application/commands/[name]/[name].handler.ts` (@CommandHandler)
3. Register in `inquiries.module.ts` CommandHandlers array
4. Add tests in `application/__tests__/[name].handler.spec.ts`
5. Optional: Define new domain events in `domain/events/`
### Thêm Command Mới
1. Tạo `application/commands/[name]/[name].command.ts` (DTO)
2. Tạo `application/commands/[name]/[name].handler.ts` (@CommandHandler)
3. Đăng ký trong mảng CommandHandlers của `inquiries.module.ts`
4. Thêm tests trong `application/__tests__/[name].handler.spec.ts`
5. Tuỳ chọn: Định nghĩa sự kiện domain mới trong `domain/events/`
### To Add Domain Logic
1. Modify `domain/entities/inquiry.entity.ts`
2. Add new public methods or properties
3. Emit new events if needed: `domain/events/[name].event.ts`
4. Update tests in `domain/__tests__/inquiry-domain.spec.ts`
5. Update handlers that use the entity
### Thêm Logic Domain
1. Chỉnh sửa `domain/entities/inquiry.entity.ts`
2. Thêm phương thức hoặc thuộc tính công khai mới
3. Phát sự kiện mới nếu cần: `domain/events/[name].event.ts`
4. Cập nhật tests trong `domain/__tests__/inquiry-domain.spec.ts`
5. Cập nhật các handler sử dụng entity
### To Add Database Operations
1. Add method to `infrastructure/repositories/prisma-inquiry.repository.ts`
2. Update interface in `domain/repositories/inquiry.repository.ts`
3. Call from relevant handlers
### Thêm Thao Tác Cơ Sở Dữ Liệu
1. Thêm phương thức vào `infrastructure/repositories/prisma-inquiry.repository.ts`
2. Cập nhật interface trong `domain/repositories/inquiry.repository.ts`
3. Gọi từ các handler liên quan
---
**Total Lines of Code:** 1,212
**Last Updated:** April 11, 2026
**Tổng số dòng code:** 1.212
**Cập nhật lần cuối:** Ngày 11 tháng 4 năm 2026