# ตารางสิทธิ์การใช้งานระบบ E-Learning (Permissions Matrix)

## รายการสิทธิ์ทั้งหมด (Permission List)

### 1. การจัดการผู้ใช้งาน (User Management)

| Permission Code | ชื่อสิทธิ์ | คำอธิบาย |
|----------------|-----------|---------|
| `user.register` | ลงทะเบียนผู้ใช้ใหม่ | สามารถสร้างบัญชีผู้ใช้ใหม่ในระบบ |
| `user.login` | เข้าสู่ระบบ | สามารถเข้าสู่ระบบด้วยอีเมล/รหัสผ่าน |
| `user.profile.view` | ดูโปรไฟล์ตนเอง | สามารถดูข้อมูลโปรไฟล์ของตนเอง |
| `user.profile.edit` | แก้ไขโปรไฟล์ตนเอง | สามารถแก้ไขข้อมูลส่วนตัวของตนเอง |
| `user.password.reset` | รีเซ็ตรหัสผ่าน | สามารถรีเซ็ตรหัสผ่านผ่านอีเมล |
| `user.list.view` | ดูรายการผู้ใช้ทั้งหมด | สามารถดูรายชื่อผู้ใช้ทั้งหมดในระบบ |
| `user.manage` | จัดการผู้ใช้งาน | สามารถสร้าง แก้ไข ลบบัญชีผู้ใช้ |
| `user.role.assign` | กำหนดบทบาทผู้ใช้ | สามารถกำหนดและเปลี่ยนบทบาทของผู้ใช้ |

---

### 2. การจัดการหลักสูตร (Course Management)

| Permission Code | ชื่อสิทธิ์ | คำอธิบาย |
|----------------|-----------|---------|
| `course.list.view` | ดูรายการหลักสูตร | สามารถดูรายการหลักสูตรที่เผยแพร่ |
| `course.detail.view` | ดูรายละเอียดหลักสูตร | สามารถดูรายละเอียดของหลักสูตร |
| `course.search` | ค้นหาหลักสูตร | สามารถค้นหาหลักสูตรในระบบ |
| `course.enroll` | ลงทะเบียนเรียน | สามารถลงทะเบียนเรียนหลักสูตร |
| `course.create` | สร้างหลักสูตร | สามารถสร้างหลักสูตรใหม่ |
| `course.edit` | แก้ไขหลักสูตร | สามารถแก้ไขรายละเอียดหลักสูตร |
| `course.delete` | ลบหลักสูตร | สามารถลบหลักสูตร |
| `course.status.manage` | จัดการสถานะหลักสูตร | สามารถเปลี่ยนสถานะเผยแพร่/ซ่อนหลักสูตร |
| `course.category.manage` | จัดการหมวดหมู่หลักสูตร | สามารถกำหนดหมวดหมู่หลักสูตร |

---

### 3. การจัดการเนื้อหาบทเรียน (Content Management)

| Permission Code | ชื่อสิทธิ์ | คำอธิบาย |
|----------------|-----------|---------|
| `content.view` | ดูเนื้อหาบทเรียน | สามารถเข้าถึงและดูเนื้อหาบทเรียน |
| `content.video.play` | เล่นวิดีโอ | สามารถเล่นวิดีโอการเรียนรู้ |
| `content.document.view` | ดูเอกสาร | สามารถดูเอกสาร PDF |
| `content.document.download` | ดาวน์โหลดเอกสาร | สามารถดาวน์โหลดเอกสารประกอบ |
| `content.progress.track` | ติดตามความคืบหน้า | ระบบบันทึกความคืบหน้าการเรียน |
| `content.chapter.create` | สร้าง Chapter | สามารถสร้าง Chapter ในหลักสูตร |
| `content.lesson.create` | สร้าง Lesson | สามารถสร้าง Lesson ในหลักสูตร |
| `content.chapter.edit` | แก้ไข Chapter | สามารถแก้ไข Chapter |
| `content.lesson.edit` | แก้ไข Lesson | สามารถแก้ไข Lesson |
| `content.upload` | อัปโหลดเนื้อหา | สามารถอัปโหลดวิดีโอ, PDF, ไฟล์ประกอบ |
| `content.order.manage` | จัดเรียงลำดับบทเรียน | สามารถจัดเรียงลำดับ Chapter และ Lesson |
| `content.access.manage` | กำหนดเงื่อนไขการเข้าถึง | สามารถกำหนดเงื่อนไขการเข้าถึงบทเรียน |

---

### 4. การจัดการแบบทดสอบ (Quiz & Assessment)

