# 07. CƠ SỞ DỮ LIỆU & SƠ ĐỒ VÒNG ĐỜI DỮ LIỆU (DATABASE & DATA FLOW)

Tài liệu này tổng hợp cấu trúc các bảng cốt lõi trong cơ sở dữ liệu Tenant, quan hệ giữa các thực thể và sơ đồ vòng đời trạng thái của một bài thi.

---

## 1. Sơ Đồ Quan Hệ Thực Thể (ERD Core Tables)

```mermaid
erDiagram
    STUDENT_EXAM_HISTORIES ||--o{ STUDENT_SCORES : "chứa điểm kỹ năng"
    STUDENT_EXAM_HISTORIES ||--o{ STUDENT_ANSWERS : "lưu payload bài làm"
    STUDENT_EXAM_HISTORIES ||--o{ STUDENT_EXAM_RESULT_MAIL_LOGS : "ghi log gửi mail"
    STUDENT_EXAM_HISTORIES }o--|| USERS : "học sinh / tester"
    STUDENT_EXAM_HISTORIES }o--|| BAIKIEMTRA : "thuộc đề thi"

    STUDENT_EXAM_HISTORIES {
        int id PK
        string idHistoryContest
        int taskNumber
        float lms_score
        float ems_score
        string skill
        int tester_id FK
        datetime timeStart
        datetime timeFinish
        int status
        int is_rescore
    }

    STUDENT_SCORES {
        int id PK
        int student_exam_history_id FK
        string skill
        float score
        text comment
    }

    STUDENT_ANSWERS {
        int id PK
        int student_exam_history_id FK
        json listQuestion
        json listQuestionGraded
    }

    STUDENT_EXAM_RESULT_MAIL_LOGS {
        int id PK
        int student_exam_history_id FK
        string email_sent_to
        datetime sent_at
        string status
    }
```

---

## 2. Chi Tiết Các Bảng Dữ Liệu Cốt Lõi

### 📌 1. Bảng `student_exam_histories` (Bảng trung tâm)
- **Ý nghĩa**: Lưu trữ thông tin từng phần thi của học sinh trong một kỳ thi.
- **Các trường quan trọng**:
  - `idHistoryContest`: Mã định danh chung của toàn bộ kỳ thi/lượt thi của học sinh (dùng để gom nhóm tất cả các kỹ năng của cùng 1 lượt làm bài).
  - `taskNumber`: Số thứ tự của task/part bài thi.
  - `skill`: Mã kỹ năng (ví dụ: `EMS_SKILL_WRITING`, `EMS_SKILL_SPEAKING`, `EMS_SKILL_READING`...).
  - `lms_score`: Điểm tính theo thang điểm LMS.
  - `ems_score`: Điểm tính theo thang điểm chuẩn EMS.
  - `timeStart` & `timeFinish`: Mốc thời gian bắt đầu và kết thúc làm bài.
  - `tester_id`: ID của Giáo viên/Tester được phân công chấm bài.

### 📌 2. Bảng `student_answers` (Lưu trữ Payload JSON)
- Lưu toàn bộ cấu trúc câu hỏi (`listQuestion`) và bài làm chi tiết (`listQuestionGraded`) dưới dạng JSON.
- Được sử dụng bởi các hàm bóc tách trong `exam-detail-modal-v3.js` để hiển thị trực quan bài làm của học sinh.

### 📌 3. Bảng `student_exam_result_mail_logs` (Chống gửi trùng Email)
- Ghi lại lịch sử gửi email thông báo điểm cho học sinh và phụ huynh.
- Khi gọi hàm `notifyThirdParty`, hệ thống kiểm tra bảng này. Nếu đã có log gửi thành công thì sẽ không gửi lại, trừ khi có cờ `$force = true` (sau khi QA phúc khảo).

---

## 3. Sơ Đồ Vòng Đời Trạng Thái Bài Thi (Exam State Diagram)

```mermaid
stateDiagram-v2
    [*] --> InProgress: Học sinh bắt đầu làm bài (timeStart)
    InProgress --> Submitted: Học sinh nộp bài (timeFinish)
    
    state Submitted {
        [*] --> AutoGrading: Bóc tách Reading / Listening / Vocab
        AutoGrading --> PendingAssignment: Kỹ năng Speaking / Writing cần GV chấm
        PendingAssignment --> Assigned: Đã phân công Tester (tester_id)
        Assigned --> Graded: Tester hoàn thành chấm điểm
    }
    
    Submitted --> CheckComplete: Kiểm tra hasAllSkillsScored
    
    state CheckComplete {
        [*] --> Incomplete: Chưa đủ điểm các kỹ năng
        [*] --> AllScored: Đã đủ điểm tất cả kỹ năng
    }
    
    AllScored --> NotifyThirdParty: Kích hoạt notifyThirdParty()
    NotifyThirdParty --> CheckLog: Kiểm tra student_exam_result_mail_logs
    CheckLog --> SentMail: Gửi mail thông báo kết quả
    CheckLog --> SkipMail: Bỏ qua (Đã gửi trước đó & không có cờ force)
    
    SentMail --> [*]
    SkipMail --> [*]
```
