# Luồng hoạt động trang Basic Exam History

Tài liệu này mô tả chi tiết luồng hoạt động của trang basicExamHistory, các API được gọi, và các bảng cơ sở dữ liệu sử dụng.

---

## 1. Tổng quan (Overview)

Trang basicExamHistory hiển thị danh sách lịch sử làm bài thi của học viên với các tính năng:
- Lọc theo bài kiểm tra, trạng thái (Đạt/Không đạt), và khoảng thời gian nộp bài
- Phân trang
- Xem chi tiết bài thi qua modal (gồm thông tin học viên, các phần thi, và điểm số)

---

## 2. Luồng hoạt động chính (Main Workflow)

### Bước 1: Khởi tạo trang
1. Trang được load, `$(document).ready()` chạy
2. Khởi tạo **Date Pickers** (`start_take_exam_time` và `end_take_exam_time`) để chọn khoảng thời gian nộp bài
3. Khởi tạo **TomSelect** filters:
   - `quiz_search`: Tìm và chọn bài kiểm tra (gọi API `/api/lms/quizzes/search`)
   - `status_search`: Chọn trạng thái (Đạt/Không đạt)
4. Gọi `loadBasicExamHistories()` lần đầu để load dữ liệu bảng

### Bước 2: Load dữ liệu bảng (`loadBasicExamHistories()`)
1. Lấy các giá trị filter hiện tại
2. Gọi API `GET /api/lms/student-exam-histories/basic` với các params:
   - `page`: Số trang hiện tại
   - `perpage`: Số bản ghi/trang
   - `selectedQuizzes[]`: Danh sách ID bài kiểm tra đã chọn
   - `selectedStatuses[]`: Danh sách trạng thái đã chọn
   - `startDateTakeExam` & `endDateTakeExam`: Khoảng thời gian nộp bài
3. Nhận response, gọi `renderTableHistories()` để hiển thị dữ liệu lên bảng

### Bước 3: Xử lý tương tác người dùng
- **Thay đổi filter**: Gọi lại `loadBasicExamHistories()` để cập nhật bảng
- **Chuyển trang**: Gọi `loadBasicExamHistories(page)` với số trang mới
- **Click "Xem chi tiết bài thi"**: Gọi `openExamDetail(student_score_id)` để mở modal chi tiết

---

## 3. Các API gọi (APIs Called)

### 3.1 API `GET /api/lms/student-exam-histories/basic`
- **Mục đích**: Lấy danh sách lịch sử thi cơ bản để hiển thị trên bảng
- **Controller**: `ExamHistoryController@getBasicExamHistories`
- **Params**:
  - `page` (int, mặc định 1)
  - `perpage` (int, mặc định 10)
  - `selectedQuizzes[]` (array, optional)
  - `selectedStatuses[]` (array, optional)
  - `startDateTakeExam` (string, optional, format d-m-Y H:i)
  - `endDateTakeExam` (string, optional, format d-m-Y H:i)
- **Response**:
  ```json
  {
    "success": true,
    "data": {
      "total": 100,
      "current_page": 1,
      "per_page": 10,
      "data": [...] // Mảng các bản ghi lịch sử thi
    }
  }
  ```

### 3.2 API `GET /api/lms/quizzes/search`
- **Mục đích**: Tìm kiếm bài kiểm tra cho filter `quiz_search`
- **Params**:
  - `q` (string, optional): Từ khóa tìm kiếm
  - `is_exam_history` (bool, true)
  - `is_basic_exam_history` (bool, true)
- **Response**: Danh sách bài kiểm tra (id, name)

### 3.3 API `GET /api/student-exam-histories/{student_score_id}/overview`
- **Mục đích**: Lấy thông tin chi tiết của một bài thi để hiển thị trong modal
- **Controller**: `StudentExamHistoryController@getOverview`
- **Params**:
  - `student_score_id` (int, required): ID của bản ghi `student_score`
- **Response**:
  ```json
  {
    "success": true,
    "data": {
      "studentInfo": {...},
      "parts": [...],
      "examData": {...},
      "tenantConnection": "...",
      "rescoredSkills": [...]
    }
  }
  ```

---

## 4. Các bảng Database sử dụng (Database Tables Used)

### 4.1 Đối với API `getBasicExamHistories()`