| Permission Code | ชื่อสิทธิ์ | คำอธิบาย |
|----------------|-----------|---------|
| `quiz.take` | ทำแบบทดสอบ | สามารถทำแบบทดสอบออนไลน์ |
| `quiz.result.view` | ดูผลคะแนนตนเอง | สามารถดูผลคะแนนและประวัติการทำแบบทดสอบของตนเอง |
| `quiz.create` | สร้างแบบทดสอบ | สามารถสร้างแบบทดสอบใหม่ |
| `quiz.edit` | แก้ไขแบบทดสอบ | สามารถแก้ไขแบบทดสอบ |
| `quiz.delete` | ลบแบบทดสอบ | สามารถลบแบบทดสอบ |
| `quiz.settings.manage` | กำหนดการตั้งค่าแบบทดสอบ | สามารถกำหนดเวลา คะแนน เกณฑ์ผ่าน |
| `quiz.results.view.all` | ดูผลคะแนนผู้เรียนทั้งหมด | สามารถดูผลคะแนนและสถิติของผู้เรียนทั้งหมด |

---

### 5. การรายงานและประเมินผล (Reporting)

| Permission Code | ชื่อสิทธิ์ | คำอธิบาย |
|----------------|-----------|---------|
| `report.progress.view.own` | ดูรายงานความคืบหน้าตนเอง | สามารถดูรายงานความคืบหน้าการเรียนของตนเอง |
| `report.score.view.own` | ดูรายงานคะแนนตนเอง | สามารถดูรายงานคะแนนแบบทดสอบของตนเอง |
| `report.certificate.view` | ดูใบประกาศนียบัตร | สามารถดูและดาวน์โหลดใบประกาศนียบัตร |
| `report.students.view` | ดูรายงานผู้เรียน | สามารถดูรายงานผู้เรียนในหลักสูตร |
| `report.progress.view.all` | ดูรายงานความคืบหน้าผู้เรียนทั้งหมด | สามารถดูความคืบหน้าการเรียนของผู้เรียนทั้งหมด |
| `report.export` | ส่งออกรายงาน | สามารถส่งออกรายงานเป็น Excel หรือ PDF |
| `report.dashboard.view` | ดู Dashboard | สามารถดู Dashboard ภาพรวมของระบบ |
| `report.statistics.view` | ดูสถิติระบบ | สามารถดูสถิติการใช้งานระบบโดยรวม |

---

### 6. การจัดการประกาศ (Announcements)

| Permission Code | ชื่อสิทธิ์ | คำอธิบาย |
|----------------|-----------|---------|
| `announcement.view` | ดูประกาศ | สามารถดูประกาศภายในหลักสูตร |
| `announcement.create` | สร้างประกาศ | สามารถโพสต์ประกาศใหม่ |
| `announcement.edit` | แก้ไขประกาศ | สามารถแก้ไขประกาศ |
| `announcement.delete` | ลบประกาศ | สามารถลบประกาศ |

---

## ตารางสิทธิ์ตามบทบาท (Role-Based Permissions Matrix)

### สัญลักษณ์
- ✅ = มีสิทธิ์
- ❌ = ไม่มีสิทธิ์
- 🔒 = มีสิทธิ์เฉพาะข้อมูลของตนเอง

---

### 1. การจัดการผู้ใช้งาน (User Management)

| สิทธิ์ | Student | Instructor | Admin |
|-------|---------|------------|-------|
| `user.register` | ✅ | ✅ | ✅ |
| `user.login` | ✅ | ✅ | ✅ |
| `user.profile.view` | 🔒 | 🔒 | 🔒 |
| `user.profile.edit` | 🔒 | 🔒 | 🔒 |
| `user.password.reset` | ✅ | ✅ | ✅ |
| `user.list.view` | ❌ | ❌ | ✅ |
| `user.manage` | ❌ | ❌ | ✅ |
| `user.role.assign` | ❌ | ❌ | ✅ |

---

### 2. การจัดการหลักสูตร (Course Management)

| สิทธิ์ | Student | Instructor | Admin |
|-------|---------|------------|-------|
| `course.list.view` | ✅ | ✅ | ✅ |
| `course.detail.view` | ✅ | ✅ | ✅ |
| `course.search` | ✅ | ✅ | ✅ |
| `course.enroll` | ✅ | ❌ | ❌ |
| `course.create` | ❌ | ✅ | ❌ |
| `course.edit` | ❌ | ✅ | ❌ |
| `course.delete` | ❌ | ✅ | ❌ |
| `course.status.manage` | ❌ | ✅ | ❌ |
| `course.category.manage` | ❌ | ✅ | ❌ |

