# Phân Hệ Quản Lý Chấm Thủ Công (Web Exam Grading)
## 03. Sơ Đồ Chức Năng & Thiết Kế API/Job (Function Diagram & Design)

---

### 1. Kiến Trúc Thành Phần Phân Hệ (System Architecture)

```mermaid
graph TD
    subgraph Client ["Client Presentation Layer"]
        BladeView["Blade View: exam-grading.index-v2"]
        JSController["JS: exam-grading-v2.js"]
        ModalEdit["Modal Chấm Bài: exam-detail-modal.edit.js"]
        ExportModal["Modal Tiến Độ Xuất Báo Cáo"]
    end

    subgraph RoutingSecurity ["Routing & Security"]
        Routes["routes/web.php (prefix: exam-grading)"]
        AuthMid["Middleware: auth, check.permission"]
        TenantMid["Middleware: tenant.access:web"]
    end

    subgraph ControllerLayer ["Application Controller Layer"]
        EGC["ExamGradingController"]
        ExportJob["ExportExamGradingJob (Queue Worker)"]
    end

    subgraph ServiceHelper ["Service & Calculation Layer"]
        IclScoreSvc["IclScoreService (Calculate Score Before Review)"]
        MoodleSvc["ApiMoodleService (Category Map Resolver)"]
        HelperTenant["HelperTenant"]
    end

    subgraph DataStorage ["Data & Cache Storage"]
        DB[(MySQL Database - Multi-Tenant)]
        RedisCache[(Redis Cache - Export Progress & Categories)]
        DiskStorage[(Disk Storage - CSV / ZIP Exports)]
    end

    BladeView --> JSController
    JSController --> RoutingSecurity
    RoutingSecurity --> EGC

    EGC --> IclScoreSvc
    EGC --> MoodleSvc
    EGC --> HelperTenant
    EGC -->|Dispatch| ExportJob
    EGC --> DB

    ExportJob --> DB
    ExportJob --> RedisCache
    ExportJob --> DiskStorage

    JSController -.->|Mở trực tiếp| ModalEdit
```

---

### 2. Sơ Đồ Luồng Xử Lý Chức Năng (Function Flowcharts)

#### 2.1. Hàm `getExamGrading` (ExamGradingController)

```mermaid
flowchart TD
    Start([GET /exam-grading/list]) --> GetTenant[Lấy Tenant Connection]
    GetTenant --> BuildQ[Gọi buildExamGradingQuery: Nối TAH, SEHT, SS, Students, ApiMoodle]
    BuildQ --> CheckPerm{Có quyền viewAllGrading?}
    
    CheckPerm -- Không --> FilterMine[Lọc tah.user_id = GV hiện tại VÀ tah.id = MAX tah.id]
    CheckPerm -- Có --> FilterAdmin[Cho phép xem toàn bộ và lọc theo teacher_id]
    
    FilterMine --> ExecPaginate[Thực thi phân trang per_page theo seht.id DESC]
    FilterAdmin --> ExecPaginate
    
    ExecPaginate --> BatchLoad[Batch Load StudentExamHistory & StudentScoreGradingHistory assign_type=1]
    BatchLoad --> LoopItems[Lặp qua từng phần tử trong Collection]
    
    LoopItems --> CalcBefore[Tính score_before_review qua IclScoreService]
    LoopItems --> ParseAfter[Parse score_after_review từ data_ems_snapshot]
    LoopItems --> FormatFields[Format skill_name, product Root Category, abnormal]
    
    FormatFields --> CheckNext{Hết danh sách?}
    CheckNext -- Chưa --> LoopItems
    CheckNext -- Rồi --> ReturnJSON[HTTP 200 JSON {success: true, data, can_view_all_grading}]
```

---

#### 2.2. Hàm `export` & `ExportExamGradingJob` (Xuất Báo Cáo Chấm Thi)

```mermaid
flowchart TD
    subgraph WebController ["ExamGradingController::export"]
        A[POST /exam-grading/export kèm bộ lọc] --> B[Resolve vai trò người dùng: Admin / Teacher]
        B --> C[Đếm tổng số bản ghi & tính số batch: 5000 records/batch]
        C --> D[Sinh export_id UUID]
        D --> E[Khởi tạo Cache: export_progress_{exportId} status = processing]
        E --> F[Dispatch ExportExamGradingJob]
        F --> G[Trả về ngay HTTP 200 {success: true, export_id}]
    end

    subgraph QueueWorker ["ExportExamGradingJob::handle"]
        F -.-> H[Tạo thư mục exports/exam_grading/export_id trên Disk]
        H --> LoopB[Lặp từng batch từ 0 -> totalBatches - 1]
        LoopB --> WriteCSV[Query 5000 dòng, format 25 cột dữ liệu, ghi file CSV part]
        WriteCSV --> UpdCache[Cập nhật exported_batches trong Cache]
        UpdCache --> NextB{Còn batch?}
        NextB -- Còn --> LoopB
        NextB -- Hết --> ZipCSV[Nén tất cả file CSV thành exam_grading_export.zip]
        ZipCSV --> DelTemp[Xóa các file CSV tạm]
        DelTemp --> DoneCache[Cập nhật Cache: status = completed, file_url]
    end

    subgraph FrontendPolling ["Frontend Polling"]
        G -.-> Poll[FE gọi GET /exam-grading/export-progress/export_id mỗi 1.5s]
        Poll --> IsDone{status == completed?}
        IsDone -- Chưa --> Poll
        IsDone -- Rồi --> Download[Tải tự động qua GET /exam-grading/download/export_id]
    end
```