| Tên bảng | Alias | Vai trò | Các trường chính sử dụng |
| :--- | :--- | :--- | :--- |
| `student_score` | `ss` | **Bảng chính**. Lưu trữ kết quả, điểm số và thời gian nộp bài. | `id`, `student_id`, `quiz_id`, `score_status`, `overrall_score`, `created_at`, `updated_at` |
| `students` | `s` | Lưu trữ thông tin định danh của học sinh. | `id`, `name`, `email`, `avatar`, `username` |
| `api_moodle` | `quiz` | Chứa cấu hình và tên bài thi đồng bộ từ Moodle. | `id`, `moodle_id`, `moodle_name`, `moodle_type`, `grading_type`, `total_rounds` |

**Mối quan hệ (Joins)**:
- `student_score.student_id` = `students.id`
- `student_score.quiz_id` = `api_moodle.moodle_id` (Điều kiện: `api_moodle.moodle_type = 'quiz'`)

---

### 4.2 Đối với API `getOverview()`

| Tên bảng | Alias | Vai trò | Các trường chính sử dụng |
| :--- | :--- | :--- | :--- |
| `student_score` | - | **Bảng chính**. Lấy thông tin tổng quát của bài thi. | `id`, `student_id`, `quiz_id`, `idMockContest`, `idHistoryContest`, `overrall_score`, `score_status`, `required_skills`, `created_at`, `updated_at` |
| `students` | - | Lấy thông tin học viên. | `id`, `name`, `username`, `email` |
| `student_exam_history` | - | Lấy lịch sử chi tiết từng kỹ năng của bài thi. | `id`, `student_score_id`, `student_id`, `skill`, `idHistoryContest`, `idbaikiemtra`, `lms_score`, `totalAllQuestions`, `totalCorrectQuestions`, `task_number`, `contest_type_id`, `created_at` |
| `student_score_ext` | - | Lấy dữ liệu EMS mở rộng (nếu có). | `id`, `student_score_id`, `data_ems` |
| `api_moodle` | - | Lấy cây Moodle (Quiz → Section → Course) để tìm danh sách lớp. | `id`, `moodle_id`, `moodle_name`, `moodle_type`, `parent_id` |
| `course_student` | - | Bảng trung gian để lấy lớp của học viên. | `id`, `course_id`, `class_id`, `student_id` |
| `classes` | - | Lấy tên lớp. | `id`, `name` |
| `student_exam_histories_teachers` | - | Lấy thông tin giáo viên được phân công chấm điểm (nếu có). | `id`, `student_exam_history_id`, `user_id`, `overall_rescored`, `rescored_comment`, `deadline` |
| `users` | - | Lấy tên và email giáo viên. | `id`, `name`, `email` |
| `api_moodle_ems` | - | Lấy `scoring_scale_id` để tính điểm tổng. | `id`, `api_moodle_id`, `scoring_scale_id` |

**Mối quan hệ (Joins)**:
- `student_score.student_id` = `students.id`
- `student_exam_history.student_score_id` = `student_score.id`
- `student_score_ext.student_score_id` = `student_score.id`
- `course_student.student_id` = `students.id`
- `course_student.class_id` = `classes.id`
- `student_exam_histories_teachers.student_exam_history_id` = `student_exam_history.id`
- `student_exam_histories_teachers.user_id` = `users.id`
- `api_moodle_ems.api_moodle_id` = `api_moodle.id` (với `api_moodle.moodle_id` = `student_score.quiz_id`)

---

## 5. Luồng chi tiết xem bài thi (Exam Detail Modal Workflow)

1. Người dùng click nút "Xem chi tiết bài thi" trên bảng
2. Gọi hàm `openExamDetail(student_score_id)`
3. Mở modal và hiển thị loading
4. Gọi API `GET /api/student-exam-histories/{student_score_id}/overview`
5. Backend xử lý:
   - Lấy thông tin từ `student_score`, `students`, `student_exam_history`
   - Lấy dữ liệu EMS từ `student_score_ext` hoặc gọi API EMS nếu chưa có
   - Tính toán điểm tổng (overall score) dựa trên `contest_type` hoặc `scoring_scale_id`
   - Lấy thông tin giáo viên chấm điểm từ `student_exam_histories_teachers`
   - Lấy danh sách lớp của học viên thông qua cây Moodle (Quiz → Section → Course → course_student → classes)
6. Frontend nhận response, gọi `renderSidebar(response.data)` để hiển thị thông tin
7. Tải lại icons Lucide để hiển thị đúng