---

### 3. การจัดการเนื้อหาบทเรียน (Content Management)

| สิทธิ์ | Student | Instructor | Admin |
|-------|---------|------------|-------|
| `content.view` | ✅ | ✅ | ❌ |
| `content.video.play` | ✅ | ✅ | ❌ |
| `content.document.view` | ✅ | ✅ | ❌ |
| `content.document.download` | ✅ | ✅ | ❌ |
| `content.progress.track` | ✅ | ❌ | ❌ |
| `content.chapter.create` | ❌ | ✅ | ❌ |
| `content.lesson.create` | ❌ | ✅ | ❌ |
| `content.chapter.edit` | ❌ | ✅ | ❌ |
| `content.lesson.edit` | ❌ | ✅ | ❌ |
| `content.upload` | ❌ | ✅ | ❌ |
| `content.order.manage` | ❌ | ✅ | ❌ |
| `content.access.manage` | ❌ | ✅ | ❌ |

---

### 4. การจัดการแบบทดสอบ (Quiz & Assessment)

| สิทธิ์ | Student | Instructor | Admin |
|-------|---------|------------|-------|
| `quiz.take` | ✅ | ❌ | ❌ |
| `quiz.result.view` | 🔒 | ❌ | ❌ |
| `quiz.create` | ❌ | ✅ | ❌ |
| `quiz.edit` | ❌ | ✅ | ❌ |
| `quiz.delete` | ❌ | ✅ | ❌ |
| `quiz.settings.manage` | ❌ | ✅ | ❌ |
| `quiz.results.view.all` | ❌ | ✅ | ❌ |

---

### 5. การรายงานและประเมินผล (Reporting)

| สิทธิ์ | Student | Instructor | Admin |
|-------|---------|------------|-------|
| `report.progress.view.own` | ✅ | ❌ | ❌ |
| `report.score.view.own` | ✅ | ❌ | ❌ |
| `report.certificate.view` | ✅ | ❌ | ❌ |
| `report.students.view` | ❌ | ✅ | ❌ |
| `report.progress.view.all` | ❌ | ✅ | ❌ |
| `report.export` | ❌ | ✅ | ❌ |
| `report.dashboard.view` | ❌ | ❌ | ✅ |
| `report.statistics.view` | ❌ | ❌ | ✅ |

---

### 6. การจัดการประกาศ (Announcements)

| สิทธิ์ | Student | Instructor | Admin |
|-------|---------|------------|-------|
| `announcement.view` | ✅ | ✅ | ❌ |
| `announcement.create` | ❌ | ✅ | ❌ |
| `announcement.edit` | ❌ | ✅ | ❌ |
| `announcement.delete` | ❌ | ✅ | ❌ |

---

## สรุปจำนวนสิทธิ์ตามบทบาท

| บทบาท | จำนวนสิทธิ์ทั้งหมด | สิทธิ์เต็ม | สิทธิ์เฉพาะตนเอง | ไม่มีสิทธิ์ |
|--------|-------------------|-----------|------------------|------------|
| **Student** | 52 | 21 | 5 | 26 |
| **Instructor** | 52 | 30 | 3 | 19 |
| **Admin** | 52 | 9 | 3 | 40 |

---

## หมายเหตุสำคัญ

### 1. การควบคุมสิทธิ์ระดับข้อมูล (Data-Level Access Control)

#### Student
- สามารถดูและแก้ไขเฉพาะโปรไฟล์ของตนเอง
- สามารถดูผลคะแนนและความคืบหน้าเฉพาะของตนเอง
- ไม่สามารถเข้าถึงข้อมูลของผู้เรียนคนอื่น

#### Instructor
- สามารถจัดการเฉพาะหลักสูตรที่ตนเองสร้างหรือได้รับมอบหมาย
- สามารถดูข้อมูลผู้เรียนเฉพาะในหลักสูตรของตนเอง
- ไม่สามารถเข้าถึงข้อมูลระดับระบบโดยรวม

#### Admin
- มีสิทธิ์เข้าถึงข้อมูลผู้ใช้ทั้งหมด
- มีสิทธิ์ดูสถิติและรายงานระดับระบบ
- ไม่มีสิทธิ์จัดการเนื้อหาการสอนโดยตรง (เป็นหน้าที่ของ Instructor)

---

### 2. การนำไปใช้งาน (Implementation Guidelines)

