# 02. QUẢN LÝ BÀI THI & QUY TRÌNH CHẤM THI (EXAM & GRADING WORKFLOW)

Module này là **trọng tâm nghiệp vụ** của hệ thống EMS Testsite, chịu trách nhiệm quản lý danh sách học sinh làm bài, mở modal bóc tách chi tiết bài làm, phân công giáo viên chấm Speaking/Writing, xử lý phúc khảo (QA) và tự động đồng bộ điểm/gửi mail kết quả.

---

## 1. Bản Đồ Các Tính Năng trong Module

| Tên Tính năng (Menu) | Route Name | Controller chính | Blade View / JS |
|---|---|---|---|
| **Danh sách học sinh làm bài** | `student-exam-history.index` | `StudentExamHistoryController@index` | `resources/views/student-exam-history/index-v2.blade.php`<br>`public/js/exam-history/exam-detail-modal-v3.js` |
| **Bài thi cần chấm của tôi** | `student-exam-history.myAssessment` | `StudentExamHistoryController@myAssessment` | `resources/views/student-exam-history/assessment.blade.php` |
| **Quản lý thi Speaking với GV** | `teacher-speaking.index` | `TeacherSpeakingController@index` | `resources/views/teacher-speaking/index.blade.php`<br>`public/js/teacher-speaking/teacher-speaking.js` |
| **Quản lý phúc khảo (QA)** | `exam-regrading.index` | `StudentExamHistoryController@regrading` | `resources/views/exam-regrading/index.blade.php` |
| **DS HS làm bài của tôi** | `student-exam-history.myStudentExamHistories` | `StudentExamHistoryController@myStudentExamHistories` | `resources/views/student-exam-history/my-student-exam-histories.blade.php` |

---

## 2. Quy Trình Vòng Đời Bài Thi (End-to-End Workflow)

```mermaid
sequenceDiagram
    autonumber
    actor Student as Học sinh
    participant Engine as Auto-Grading Engine
    participant DB as Tenant Database
    actor Teacher as Giáo viên / Tester
    actor QA as Quản lý QA
    participant ThirdParty as Webhook & Mail Service

    Student->>Engine: Nộp bài kiểm tra
    Engine->>DB: Lưu điểm Reading, Listening, Vocab
    alt Có bài thi Speaking
        DB->>Teacher: Phân công GV Speaking (TeacherSpeakingReceiveGrading)
        Teacher->>DB: Chấm điểm & Nhận xét Speaking
    end
    alt Có bài thi Writing
        DB->>Teacher: Phân công Tester Writing theo Formula
        Teacher->>DB: Chấm điểm & Tiêu chí Writing
    end
    opt Có yêu cầu phúc khảo / Hậu kiểm
        QA->>DB: QA chấm lại (QACanRescore / VHRescoreAll)
    end
    DB->>ThirdParty: notifyThirdParty() khi đủ điểm các kỹ năng
    ThirdParty-->>Student: Gửi Email Thông báo & Đồng bộ LMS
```

---

## 3. Chi Tiết Từng Tính Năng

### 3.1. Danh Sách Học Sinh Làm Bài & Modal Bóc Tách v3
- **Route**: `GET /student-exam-history` (`student-exam-histories.index`)
- **Controller**: [`StudentExamHistoryController.php`](file:///var/www/html/hocmai_testsite/app/Http/Controllers/StudentExamHistoryController.php)
- **Modal Engine**: [`public/js/exam-history/exam-detail-modal-v3.js`](file:///var/www/html/hocmai_testsite/public/js/exam-history/exam-detail-modal-v3.js)
- **Nghiệp vụ**:
  - Hiển thị danh sách toàn bộ lượt thi của học sinh kèm trạng thái, điểm từng kỹ năng, ngày nộp, và thời gian làm bài (`timeStart - timeFinish`).
  - Nút **"Xem chi tiết"** kích hoạt hàm `openExamDetail(studentScoreId)`.
  - Nút **"Chấm điểm"** kích hoạt hàm `openTeacherExamDetail(studentScoreId)`.

---

### 3.2. Quản Lý Thi Speaking Với Giáo Viên
- **Route**: `GET /teacher-speaking` (`teacher-speaking.index`)
- **Controller**: [`TeacherSpeakingController.php`](file:///var/www/html/hocmai_testsite/app/Http/Controllers/TeacherSpeakingController.php) & [`TeacherController.php`](file:///var/www/html/hocmai_testsite/app/Http/Controllers/TeacherController.php)
- **JavaScript**: [`public/js/teacher-speaking/teacher-speaking.js`](file:///var/www/html/hocmai_testsite/public/js/teacher-speaking/teacher-speaking.js)
- **Nghiệp vụ**:
  - Quản lý các lượt thi kỹ năng Speaking phỏng vấn 1-1 với giáo viên.
  - **Modal Phân công Tester Speaking**:
    - Sử dụng TomSelect tìm kiếm giáo viên qua endpoint `/teacher/search?only_teacher_speaking=1`.
    - Backend lọc chính xác các User có quyền `student-exam-histories.TeacherSpeakingReceiveGrading`.
    - Thiết lập hạn chót chấm bài (`deadline_hours`, mặc định 6 tiếng).

---

### 3.3. Bài Thi Cần Chấm Của Tôi (My Assessment)
- **Route**: `GET /student-exam-history/my-assessment` (`student-exam-histories.myAssessment`)
- **Phân quyền theo Formula**:
  - **Formula 2 hoặc 5** (EasyPass): Giáo viên cần quyền `student-exam-histories.TesterEasyPassReceiveGrading`.
  - **Formula 3 hoặc 4** (EasyIELTS): Giáo viên cần quyền `student-exam-histories.TesterEasyIeltsReceiveGrading`.
- **Nghiệp vụ**:
  - Chỉ hiển thị các bài thi mà giáo viên đó được phân công (`tester_id = auth()->id()`) hoặc chưa ai nhận trong phạm vi quyền được cấu hình.

---

### 3.4. Quản Lý Phúc Khảo (QA Regrading)
- **Route**: `GET /exam-regrading` (`exam-regrading.index`)
- **Phân quyền**: `student-exam-histories.QACanRescore`, `student-exam-histories.VHRescoreAll`.
- **Nghiệp vụ**:
  - QA kiểm tra lại kết quả bài chấm của Tester.
  - Cho phép chấm lại điểm, sửa nhận xét và lưu lịch sử thay đổi điểm.

---

### 3.5. Đồng Bộ Bên Thứ 3 & Gửi Email Tự Động (`notifyThirdParty`)
- **Phương thức**: `StudentExamHistoryController::notifyThirdParty($idHistoryContest, $force = false)`
- **Luồng hoạt động**:
  1. Kiểm tra bài thi đã có đủ điểm tất cả các kỹ năng bắt buộc chưa (`hasAllSkillsScored`).
  2. Kiểm tra bảng `student_exam_result_mail_logs` để tránh gửi email lặp lại.
  3. Nếu `$force === true` (ví dụ: sau khi QA phúc khảo xong `handlePostGradingQA`), bỏ qua bước check log để gửi bản cập nhật mới nhất.
  4. Bắn Webhook đồng bộ điểm `ems_score` và `lms_score` sang hệ thống LMS nguồn.