---

### 3. Đặc Tả API Chi Tiết (API Endpoints Specification)

#### 3.1. `GET /exam-grading/list` (Lấy danh sách quản lý chấm bài)
- **Route Name**: `exam-grading.getExamGrading`
- **Middleware**: `auth`, `check.permission`, `tenant.access:web`
- **Request Parameters (Query)**:
  | Tham số | Kiểu | Mô tả |
  | :--- | :---: | :--- |
  | `page` | Integer | Số trang (Mặc định: 1) |
  | `per_page` | Integer | Số dòng/trang (Mặc định: 10) |
  | `start_date` / `end_date` | String | Lọc theo khoảng ngày phân công chấm (`d-m-Y`) |
  | `phone` / `email` | String | Tìm theo số điện thoại hoặc email học viên |
  | `student_score_id` | Integer | Tìm chính xác theo mã bài thi |
  | `teacher_id[]` | Array[Int] | Lọc theo ID giáo viên được phân công |
  | `student_code[]` | Array[Int] | Danh sách ID học viên |
  | `product[]` / `course[]` / `exam[]` | Array[Int] | Mảng ID Sản phẩm, Khóa học, Bài thi |
  | `grading_status` | Integer / String | Trạng thái chấm (`0`: Chờ chấm, `1`: Đã hoàn thành) |
  | `point_status` | Integer / String | Trạng thái xử lý điểm (`0`: Đang xử lý, `1`: Hoàn tất) |
- **Response Success (200 OK)**:
  ```json
  {
      "success": true,
      "can_view_all_grading": true,
      "data": {
          "current_page": 1,
          "last_page": 8,
          "total": 76,
          "data": [
              {
                  "tah_id": 890,
                  "seht_id": 450,
                  "student_score_id": 5001,
                  "teacherEmail": "teacher.lan@hocmai.vn",
                  "studentName": "Trần Thị B",
                  "studentEmail": "tranthib@gmail.com",
                  "studentCode": "HV_2026_09",
                  "classCode": "IELTS_K12_A",
                  "product": "IELTS Master",
                  "course": "IELTS Intensive 6.5+",
                  "exam": "Mocktest 02 - Full Test",
                  "skill": 15,
                  "skill_name": "Writing",
                  "timeStart": "2026-10-05 14:00:00",
                  "timeEnd": "2026-10-05 15:30:00",
                  "assignedTime": "2026-10-05 16:00:00",
                  "deadline": "2026-10-07 16:00:00",
                  "statusId": 1,
                  "abnormal": "Bình thường",
                  "score_before_review": {
                      "overall": 6.0,
                      "skills": {
                          "Listening": 7.0,
                          "Reading": 6.5,
                          "Writing": 5.5,
                          "Speaking": 6.0
                      }
                  },
                  "score_after_review": {
                      "overall": 6.5,
                      "skills": {
                          "Listening": 7.0,
                          "Reading": 6.5,
                          "Writing": 6.0,
                          "Speaking": 6.5
                      }
                  }
              }
          ]
      }
  }
  ```

---

#### 3.2. `POST /exam-grading/export` (Khởi tạo xuất báo cáo chấm)
- **Route Name**: `exam-grading.export`
- **Response Success (200 OK)**:
  ```json
  {
      "success": true,
      "export_id": "8d3e7b1a-4c2f-4e9b-9a1d-3b5e7f9a1c2d"
  }
  ```

---

#### 3.3. `GET /exam-grading/export-progress/{export_id}` (Kiểm tra tiến độ xuất)
- **Route Name**: `exam-grading.export-progress`
- **Response Success (200 OK)**:
  ```json
  {
      "success": true,
      "data": {
          "status": "completed",
          "total_batches": 2,
          "exported_batches": 2,
          "file_url": "https://lms.hocmai.vn/exam-grading/download/8d3e7b1a-4c2f-4e9b-9a1d-3b5e7f9a1c2d"
      }
  }
  ```

---

#### 3.4. `GET /exam-grading/download/{export_id}` (Tải file ZIP)
- **Route Name**: `exam-grading.download`
- **Output**: Binary Stream File `exam_grading_export.zip` chứa các file CSV với 25 cột dữ liệu chi tiết.