#### Backend API
```javascript
// ตัวอย่างการตรวจสอบสิทธิ์
const checkPermission = (user, permission) => {
  const rolePermissions = {
    STUDENT: ['user.login', 'course.enroll', 'content.view', ...],
    INSTRUCTOR: ['user.login', 'course.create', 'content.upload', ...],
    ADMIN: ['user.manage', 'user.role.assign', 'report.dashboard.view', ...]
  };
  
  return rolePermissions[user.role]?.includes(permission);
};
```

#### Frontend UI
```javascript
// ตัวอย่างการซ่อน/แสดง UI ตามสิทธิ์
const canCreateCourse = hasPermission('course.create'); // true สำหรับ Instructor
const canManageUsers = hasPermission('user.manage'); // true สำหรับ Admin
```

---

### 3. ความปลอดภัย (Security Considerations)

> [!IMPORTANT]
> - การตรวจสอบสิทธิ์ต้องทำทั้งที่ Frontend และ Backend
> - Frontend ใช้สำหรับ UX (ซ่อน/แสดง UI)
> - Backend ใช้สำหรับ Security (ป้องกันการเข้าถึงที่ไม่ได้รับอนุญาต)

> [!WARNING]
> - ห้ามพึ่งพาการตรวจสอบสิทธิ์ที่ Frontend เพียงอย่างเดียว
> - ต้องมีการตรวจสอบสิทธิ์ที่ API Layer ทุกครั้ง

---

### 4. กรณีพิเศษและ Edge Cases ที่ต้องจัดการ

> [!CAUTION]
> กรณีพิเศษเหล่านี้ต้องได้รับการจัดการอย่างถูกต้องเพื่อป้องกันช่องโหว่ด้านความปลอดภัยและปัญหาการใช้งาน

---

#### 4.1 การเปลี่ยนแปลงบทบาทผู้ใช้โดย Admin (Admin Role Management)

**สถานการณ์**: Admin เปลี่ยนบทบาทผู้ใช้ (เช่น ปรับสถานะบัญชี, แก้ไขข้อมูลผิดพลาด)

> [!NOTE]
> ในระบบนี้ **ไม่มีการเปลี่ยนบทบาทระหว่าง Student และ Instructor** ในการใช้งานปกติ
> - Student ลงทะเบียนเป็น Student ตั้งแต่แรก
> - Instructor สมัครหรือได้รับเชิญเป็น Instructor ตั้งแต่แรก
> - การเปลี่ยนบทบาทเกิดขึ้นเฉพาะกรณีพิเศษที่ Admin จัดการ (เช่น แก้ไขข้อมูลผิดพลาด)

**ปัญหาที่อาจเกิด** (กรณีพิเศษที่ Admin ต้องเปลี่ยนบทบาท):
- Session/Token เก่าอาจยังมีสิทธิ์เดิมอยู่
- ข้อมูลที่เกี่ยวข้องกับบทบาทเดิม (เช่น หลักสูตรที่สร้าง, การลงทะเบียน)

**วิธีจัดการ**:
```javascript
// Admin เปลี่ยนบทบาทผู้ใช้ (กรณีพิเศษเท่านั้น)
async function adminChangeUserRole(userId, newRole, adminId, reason) {
  const user = await getUser(userId);
  const oldRole = user.role;
  
  // บันทึก audit log
  await logRoleChange(userId, oldRole, newRole, adminId, reason);
  
  // 1. อัปเดตบทบาทในฐานข้อมูล
  await updateUserRole(userId, newRole);
  
  // 2. Invalidate all active sessions/tokens
  await invalidateUserSessions(userId);
  
  // 3. แจ้งเตือนผู้ใช้ทางอีเมล
  await notifyUserRoleChange(userId, oldRole, newRole, reason);
  
  // 4. บังคับให้ Login ใหม่
  return { 
    success: true,
    requireRelogin: true,
    message: 'เปลี่ยนบทบาทเรียบร้อย ผู้ใช้จะต้อง Login ใหม่'
  };
}
```

---

#### 4.2 การเข้าถึงหลักสูตรที่ถูกซ่อน/ลบ (Hidden/Deleted Course Access)

**สถานการณ์**: Student ลงทะเบียนเรียนหลักสูตรแล้ว แต่ Instructor เปลี่ยนสถานะเป็น "ซ่อน" หรือลบหลักสูตร

**ปัญหาที่อาจเกิด**:
- Student ที่ลงทะเบียนไว้แล้วควรเข้าถึงได้หรือไม่?
- ความคืบหน้าการเรียนจะเกิดอะไร?
- ใบประกาศนียบัตรที่ได้รับไปแล้วยังใช้ได้หรือไม่?

