Files
goodgo-platform/docs/audits/INQUIRIES_COMPLETE_FILE_INDEX.md
Ho Ngoc Hai 11f2bf26e6
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
chore: update project documentation, audit reports, and initialize IDE configuration files
2026-04-19 03:12:54 +07:00

25 KiB

Inquiries Module - Chỉ Mục File Đầy Đủ

Tạo lúc: Ngày 11 tháng 4 năm 2026
Module: apps/api/src/modules/inquiries/
Tổng số file: 25


📋 DANH SÁCH FILE ĐẦY ĐỦ THEO ĐƯỜNG DẪN

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 cho use case tạo yêu cầu tư vấn
   Exports: CreateInquiryCommand class
   Properties: userId, listingId, message, phone
   Lines: ~8
📄 apps/api/src/modules/inquiries/application/commands/create-inquiry/create-inquiry.handler.ts
   Type: Command Handler (CQRS)
   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:
     • 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)
     • EventBus (injected)
     • PrismaService (injected)
     • LoggerService (injected)
📄 apps/api/src/modules/inquiries/application/commands/mark-inquiry-read/mark-inquiry-read.command.ts
   Type: Command (CQRS)
   Purpose: Input DTO để đánh dấu yêu cầu tư vấn đã đọc
   Exports: MarkInquiryReadCommand class
   Properties: inquiryId, agentUserId
   Lines: ~6
📄 apps/api/src/modules/inquiries/application/commands/mark-inquiry-read/mark-inquiry-read.handler.ts
   Type: Command Handler (CQRS)
   Purpose: Điều phối thao tác đánh dấu đã đọc
   Implements: ICommandHandler<MarkInquiryReadCommand>
   Returns: void (không có giá trị trả về)
   Key Logic:
     • 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:
     • 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)
     • EventBus (injected)
     • PrismaService (injected)
     • LoggerService (injected)

Queries (4 files)

📄 apps/api/src/modules/inquiries/application/queries/get-inquiries-by-agent/get-inquiries-by-agent.query.ts
   Type: Query (CQRS)
   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
📄 apps/api/src/modules/inquiries/application/queries/get-inquiries-by-agent/get-inquiries-by-agent.handler.ts
   Type: Query Handler (CQRS)
   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:
     • 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)
     • PrismaService (injected)
📄 apps/api/src/modules/inquiries/application/queries/get-inquiries-by-listing/get-inquiries-by-listing.query.ts
   Type: Query (CQRS)
   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
📄 apps/api/src/modules/inquiries/application/queries/get-inquiries-by-listing/get-inquiries-by-listing.handler.ts
   Type: Query Handler (CQRS)
   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:
     • Ủy quyền trực tiếp cho repository.findByListing()
   Lines: ~20
   Dependencies:
     • INQUIRY_REPOSITORY (injected)

Application Tests (4 files)

📄 apps/api/src/modules/inquiries/application/__tests__/create-inquiry.handler.spec.ts
   Type: Unit Tests (Jest/Vitest)
   Test Framework: Vitest với hàm Mock (vi.fn)
   Test Count: 4
   Tests:
     ✓ 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
     • mockPrisma.listing.findUnique
   Lines: ~98
📄 apps/api/src/modules/inquiries/application/__tests__/mark-inquiry-read.handler.spec.ts
   Type: Unit Tests (Jest/Vitest)
   Test Count: 5
   Tests:
     ✓ đá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
     • mockPrisma.listing.findUnique
     • mockPrisma.agent.findUnique
   Lines: ~130
📄 apps/api/src/modules/inquiries/application/__tests__/get-inquiries-by-listing.handler.spec.ts
   Type: Unit Tests (Jest/Vitest)
   Test Count: 2
   Tests:
     ✓ 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
📄 apps/api/src/modules/inquiries/application/__tests__/get-inquiries-by-agent.handler.spec.ts
   Type: Unit Tests (Jest/Vitest)
   Test Count: 2
   Tests:
     ✓ 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
   Lines: ~77

2. TẦNG DOMAIN (DOMAIN LAYER)

Entities (1 file)

