# Fix Invalid Questions Batch (By Course)

## 📋 Tổng quan

API để fix invalid questions cho **TẤT CẢ exam parts** trong 1 course, chạy trong **background**.

**Use case:** Course có nhiều exam parts (10-100+), cần fix tất cả cùng lúc.

---

## 📡 API Endpoint

### **POST /api/lms/exam_part/fix-invalid-questions-by-course**

**Input:**
```json
{
  "course_id": 185
}
```

**Response:**
```json
{
  "success": true,
  "message": "Started background process to fix invalid questions for course_id: 185",
  "data": {
    "course_id": 185,
    "exam_parts_count": 25,
    "command": "php artisan exam:fix-invalid-questions 185...",
    "log_file": "storage/logs/fix_invalid_questions.log"
  }
}
```

---

## 🔄 Flow

```
┌─────────────────────────────────────────────────────────────┐
│  POST /api/lms/exam_part/fix-invalid-questions-by-course   │
│  Body: { course_id: 185 }                                   │
└─────────────────────────────────────────────────────────────┘
                          ↓
┌─────────────────────────────────────────────────────────────┐
│  API Check:                                                  │
│  - Count ImportExamPartEms where course_id = 185            │
│  - Found: 25 exam parts                                     │
└─────────────────────────────────────────────────────────────┘
                          ↓
┌─────────────────────────────────────────────────────────────┐
│  Exec Background Command:                                    │
│  php artisan exam:fix-invalid-questions 185                 │
│  >> storage/logs/fix_invalid_questions.log 2>&1 &           │
└─────────────────────────────────────────────────────────────┘
                          ↓
┌─────────────────────────────────────────────────────────────┐
│  API Return Immediately (không chờ command xong)            │
│  { success: true, ... }                                     │
└─────────────────────────────────────────────────────────────┘

Meanwhile, in background...

┌─────────────────────────────────────────────────────────────┐
│  Artisan Command Processing:                                │
│                                                              │
│  Exam Part 1/25: ✓ Updated (3 invalid, 5 valid)            │
│  Exam Part 2/25: ○ Skipped (all valid)                     │
│  Exam Part 3/25: ✓ Updated (1 invalid, 7 valid)            │
│  ...                                                         │
│  Exam Part 25/25: ✓ Updated (2 invalid, 6 valid)           │
│                                                              │
│  ═══════════════════════════════════════                   │
│  📊 SUMMARY                                                 │
│  ═══════════════════════════════════════                   │
│  Total parts: 25                                            │
│  Processed: 25                                              │
│  Updated: 18                                                │
│  Skipped: 7                                                 │
│  Failed: 0                                                  │
│  Execution time: 45.23s                                     │
└─────────────────────────────────────────────────────────────┘
```

---

## 🧪 Testing

### **1. Call API:**

```bash
curl -X POST http://localhost/api/lms/exam_part/fix-invalid-questions-by-course \
  -H "Content-Type: application/json" \
  -d '{"course_id": 185}'
```

### **2. Check Progress (Real-time):**

```bash
# Watch log file
tail -f /var/www/html/lms_hocmai/storage/logs/fix_invalid_questions.log

# Expected output:
# Starting fix invalid questions for course_id: 185
# Found 25 exam parts to process
# 
# ✓ Part 123: Updated: 5 valid, 3 invalid removed
# ○ Part 124: All 8 questions valid, skipped
# ✓ Part 125: Updated: 7 valid, 1 invalid removed
# ...
```

### **3. Check Laravel Log:**

```bash
tail -f storage/logs/laravel.log | grep "Fix invalid questions"

# Expected:
# [INFO] Started fix invalid questions background job {"course_id":185,"exam_parts_count":25}
# [INFO] Fix invalid questions batch completed {"course_id":185,"results":{...}}
```

---

## 🎯 Command Details

### **Run Manually (for testing):**

```bash
# Run command directly (không background)
php artisan exam:fix-invalid-questions 185

# Output:
# Starting fix invalid questions for course_id: 185
# Found 25 exam parts to process
#  25/25 [████████████████████████████] 100%
# 
# ✓ Part 123: Updated: 5 valid, 3 invalid removed
# ○ Part 124: All 8 questions valid, skipped
# ...
# 
# ═══════════════════════════════════════
# 📊 SUMMARY
# ═══════════════════════════════════════
# Course ID: 185
# Total parts: 25
# Processed: 25
# Updated: 18
# Skipped: 7
# Failed: 0
# Execution time: 45.23s
```

---

## 📊 Result Details

### **For each exam part:**

**Updated:**
```
✓ Part 123: Updated: 5 valid, 3 invalid removed
```

**Skipped (all valid):**
```
○ Part 124: All 8 questions valid, skipped
```

**Failed:**
```
✗ Part 125: Could not get access token from EMS
```

---

## 🔍 Process Logic

### **For each ImportExamPartEms:**

```
1. Get data_response
   ↓
2. Parse newBaikiemtra.listTestInfo[0].listQuestionDetail
   ↓
3. Check each question:
   - text = "default" → Invalid
   - text = "" → Invalid
   - text = "actual content" → Valid
   ↓
4. If has invalid questions:
   a. Filter valid questions
   b. Login to EMS
   c. Update baikiemtra (maxMark = valid count)
   d. Update test (listQuestion = valid only)
   ↓
5. If all valid:
   Skip (no update needed)
```

---

## ⚠️ Important Notes

1. **Background Process:**
   - API returns immediately
   - Process chạy background
   - Check log để xem progress

2. **Logging:**
   - Command output: `storage/logs/fix_invalid_questions.log`
   - Laravel log: `storage/logs/laravel.log`

3. **Performance:**
   - Mỗi exam part ~ 2-3 seconds (login + 2 API calls)
   - 25 exam parts ~ 45-60 seconds
   - 100 exam parts ~ 3-5 phút

4. **Error Handling:**
   - Nếu 1 part fail → continue với part tiếp theo
   - Summary report cuối cùng

---

## 📋 Comparison

| Feature | Single Part API | Batch API |
|---------|----------------|-----------|
| **Endpoint** | `/fix-invalid-questions` | `/fix-invalid-questions-by-course` |
| **Input** | `import_exam_part_id` | `course_id` |
| **Process** | 1 exam part | All exam parts |
| **Execution** | Synchronous | Background (async) |
| **Response** | Full results | Job started |
| **Log** | laravel.log | fix_invalid_questions.log |
| **Use case** | Fix 1 part | Fix nhiều parts |

---

## 🚀 Usage

### **Scenario 1: Fix 1 part cụ thể**
```bash
POST /api/lms/exam_part/fix-invalid-questions
Body: { "import_exam_part_id": 123 }
```

### **Scenario 2: Fix toàn bộ course**
```bash
POST /api/lms/exam_part/fix-invalid-questions-by-course
Body: { "course_id": 185 }

# Then watch log:
tail -f storage/logs/fix_invalid_questions.log
```

---

## 📄 Files Created

1. ✅ `app/Console/Commands/FixInvalidQuestionsByCourse.php` - Artisan command
2. ✅ `app/Http/Controllers/EmsImportController.php` - API method
3. ✅ `routes/api.php` - Route với comment
4. ✅ `docs/FIX_INVALID_QUESTIONS_BATCH_API.md` - This doc

---

**Ready to test!** 🎉

Chạy thử với course_id thực tế và watch log để xem progress!