**วิธีจัดการ**:
```javascript
// ตรวจสอบการเข้าถึงหลักสูตร
async function canAccessCourse(userId, courseId) {
  const course = await getCourse(courseId);
  const enrollment = await getEnrollment(userId, courseId);
  
  // กรณีหลักสูตรถูกลบ
  if (course.isDeleted) {
    // อนุญาตให้ดูเฉพาะ read-only mode (ดูเนื้อหาเก่าได้ แต่ไม่สามารถทำแบบทดสอบ)
    return enrollment ? { access: 'read-only', reason: 'course_deleted' } : false;
  }
  
  // กรณีหลักสูตรถูกซ่อน
  if (course.status === 'HIDDEN') {
    // Student ที่ลงทะเบียนไว้แล้วยังเข้าถึงได้ปกติ
    if (enrollment) return { access: 'full' };
    
    // Student ใหม่ไม่สามารถลงทะเบียนได้
    return false;
  }
  
  return { access: 'full' };
}
```

**นโยบายที่แนะนำ**:
- หลักสูตรที่ถูก **ซ่อน**: Student ที่ลงทะเบียนแล้วยังเข้าถึงได้ปกติ
- หลักสูตรที่ถูก **ลบ**: เปลี่ยนเป็น Read-Only Mode (ดูเนื้อหาได้ แต่ไม่สามารถทำแบบทดสอบหรือรับใบประกาศนียบัตรใหม่)

---

#### 4.3 การลงทะเบียนซ้ำ (Duplicate Enrollment)

**สถานการณ์**: Student พยายามลงทะเบียนหลักสูตรที่ลงทะเบียนไว้แล้ว

**ปัญหาที่อาจเกิด**:
- ข้อมูลความคืบหน้าเดิมจะเป็นอย่างไร?
- ควรรีเซ็ตความคืบหน้าหรือไม่?

**วิธีจัดการ**:
```javascript
async function enrollCourse(userId, courseId) {
  const existingEnrollment = await getEnrollment(userId, courseId);
  
  if (existingEnrollment) {
    // ถ้าลงทะเบียนไว้แล้ว ให้ redirect ไปที่หลักสูตร
    return { 
      success: false, 
      message: 'คุณได้ลงทะเบียนหลักสูตรนี้ไว้แล้ว',
      redirectTo: `/courses/${courseId}`
    };
  }
  
  // สร้างการลงทะเบียนใหม่
  return await createEnrollment(userId, courseId);
}
```

---

#### 4.4 การเข้าถึงเนื้อหาที่ยังไม่ถึงลำดับ (Sequential Content Access)

**สถานการณ์**: Student พยายามเข้าถึง Lesson 5 โดยที่ยังไม่ได้เรียน Lesson 1-4

**ปัญหาที่อาจเกิด**:
- Student อาจใช้ Direct URL เพื่อข้ามลำดับ
- ระบบต้องบังคับให้เรียนตามลำดับ

**วิธีจัดการ**:
```javascript
async function canAccessLesson(userId, lessonId) {
  const lesson = await getLesson(lessonId);
  const course = await getCourse(lesson.courseId);
  
  // ถ้าหลักสูตรไม่บังคับลำดับ
  if (!course.requireSequentialAccess) {
    return true;
  }
  
  // ตรวจสอบว่าเรียน Lesson ก่อนหน้าครบหรือไม่
  const previousLessons = await getPreviousLessons(lessonId);
  const completedLessons = await getCompletedLessons(userId, lesson.courseId);
  
  const allPreviousCompleted = previousLessons.every(prev => 
    completedLessons.includes(prev.id)
  );
  
  if (!allPreviousCompleted) {
    return { 
      access: false, 
      reason: 'กรุณาเรียนบทเรียนก่อนหน้าให้เสร็จก่อน',
      nextAvailableLesson: findNextAvailableLesson(userId, lesson.courseId)
    };
  }
  
  return { access: true };
}
```

---

#### 4.5 การทำแบบทดสอบหลายครั้ง (Multiple Quiz Attempts)

**สถานการณ์**: Student ทำแบบทดสอบไม่ผ่านและต้องการทำใหม่

**ปัญหาที่อาจเกิด**:
- จำกัดจำนวนครั้งในการทำหรือไม่?
- คะแนนที่บันทึกควรเป็นครั้งแรก ครั้งสุดท้าย หรือคะแนนสูงสุด?
- ต้องรอระยะเวลาก่อนทำใหม่หรือไม่?