📄 apps/api/src/modules/inquiries/domain/entities/inquiry.entity.ts
   Type: Aggregate Root (DDD)
   Extends: AggregateRoot<string>
   Purpose: Logic nghiệp vụ cốt lõi cho yêu cầu tư vấn
   
   Properties (Private):
     • _listingId: string
     • _userId: string
     • _message: string
     • _phone: string | null
     • _isRead: boolean
   
   Getters (Read-only):
     • listingId: string
     • userId: string
     • message: string
     • phone: string | null
     • isRead: boolean
   
   Factory Method:
     • static createNew(id, listingId, userId, message, phone): InquiryEntity
       - 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
       - Đặt _isRead thành true
       - Phát InquiryReadEvent
   
   Lines: ~63
   Dependencies:
     • AggregateRoot from @modules/shared
     • InquiryCreatedEvent
     • InquiryReadEvent

Events (2 files)

📄 apps/api/src/modules/inquiries/domain/events/inquiry-created.event.ts
   Type: Domain Event (DDD)
   Implements: DomainEvent interface
   Purpose: Báo hiệu rằng một yêu cầu tư vấn đã được tạo
   
   Properties:
     • eventName: string = 'inquiry.created'
     • occurredAt: Date = new Date()
     • aggregateId: string
     • listingId: string
     • userId: string
   
   Lines: ~13
📄 apps/api/src/modules/inquiries/domain/events/inquiry-read.event.ts
   Type: Domain Event (DDD)
   Implements: DomainEvent interface
   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'
     • occurredAt: Date = new Date()
     • aggregateId: string
     • listingId: string
     • userId: string
   
   Lines: ~13

Repositories (2 files)

📄 apps/api/src/modules/inquiries/domain/repositories/inquiry.repository.ts
   Type: Repository Interface + Symbol (DDD)
   Purpose: Định nghĩa hợp đồng persistence
   
   Exports:
     • INQUIRY_REPOSITORY: Symbol (DI token)
     • IInquiryRepository: Interface
     • PaginatedResult<T>: Interface
   
   IInquiryRepository Methods:
     • findById(id: string): Promise<InquiryEntity | null>
     • save(inquiry: InquiryEntity): Promise<void>
     • markAsRead(id: string): Promise<void>
     • findByListing(listingId, page, limit): Promise<PaginatedResult<InquiryReadDto>>
     • findByAgent(agentId, page, limit): Promise<PaginatedResult<InquiryReadDto>>
     • countUnreadByAgent(agentId): Promise<number>
   
   PaginatedResult<T> Interface:
     • data: T[]
     • total: number
     • page: number
     • limit: number
     • totalPages: number
   
   Lines: ~22
📄 apps/api/src/modules/inquiries/domain/repositories/inquiry-read.dto.ts
   Type: Data Transfer Object (Read Model)
   Purpose: DTO cho kết quả truy vấn
   Exports: InquiryReadDto interface
   
   InquiryReadDto Properties:
     • id: string
     • listingId: string
     • listingTitle: string
     • userId: string
     • userName: string
     • userPhone: string
     • message: string
     • phone: string | null
     • isRead: boolean
     • createdAt: string
   
   Lines: ~13

Domain Tests (1 file)

📄 apps/api/src/modules/inquiries/domain/__tests__/inquiry-domain.spec.ts
   Type: Unit Tests (Jest/Vitest)
   Test Count: 5
   Tests:
     ✓ 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. TẦNG HẠ TẦNG (INFRASTRUCTURE LAYER)

Repository Implementation (1 file)

📄 apps/api/src/modules/inquiries/infrastructure/repositories/prisma-inquiry.repository.ts
   Type: Repository Implementation (Service)
   Implements: IInquiryRepository
   Decorator: @Injectable()
   Purpose: Persistence dựa trên Prisma
   
   Methods:
     1. findById(id: string): Promise<InquiryEntity | null>
        - Query: prisma.inquiry.findUnique({ where: { id } })
        - Returns: InquiryEntity | null
     
     2. save(entity: InquiryEntity): Promise<void>
        - Query: prisma.inquiry.create({ data: {...} })
        - Á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() với joins
        - Includes: listing.property.title, user.fullName, user.phone
        - Pagination: mô hình skip/take
        - Sorting: orderBy: { createdAt: 'desc' }
        - 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() lọc theo listing.agentId
        - Cùng includes và phân trang như findByListing
        - Filter: { listing: { agentId } }
     
     6. countUnreadByAgent(agentId): Promise<number>
        - Query: prisma.inquiry.count()
        - Filter: { isRead: false, listing: { agentId } }
     
     Helper Method:
     • toDomain(raw: PrismaInquiry): InquiryEntity
       - Ánh xạ bản ghi cơ sở dữ liệu sang domain entity
   
   Lines: ~146
   Dependencies:
     • PrismaService (injected)
     • InquiryEntity
     • IInquiryRepository (implements)

