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,91 +1,91 @@
# Test Coverage Quick Reference Guide
# Hướng Dẫn Tham Khảo Nhanh về Độ Phủ Kiểm Thử
## 17 Untested Source Files Overview
## Tổng Quan 17 Tệp Nguồn Chưa Được Kiểm Thử
### INQUIRIES MODULE (4 files)
### MODULE INQUIRIES (4 tệp)
```
1. prisma-inquiry.repository.ts — 6 methods to test + 1 private mapper
2. inquiries.controller.ts — 4 endpoints to test + guard validation
3. create-inquiry.dto.ts — 3 field validations
4. list-inquiries.dto.ts — 2 field validations (pagination)
1. prisma-inquiry.repository.ts — 6 phương thức cần kiểm thử + 1 mapper riêng
2. inquiries.controller.ts — 4 endpoint cần kiểm thử + xác thực guard
3. create-inquiry.dto.ts — 3 xác thực trường dữ liệu
4. list-inquiries.dto.ts — 2 xác thực trường dữ liệu (phân trang)
```
### LEADS MODULE (6 files)
### MODULE LEADS (6 tệp)
```
5. prisma-lead.repository.ts — 6 methods + stats aggregation
6. lead-score.vo.ts — Value object: range 0-100
7. leads.controller.ts — 5 endpoints + class-level role guard
8. create-lead.dto.ts — 6 field validations
9. list-leads.dto.ts — Status enum + pagination
10. update-lead-status.dto.ts — Status enum validation
5. prisma-lead.repository.ts — 6 phương thức + tổng hợp thống kê
6. lead-score.vo.ts — Value object: phạm vi 0-100
7. leads.controller.ts — 5 endpoint + role guard cấp class
8. create-lead.dto.ts — 6 xác thực trường dữ liệu
9. list-leads.dto.ts — Enum trạng thái + phân trang
10. update-lead-status.dto.ts — Xác thực enum trạng thái
```
### REVIEWS MODULE (5 files)
### MODULE REVIEWS (5 tệp)
```
11. prisma-review.repository.ts — 7 methods + stats with distribution
12. rating.vo.ts — Value object: range 1-5 (integers only)
13. reviews.controller.ts — 5 endpoints + mixed auth
14. create-review.dto.ts — 4 field validations
15. list-reviews.dto.ts — 2 DTOs: ListReviewsByTargetDto, ReviewStatsDto
11. prisma-review.repository.ts — 7 phương thức + thống kê với phân phối
12. rating.vo.ts — Value object: phạm vi 1-5 (chỉ số nguyên)
13. reviews.controller.ts — 5 endpoint + xác thực hỗn hợp
14. create-review.dto.ts — 4 xác thực trường dữ liệu
15. list-reviews.dto.ts — 2 DTO: ListReviewsByTargetDto, ReviewStatsDto
```
### REFERENCE PATTERNS (2 test files)
### MẪU THAM KHẢO (2 tệp kiểm thử)
```
16. create-inquiry.handler.spec.ts — Handler test pattern
17. create-lead.handler.spec.ts — Handler test pattern
18. reviews.controller.spec.ts — Controller test pattern
16. create-inquiry.handler.spec.ts — Mẫu kiểm thử handler
17. create-lead.handler.spec.ts — Mẫu kiểm thử handler
18. reviews.controller.spec.ts — Mẫu kiểm thử controller
```
---
## Quick Test Scenarios by Type
## Kịch Bản Kiểm Thử Nhanh Theo Loại
### REPOSITORIES (3 files)
Test checklist for each repository:
- [ ] findById() returns entity or null
- [ ] save() creates record with correct data mapping
- [ ] Paginated methods respect limit cap (100 max)
- [ ] Pagination calculation: skip = (page - 1) * take
- [ ] Relationships are joined correctly
- [ ] Aggregations calculate correctly (stats methods)
- [ ] Optional fields handling (null coercion)
- [ ] ISO date formatting in DTOs
### REPOSITORIES (3 tệp)
Danh sách kiểm tra cho từng repository:
- [ ] findById() trả về entity hoặc null
- [ ] save() tạo bản ghi với ánh xạ dữ liệu đúng
- [ ] Các phương thức phân trang tuân thủ giới hạn tối đa (tối đa 100)
- [ ] Tính toán phân trang: skip = (page - 1) * take
- [ ] Các quan hệ được nối đúng
- [ ] Các phép tổng hợp tính toán đúng (các phương thức thống kê)
- [ ] Xử lý trường tùy chọn (ép kiểu null)
- [ ] Định dạng ngày ISO trong DTO
**Specific to PrismaInquiryRepository:**
- countUnreadByAgent() aggregation
- findByListing() includes property.title
- findByAgent() joins through listing.agentId
**Riêng cho PrismaInquiryRepository:**
- countUnreadByAgent() tổng hợp
- findByListing() bao gồm property.title
- findByAgent() nối qua listing.agentId
**Specific to PrismaLeadRepository:**
- findByAgent() optional status filter
- getStatsByAgent() calculates:
**Riêng cho PrismaLeadRepository:**
- findByAgent() bộ lọc trạng thái tùy chọn
- getStatsByAgent() tính toán:
- totalLeads count
- byStatus object (dict of counts)
- conversionRate: (CONVERTED / total) * 100 (2 decimals)
- avgScore: average of non-null scores (1 decimal)
- conversionRate: (CONVERTED / total) * 100 (2 chữ số thập phân)
- avgScore: trung bình của các điểm khác null (1 chữ số thập phân)
**Specific to PrismaReviewRepository:**
- findByUserAndTarget() unique constraint query
- getStats() builds distribution object (keys 1-5)
- averageRating calculation: (sum / total) * 10 / 10 (1 decimal)
**Riêng cho PrismaReviewRepository:**
- findByUserAndTarget() truy vấn ràng buộc duy nhất
- getStats() xây dựng đối tượng phân phối (khóa 1-5)
- Tính toán averageRating: (sum / total) * 10 / 10 (1 chữ số thập phân)
---
### VALUE OBJECTS (2 files)
Test checklist:
- [ ] create() with valid value returns Result.ok()
- [ ] create() with invalid value returns Result.err() with correct message
- [ ] Getter returns props.value
- [ ] Invalid cases covered (negative, > max, non-integer, null)
### VALUE OBJECTS (2 tệp)
Danh sách kiểm tra:
- [ ] create() với giá trị hợp lệ trả về Result.ok()
- [ ] create() với giá trị không hợp lệ trả về Result.err() với thông báo đúng
- [ ] Getter trả về props.value
- [ ] Các trường hợp không hợp lệ được bao phủ (âm, > max, không phải số nguyên, null)
**LeadScore validation:**
**Xác thực LeadScore:**
```
✓ Valid: 0, 50, 100
✗ Invalid: -1, 101, 2.5, null, "50"
Error: "Điểm lead phải từ 0 đến 100"
```
**Rating validation:**
**Xác thực Rating:**
```
✓ Valid: 1, 2, 3, 4, 5
✗ Invalid: 0, 6, 2.5, null, "5"
@@ -94,94 +94,94 @@ Error: "Đánh giá phải từ 1 đến 5 sao"
---
### CONTROLLERS (2 files)
Test checklist:
- [ ] Each endpoint dispatches correct command/query type
- [ ] Parameters are mapped correctly from DTO
- [ ] Optional fields become null (e.g., phone ?? null → null)
- [ ] Default pagination values applied (page: 1, limit: 20)
- [ ] CurrentUser decorator extracts user.sub correctly
- [ ] Guard enforcement (@UseGuards, @Roles)
- [ ] Return types match (e.g., { deleted: true })
### CONTROLLERS (2 tệp)
Danh sách kiểm tra:
- [ ] Mỗi endpoint điều phối đúng loại command/query
- [ ] Các tham số được ánh xạ đúng từ DTO
- [ ] Các trường tùy chọn trở thành null (ví dụ: phone ?? null → null)
- [ ] Các giá trị phân trang mặc định được áp dụng (page: 1, limit: 20)
- [ ] Decorator CurrentUser trích xuất user.sub đúng
- [ ] Thực thi guard (@UseGuards, @Roles)
- [ ] Kiểu trả về khớp (ví dụ: { deleted: true })
**InquiriesController specifics:**
- POST /inquiries: phone optional → null
- GET /inquiries/listing/:listingId: requires JWT
- GET /inquiries/agent/me: requires JWT + AGENT role
- PATCH /inquiries/:id/read: requires JWT + AGENT role
**Đặc điểm riêng của InquiriesController:**
- POST /inquiries: phone tùy chọn → null
- GET /inquiries/listing/:listingId: yêu cầu JWT
- GET /inquiries/agent/me: yêu cầu JWT + vai trò AGENT
- PATCH /inquiries/:id/read: yêu cầu JWT + vai trò AGENT
**LeadsController specifics:**
- ALL endpoints require JWT + AGENT role (class-level @Roles)
- POST /leads: score optional, score range validation in command
- GET /leads: status filter optional
- GET /leads/stats: aggregation query
- PATCH /leads/:id/status: only status field in command
- DELETE /leads/:id: agentId verification in command
**Đặc điểm riêng của LeadsController:**
- TẤT CẢ endpoint yêu cầu JWT + vai trò AGENT (cấp class @Roles)
- POST /leads: score tùy chọn, xác thực phạm vi score trong command
- GET /leads: bộ lọc trạng thái tùy chọn
- GET /leads/stats: truy vấn tổng hợp
- PATCH /leads/:id/status: chỉ trường status trong command
- DELETE /leads/:id: xác thực agentId trong command
**ReviewsController specifics:**
- POST /reviews: requires JWT (AuthGuard)
- GET /reviews: NO auth required (stats are public)
- GET /reviews/stats: NO auth required
- GET /reviews/me: requires JWT
- DELETE /reviews/:id: requires JWT + ownership check in command
**Đặc điểm riêng của ReviewsController:**
- POST /reviews: yêu cầu JWT (AuthGuard)
- GET /reviews: KHÔNG yêu cầu xác thực (thống kê là công khai)
- GET /reviews/stats: KHÔNG yêu cầu xác thực
- GET /reviews/me: yêu cầu JWT
- DELETE /reviews/:id: yêu cầu JWT + kiểm tra quyền sở hữu trong command
---
### DTOs (10 files)
Test checklist:
- [ ] Required fields throw ValidationException if missing
- [ ] String max/min length validated
- [ ] Number min/max validated
- [ ] Enum @IsIn() validates allowed values
- [ ] Type transformation (class-transformer @Type)
- [ ] Email format validated (@IsEmail)
- [ ] Optional fields (@IsOptional) don't throw if omitted
### DTOs (10 tệp)
Danh sách kiểm tra:
- [ ] Các trường bắt buộc ném ValidationException nếu thiếu
- [ ] Độ dài tối đa/tối thiểu của chuỗi được xác thực
- [ ] Giá trị tối thiểu/tối đa của số được xác thực
- [ ] Enum @IsIn() xác thực các giá trị được phép
- [ ] Chuyển đổi kiểu (class-transformer @Type)
- [ ] Định dạng email được xác thực (@IsEmail)
- [ ] Các trường tùy chọn (@IsOptional) không ném lỗi nếu bỏ qua
**Pagination standard (used in 5 DTOs):**
- page: optional, @Min(1), default 1
- limit: optional, @Min(1), @Max(100), default 20
- Both use @Type(() => Number) for string→number transformation
**Chuẩn phân trang (dùng trong 5 DTO):**
- page: tùy chọn, @Min(1), mặc định 1
- limit: tùy chọn, @Min(1), @Max(100), mặc định 20
- Cả hai dùng @Type(() => Number) để chuyển đổi chuỗi→số
**Enum validations:**
**Xác thực enum:**
- LeadStatus: ['NEW', 'CONTACTED', 'QUALIFIED', 'NEGOTIATING', 'CONVERTED', 'LOST']
- Used in: ListLeadsDto, UpdateLeadStatusDto
- Dùng trong: ListLeadsDto, UpdateLeadStatusDto
---
## Test Priority Matrix
## Ma Trận Ưu Tiên Kiểm Thử
### 🔴 CRITICAL (Business Logic)
1. PrismaReviewRepository.getStats() - distribution calculation
2. PrismaLeadRepository.getStatsByAgent() - conversion rate formula
3. Rating.vo - must be 1-5 integers only
4. LeadScore.vo - must be 0-100 range
### 🔴 QUAN TRỌNG (Logic Nghiệp Vụ)
1. PrismaReviewRepository.getStats() - tính toán phân phối
2. PrismaLeadRepository.getStatsByAgent() - công thức tỷ lệ chuyển đổi
3. Rating.vo - phải là số nguyên từ 1-5
4. LeadScore.vo - phải trong phạm vi 0-100
### 🟡 HIGH (Data Integrity)
1. All repository CRUD methods
2. Pagination calculations
3. Relationship mapping (user joins, listing joins)
4. Controller parameter mapping
### 🟡 CAO (Tính Toàn Vẹn Dữ Liệu)
1. Tất cả phương thức CRUD của repository
2. Tính toán phân trang
3. Ánh xạ quan hệ (nối user, nối listing)
4. Ánh xạ tham số controller
### 🟢 MEDIUM (Validation)
1. DTO field validations
2. Enum constraints
3. Optional field handling
4. Guard enforcement
### 🟢 TRUNG BÌNH (Xác Thực)
1. Xác thực trường DTO
2. Ràng buộc enum
3. Xử lý trường tùy chọn
4. Thực thi guard
---
## Test Execution Order Recommendation
## Khuyến Nghị Thứ Tự Thực Thi Kiểm Thử
1. **Value Objects** (2 files) - 2 simple test files
2. **DTOs** (10 files) - Use class-validator testing patterns
3. **Controllers** (2 files) - Command/query dispatch tests
4. **Repositories** (3 files) - Data layer tests with mocked Prisma
1. **Value Objects** (2 tệp) - 2 tệp kiểm thử đơn giản
2. **DTOs** (10 tệp) - Dùng mẫu kiểm thử class-validator
3. **Controllers** (2 tệp) - Kiểm thử điều phối command/query
4. **Repositories** (3 tệp) - Kiểm thử tầng dữ liệu với Prisma được giả lập
---
## Mock Setup Template
## Mẫu Thiết Lập Mock
### For Repositories:
### Cho Repositories:
```typescript
const mockPrisma = {
inquiry: { findUnique: vi.fn(), findMany: vi.fn(), create: vi.fn(), update: vi.fn(), delete: vi.fn(), count: vi.fn() },
@@ -189,69 +189,69 @@ const mockPrisma = {
const repo = new PrismaInquiryRepository(mockPrisma as any);
```
### For Controllers:
### Cho Controllers:
```typescript
const mockCommandBus = { execute: vi.fn() };
const mockQueryBus = { execute: vi.fn() };
const controller = new InquiriesController(mockCommandBus as any, mockQueryBus as any);
```
### For Value Objects:
### Cho Value Objects:
```typescript
const result = LeadScore.create(75);
expect(result.isOk()).toBe(true);
expect(result.unwrap().value).toBe(75);
```
### For DTOs:
### Cho DTOs:
```typescript
import { validate } from 'class-validator';
const dto = new CreateLeadDto();
dto.name = 'Nguyễn Văn A';
dto.phone = '0901234567';
// ... set other required fields
// ... đặt các trường bắt buộc khác
const errors = await validate(dto);
expect(errors).toHaveLength(0);
```
---
## Key Formulas to Verify
## Các Công Thức Cần Xác Minh
### Pagination:
### Phân trang:
```
skip = (page - 1) * take
totalPages = Math.ceil(total / take)
take = Math.min(limit, 100)
```
### Lead Conversion Rate:
### Tỷ Lệ Chuyển Đổi Lead:
```
conversionRate = (convertedCount / totalLeads) * 100
Result: rounded to 2 decimals (e.g., 33.33)
Kết quả: làm tròn đến 2 chữ số thập phân (ví dụ: 33.33)
```
### Lead Average Score:
### Điểm Trung Bình Lead:
```
avgScore = scoreSum / scoreCount (where score !== null)
Result: rounded to 1 decimal (e.g., 75.5)
Kết quả: làm tròn đến 1 chữ số thập phân (ví dụ: 75.5)
```
### Review Average Rating:
### Đánh Giá Trung Bình Review:
```
averageRating = (sum / totalReviews)
Result: rounded to 1 decimal (e.g., 4.5)
Kết quả: làm tròn đến 1 chữ số thập phân (ví dụ: 4.5)
```
### Review Distribution:
### Phân Phối Review:
```
distribution: { 1: count, 2: count, 3: count, 4: count, 5: count }
Must initialize all 5 keys, even if 0
Phải khởi tạo tất cả 5 khóa, kể cả khi bằng 0
```
---
## File Locations for Reference
## Vị Trí Tệp Để Tham Khảo
```
/Users/velikho/Desktop/WORKING/goodgo-platform-ai/apps/api/
@@ -280,22 +280,21 @@ Reviews:
---
## Next Steps
## Các Bước Tiếp Theo
1. **Copy reference test patterns:**
- Create inquiry and lead handlers already have good test patterns
- Controller test for reviews shows endpoint testing approach
1. **Sao chép các mẫu kiểm thử tham khảo:**
- Các handler tạo inquiry lead đã có mẫu kiểm thử tốt
- Kiểm thử controller cho reviews cho thấy cách tiếp cận kiểm thử endpoint
2. **Start with repositories:**
- Most complex (Prisma mocking)
- Most critical (data layer)
- Established patterns in existing tests
2. **Bắt đầu với repositories:**
- Phức tạp nhất (giả lập Prisma)
- Quan trọng nhất (tầng dữ liệu)
- Các mẫu đã được thiết lập trong các kiểm thử hiện có
3. **Test DTOs second:**
- Quick feedback (class-validator validation)
- 10 files but mostly simple
4. **Controllers and VOs last:**
- Build on repository/DTO tests
- Depend on handler tests (if testing full flow)
3. **Kiểm thử DTO thứ hai:**
- Phản hồi nhanh (xác thực class-validator)
- 10 tệp nhưng hầu hết đơn giản
4. **Controllers và VO sau cùng:**
- Xây dựng trên các kiểm thử repository/DTO
- Phụ thuộc vào các kiểm thử handler (nếu kiểm thử toàn bộ luồng)