**วิธีจัดการ**:
```javascript
async function canTakeQuiz(userId, quizId) {
  const quiz = await getQuiz(quizId);
  const attempts = await getQuizAttempts(userId, quizId);
  
  // ตรวจสอบจำนวนครั้งที่ทำได้
  if (quiz.maxAttempts && attempts.length >= quiz.maxAttempts) {
    return { 
      canTake: false, 
      reason: `คุณทำแบบทดสอบครบ ${quiz.maxAttempts} ครั้งแล้ว` 
    };
  }
  
  // ตรวจสอบระยะเวลารอระหว่างการทำ (cooldown)
  if (quiz.cooldownMinutes && attempts.length > 0) {
    const lastAttempt = attempts[attempts.length - 1];
    const minutesSinceLastAttempt = 
      (Date.now() - lastAttempt.completedAt) / 1000 / 60;
    
    if (minutesSinceLastAttempt < quiz.cooldownMinutes) {
      const remainingMinutes = Math.ceil(
        quiz.cooldownMinutes - minutesSinceLastAttempt
      );
      return { 
        canTake: false, 
        reason: `กรุณารออีก ${remainingMinutes} นาทีก่อนทำใหม่` 
      };
    }
  }
  
  return { canTake: true };
}

// การบันทึกคะแนน
async function recordQuizScore(userId, quizId, score) {
  const quiz = await getQuiz(quizId);
  
  // กำหนดว่าจะเก็บคะแนนแบบไหน
  const scorePolicy = quiz.scorePolicy || 'HIGHEST'; // HIGHEST, LATEST, FIRST, AVERAGE
  
  await saveQuizAttempt(userId, quizId, score, scorePolicy);
}
```

**นโยบายที่แนะนำ**:
- **จำนวนครั้ง**: กำหนดได้ต่อแบบทดสอบ (เช่น 3 ครั้ง, ไม่จำกัด)
- **คะแนนที่บันทึก**: ใช้คะแนนสูงสุด (HIGHEST) เป็นค่าเริ่มต้น
- **Cooldown**: กำหนดได้ต่อแบบทดสอบ (เช่น รอ 30 นาที)

---

#### 4.6 Instructor แก้ไขหลักสูตรขณะที่ Student กำลังเรียน

**สถานการณ์**: Instructor แก้ไขเนื้อหา/ลบ Lesson ขณะที่ Student กำลังดูอยู่

**ปัญหาที่อาจเกิด**:
- Student อาจเห็นข้อผิดพลาด 404 Not Found
- ความคืบหน้าอาจไม่ถูกต้อง
- Video ที่กำลังเล่นอาจหยุดทำงาน

**วิธีจัดการ**:
```javascript
// Soft Delete แทน Hard Delete
async function deleteLesson(lessonId, instructorId) {
  const activeViewers = await getActiveLessonViewers(lessonId);
  
  if (activeViewers.length > 0) {
    // ไม่ลบทันที แต่ทำ Soft Delete
    await markLessonAsDeleted(lessonId);
    
    // แจ้งเตือน Instructor
    return {
      success: true,
      warning: `มีผู้เรียน ${activeViewers.length} คนกำลังดูบทเรียนนี้อยู่ ระบบจะซ่อนบทเรียนนี้และลบถาวรในอีก 24 ชั่วโมง`
    };
  }
  
  // ถ้าไม่มีคนดู ลบได้เลย
  await hardDeleteLesson(lessonId);
  return { success: true };
}

// ตรวจสอบการเข้าถึง Lesson
async function accessLesson(userId, lessonId) {
  const lesson = await getLesson(lessonId);
  
  if (lesson.isDeleted) {
    // ถ้า Student เข้าถึงก่อนที่จะถูกลบ ให้ดูต่อได้
    const wasAccessedBefore = await hasAccessedBefore(userId, lessonId);
    
    if (wasAccessedBefore) {
      return { 
        access: true, 
        warning: 'บทเรียนนี้จะถูกลบในเร็วๆ นี้' 
      };
    }
    
    return { access: false, reason: 'บทเรียนนี้ถูกลบแล้ว' };
  }
  
  return { access: true };
}
```

---

#### 4.7 Admin ลบบัญชี Instructor ที่มีหลักสูตรอยู่

**สถานการณ์**: Admin ลบบัญชี Instructor ที่เป็นเจ้าของหลักสูตรหลายรายการ

**ปัญหาที่อาจเกิด**:
- หลักสูตรจะกลายเป็น "ไม่มีเจ้าของ"
- Student ที่ลงทะเบียนไว้จะเข้าถึงไม่ได้
- ข้อมูลรายงานจะสูญหาย