4. TẦNG TRÌNH BÀY (PRESENTATION LAYER)

Controller (1 file)

📄 apps/api/src/modules/inquiries/presentation/controllers/inquiries.controller.ts
   Type: NestJS Controller
   Decorator: @Controller('inquiries')
   Decorator: @ApiTags('inquiries')
   Purpose: Các endpoint HTTP API
   
   Endpoints:
   
   1. POST /inquiries
      Decorator: @Post()
      Auth: @UseGuards(JwtAuthGuard)
      Method: createInquiry(dto: CreateInquiryDto, user: JwtPayload)
      Body: CreateInquiryDto { listingId, message, phone? }
      Returns: CreateInquiryResult { id, listingId, createdAt }
      Status Codes: 201 Created, 400 Bad Request, 401 Unauthorized, 404 Not Found
      Logic: 
        • Điều phối CreateInquiryCommand qua CommandBus
        • Truyền user.sub làm userId
   
   2. GET /inquiries/listing/:listingId
      Decorator: @Get('listing/:listingId')
      Auth: @UseGuards(JwtAuthGuard)
      Method: getByListing(listingId: string, dto: ListInquiriesDto)
      Query: page?, limit?
      Returns: PaginatedResult<InquiryReadDto>
      Status Codes: 200 OK, 401 Unauthorized
      Logic:
        • Điều phối GetInquiriesByListingQuery qua QueryBus
        • Mặc định page=1, limit=20
   
   3. GET /inquiries/agent/me
      Decorator: @Get('agent/me')
      Auth: @UseGuards(JwtAuthGuard, RolesGuard)
      Decorator: @Roles('AGENT')
      Method: getMyInquiries(user: JwtPayload, dto: ListInquiriesDto)
      Query: page?, limit?
      Returns: PaginatedResult<InquiryReadDto>
      Status Codes: 200 OK, 401 Unauthorized, 403 Forbidden
      Logic:
        • Đ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')
      Auth: @UseGuards(JwtAuthGuard, RolesGuard)
      Decorator: @Roles('AGENT')
      Method: markAsRead(id: string, user: JwtPayload)
      Returns: { success: boolean }
      Status Codes: 200 OK, 401 Unauthorized, 403 Forbidden, 404 Not Found
      Logic:
        • Điều phối MarkInquiryReadCommand qua CommandBus
        • Truyền user.sub làm agentUserId
        • Trả về { success: true }
   
   Lines: ~121
   Dependencies:
     • CommandBus (injected)
     • QueryBus (injected)
     • @nestjs/swagger decorators
     • @modules/auth guards and decorators

DTOs (2 files)

📄 apps/api/src/modules/inquiries/presentation/dto/create-inquiry.dto.ts
   Type: Data Transfer Object (Validation)
   Purpose: Xác thực body của request POST /inquiries
   Decorators: @ApiProperty, @ApiPropertyOptional
   
   Properties:
     • listingId: string (required)
       Validators: @IsString(), @IsNotEmpty()
       API Doc: "ID of the listing"
     
     • 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 ký tự
     
     • phone?: string (optional)
       Validators: @IsOptional(), @IsString()
       API Doc: "Số điện thoại liên hệ" (Contact phone number)
   
   Lines: ~21
   Dependencies: class-validator, @nestjs/swagger
📄 apps/api/src/modules/inquiries/presentation/dto/list-inquiries.dto.ts
   Type: Data Transfer Object (Validation)
   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: "Số trang", mặc định: 1
       Example: 1
     
     • limit?: number (optional)
       Validators: @IsOptional(), @IsInt(), @Min(1), @Max(100), @Type(() => Number)
       API Doc: "Số mục mỗi trang", mặc định: 20
       Example: 20
       Max: 100
   
   Lines: ~21
   Dependencies: class-validator, @nestjs/swagger, class-transformer

Presentation Tests (1 file)

📄 apps/api/src/modules/inquiries/presentation/__tests__/inquiries.controller.spec.ts
   Type: Unit Tests (Jest/Vitest)
   Test Count: 6
   
   Tests:
     ✓ 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 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')
   
   Lines: ~105

5. TẦNG MODULE (MODULE LAYER)