**วิธีจัดการ**:
```javascript
async function deleteInstructor(instructorId, adminId) {
  const courses = await getCoursesByInstructor(instructorId);
  
  if (courses.length > 0) {
    // ห้ามลบถ้ายังมีหลักสูตร
    return {
      success: false,
      error: 'ไม่สามารถลบ Instructor ที่มีหลักสูตรอยู่',
      suggestion: 'กรุณาโอนหลักสูตรให้ Instructor คนอื่นก่อน',
      courses: courses.map(c => ({ id: c.id, title: c.title }))
    };
  }
  
  // Soft Delete แทน Hard Delete
  await deactivateUser(instructorId);
  
  return { 
    success: true, 
    message: 'ระงับการใช้งานบัญชีเรียบร้อย' 
  };
}

// ฟังก์ชันโอนหลักสูตร
async function transferCourses(fromInstructorId, toInstructorId, adminId) {
  const courses = await getCoursesByInstructor(fromInstructorId);
  
  for (const course of courses) {
    await updateCourseOwner(course.id, toInstructorId);
    await logOwnershipTransfer(course.id, fromInstructorId, toInstructorId, adminId);
  }
  
  return { success: true, transferredCount: courses.length };
}
```

**นโยบายที่แนะนำ**:
- ใช้ **Soft Delete** (ระงับการใช้งาน) แทน Hard Delete
- บังคับให้โอนหลักสูตรก่อนลบบัญชี
- เก็บ Audit Log ของการโอนหลักสูตร

---

#### 4.8 การเข้าถึงข้อมูลข้ามหลักสูตร (Cross-Course Data Access)

**สถานการณ์**: Instructor A พยายามดูรายงานผู้เรียนในหลักสูตรของ Instructor B

**ปัญหาที่อาจเกิด**:
- Instructor อาจใช้ API โดยตรงเพื่อเข้าถึงข้อมูลหลักสูตรอื่น
- การ Bypass ผ่าน Direct URL

**วิธีจัดการ**:
```javascript
// Middleware ตรวจสอบความเป็นเจ้าของ
async function checkCourseOwnership(req, res, next) {
  const { courseId } = req.params;
  const { userId, role } = req.user;
  
  // Admin สามารถเข้าถึงได้ทุกหลักสูตร (เฉพาะดู ไม่ใช่แก้ไข)
  if (role === 'ADMIN') {
    req.accessLevel = 'read-only';
    return next();
  }
  
  // Instructor ต้องเป็นเจ้าของหลักสูตร
  if (role === 'INSTRUCTOR') {
    const course = await getCourse(courseId);
    
    if (course.instructorId !== userId) {
      return res.status(403).json({
        error: 'คุณไม่มีสิทธิ์เข้าถึงหลักสูตรนี้'
      });
    }
    
    req.accessLevel = 'full';
    return next();
  }
  
  // Student ต้องลงทะเบียนหลักสูตรนี้
  if (role === 'STUDENT') {
    const enrollment = await getEnrollment(userId, courseId);
    
    if (!enrollment) {
      return res.status(403).json({
        error: 'คุณต้องลงทะเบียนหลักสูตรนี้ก่อน'
      });
    }
    
    req.accessLevel = 'student';
    return next();
  }
  
  return res.status(403).json({ error: 'ไม่มีสิทธิ์เข้าถึง' });
}

// ใช้งาน
app.get('/api/courses/:courseId/students', 
  authenticate, 
  checkCourseOwnership, 
  getStudentList
);
```

---

#### 4.9 Student จบหลักสูตรแล้วแต่ Instructor เพิ่มเนื้อหาใหม่

**สถานการณ์**: Student ทำครบทุก Lesson และได้ใบประกาศนียบัตรแล้ว แต่ Instructor เพิ่ม Lesson ใหม่

**ปัญหาที่อาจเกิด**:
- ความคืบหน้าจะกลับไปไม่ครบ 100%
- ใบประกาศนียบัตรยังใช้ได้หรือไม่?
- ต้องเรียนเนื้อหาใหม่หรือไม่?

**วิธีจัดการ**:
```javascript
async function calculateProgress(userId, courseId) {
  const enrollment = await getEnrollment(userId, courseId);
  const allLessons = await getCourseLessons(courseId);
  const completedLessons = await getCompletedLessons(userId, courseId);
  
  // แยกเนื้อหาเก่าและใหม่
  const lessonsAtEnrollment = allLessons.filter(
    lesson => lesson.createdAt <= enrollment.enrolledAt
  );
  
  const newLessons = allLessons.filter(
    lesson => lesson.createdAt > enrollment.enrolledAt
  );
  
  // คำนวณความคืบหน้าจากเนื้อหาตอนลงทะเบียน
  const originalProgress = 
    (completedLessons.length / lessonsAtEnrollment.length) * 100;
  
  // ถ้าจบหลักสูตรแล้ว (100% ของเนื้อหาเดิม)
  if (originalProgress === 100 && enrollment.certificateIssued) {
    return {
      progress: 100,
      status: 'COMPLETED',
      certificate: enrollment.certificateId,
      newContentAvailable: newLessons.length > 0,
      message: newLessons.length > 0 
        ? `มีเนื้อหาใหม่ ${newLessons.length} บทเรียน (ไม่บังคับ)` 
        : null
    };
  }
  
  // ถ้ายังไม่จบ คำนวณจากเนื้อหาทั้งหมด
  const totalProgress = (completedLessons.length / allLessons.length) * 100;
  
  return {
    progress: totalProgress,
    status: 'IN_PROGRESS',
    remainingLessons: allLessons.length - completedLessons.length
  };
}
```

**นโยบายที่แนะนำ**:
- ใบประกาศนียบัตรที่ออกแล้ว **ยังคงใช้ได้**
- เนื้อหาใหม่ถือเป็น **เนื้อหาเสริม** (ไม่บังคับ)
- แสดงป้าย "มีเนื้อหาใหม่" ให้ Student ที่จบแล้วทราบ

---

#### 4.10 ระบบอยู่ในช่วง Maintenance

**สถานการณ์**: ระบบต้องปิดปรับปรุงชั่วคราว

**ปัญหาที่อาจเกิด**:
- Student ที่กำลังทำแบบทดสอบจะเกิดอะไร?
- ความคืบหน้าจะสูญหายหรือไม่?

**วิธีจัดการ**:
```javascript
// Maintenance Mode Middleware
async function maintenanceMode(req, res, next) {
  const isMaintenanceMode = await getSystemSetting('maintenance_mode');
  
  if (!isMaintenanceMode) {
    return next();
  }
  
  const { role } = req.user || {};
  
  // อนุญาตให้ Admin เข้าถึงได้
  if (role === 'ADMIN') {
    return next();
  }
  
  // บันทึกข้อมูลที่กำลังทำอยู่ก่อน
  if (req.method === 'POST' || req.method === 'PUT') {
    await savePendingRequest(req);
  }
  
  return res.status(503).json({
    error: 'ระบบอยู่ในช่วงปรับปรุง',
    message: 'ขออภัยในความไม่สะดวก ระบบจะกลับมาให้บริการเร็วๆ นี้',
    estimatedTime: await getMaintenanceEndTime(),
    savedData: req.method !== 'GET' // แจ้งว่าบันทึกข้อมูลไว้แล้ว
  });
}

// Auto-save สำหรับแบบทดสอบ
async function autoSaveQuizProgress(userId, quizId, answers) {
  // บันทึกทุก 30 วินาที
  await saveQuizDraft(userId, quizId, answers, Date.now());
}

// กู้คืนข้อมูลหลัง Maintenance
async function restoreQuizProgress(userId, quizId) {
  const draft = await getQuizDraft(userId, quizId);
  
  if (draft && Date.now() - draft.savedAt < 24 * 60 * 60 * 1000) {
    return {
      canRestore: true,
      answers: draft.answers,
      savedAt: draft.savedAt
    };
  }
  
  return { canRestore: false };
}
```

**นโยบายที่แนะนำ**:
- แจ้งเตือนล่วงหน้า 24 ชั่วโมงก่อน Maintenance
- Auto-save ข้อมูลแบบทดสอบทุก 30 วินาที
- เก็บ Draft ไว้ 24 ชั่วโมงหลัง Maintenance
- อนุญาตให้ Admin เข้าถึงระบบได้ระหว่าง Maintenance

---

### 5. การขยายสิทธิ์ในอนาคต (Future Extensions)

ระบบสามารถขยายเพิ่มสิทธิ์ได้ เช่น:
- `course.moderate` - สำหรับ Moderator ที่ช่วยตรวจสอบหลักสูตร
- `content.review` - สำหรับ Reviewer ที่ตรวจสอบเนื้อหา
- `quiz.manual.grade` - สำหรับการให้คะแนนแบบอัตนัย
- `discussion.moderate` - สำหรับการดูแลกระดานสนทนา (ถ้ามีในอนาคต)
- `course.co-teach` - สำหรับการสอนร่วมกันหลาย Instructor
- `content.version.manage` - สำหรับการจัดการเวอร์ชันของเนื้อหา