📄 apps/api/src/modules/inquiries/inquiries.module.ts
   Type: NestJS Module
   Decorator: @Module()
   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 }
       - Ánh xạ token dependency injection
     • CommandHandlers array: [CreateInquiryHandler, MarkInquiryReadHandler]
     • QueryHandlers array: [GetInquiriesByListingHandler, GetInquiriesByAgentHandler]
   
   Exports: [INQUIRY_REPOSITORY]
     - Cung cấp repository cho các module khác
   
   Lines: ~29
   Dependencies:
     • @nestjs/common
     • @nestjs/cqrs
     • All handlers, repository, controller
📄 apps/api/src/modules/inquiries/index.ts
   Type: Barrel Export (Public API)
   Purpose: Định nghĩa giao diện công khai của module
   
   Exports:
     • InquiriesModule (default export for app imports)
     • INQUIRY_REPOSITORY (DI token)
     • IInquiryRepository (interface type)
     • InquiryEntity (for external access)
   
   Lines: ~4

📊 THỐNG KÊ FILE

Theo Tầng

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 - -

Theo Loại

Loại Số lượng
File nguồn (.ts, không phải test) 19
File test (.spec.ts) 6
Tổng 25

Theo Mục Đích

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
Queries 2 get-inquiries-by-*.query.ts (2 files)
Handlers 4 2 command handlers + 2 query handlers
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 bộ test trải rộng các tầng
Module 2 inquiries.module.ts, index.ts

🔍 HƯỚNG DẪN TÌM KIẾM FILE

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ụ

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

Tìm kiếm HTTP Endpoint?

presentation/controllers/inquiries.controller.ts - Toàn bộ 4 endpoint

Tìm kiếm Xác Thực Đầu Vào?

presentation/dto/ - Tất cả DTOs kèm validator

Tìm kiếm Logic Cơ Sở Dữ Liệu?

infrastructure/repositories/prisma-inquiry.repository.ts - Tất cả Prisma query

Tìm kiếm Tests?

domain/__tests__/ - Hành vi domain → application/__tests__/ - Test handler → presentation/__tests__/ - Test controller


🔗 ĐỒ THỊ PHỤ THUỘC (DEPENDENCY GRAPH)

presentation/controllers/inquiries.controller.ts
  ├── application/commands/create-inquiry/create-inquiry.handler.ts
  ├── application/commands/mark-inquiry-read/mark-inquiry-read.handler.ts
  ├── application/queries/get-inquiries-by-*/[name].handler.ts
  └── CommandBus/QueryBus (NestJS CQRS)

application/commands/*/[name].handler.ts
  ├── domain/entities/inquiry.entity.ts
  ├── domain/repositories/inquiry.repository.ts (interface)
  ├── domain/events/*.event.ts
  └── @modules/shared (AggregateRoot, exceptions)

application/queries/*/[name].handler.ts
  ├── domain/repositories/inquiry.repository.ts
  └── domain/repositories/inquiry-read.dto.ts

domain/entities/inquiry.entity.ts
  ├── @modules/shared (AggregateRoot)
  └── domain/events/*.event.ts

infrastructure/repositories/prisma-inquiry.repository.ts
  ├── domain/entities/inquiry.entity.ts
  ├── domain/repositories/inquiry.repository.ts (implements)
  ├── domain/repositories/inquiry-read.dto.ts
  └── @prisma/client (Prisma)

inquiries.module.ts
  ├── All handlers
  ├── All repositories
  ├── InquiriesController
  └── CqrsModule (NestJS)

📝 THAM CHIẾU CHÉO FILE

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

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ừ

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

Các File Có Tests

  • domain/entities/inquiry.entity.tsdomain/__tests__/inquiry-domain.spec.ts
  • application/commands/create-inquiry/create-inquiry.handler.tsapplication/__tests__/create-inquiry.handler.spec.ts
  • application/commands/mark-inquiry-read/mark-inquiry-read.handler.tsapplication/__tests__/mark-inquiry-read.handler.spec.ts
  • application/queries/get-inquiries-by-listing/application/__tests__/get-inquiries-by-listing.handler.spec.ts
  • application/queries/get-inquiries-by-agent/application/__tests__/get-inquiries-by-agent.handler.spec.ts
  • presentation/controllers/inquiries.controller.tspresentation/__tests__/inquiries.controller.spec.ts

🎯 ĐIỂM VÀO CHO VIỆC CHỈNH SỬA

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

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/

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

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

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