# WEEK 4: QUESTION BANK ENHANCEMENTS - Implementation Documentation

This document provides comprehensive documentation for all the Question Bank Enhancement features implemented in Week 4.

## Table of Contents
1. [Day 1: Question Hierarchy Browsing](#day-1-question-hierarchy-browsing)
2. [Day 2-3: Question Edit/Update Functionality](#day-2-3-question-editupdate-functionality)
3. [Day 4: Soft Deletes for Questions](#day-4-soft-deletes-for-questions)
4. [Day 5: Question Audit Trail](#day-5-question-audit-trail)
5. [Database Migrations](#database-migrations)
6. [Testing Guide](#testing-guide)

---

## Day 1: Question Hierarchy Browsing

### Endpoint: Get Question Hierarchy

**URL:** `GET /api/v2/tutor/question-bank/hierarchy`

**Description:** Fetch the question hierarchy (Class → Subject → Topic) with question counts. Results are cached for 1 hour.

**Authentication:** Required (Teacher role)

**Query Parameters:**
- `class_id` (optional): Filter by specific class ID
- `subject_id` (optional): Filter by specific subject ID

### cURL Examples

#### Get Full Hierarchy
```bash
curl --location 'http://127.0.0.1:8000/api/v2/tutor/question-bank/hierarchy' \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
--header 'Accept: application/json'
```

#### Filter by Class
```bash
curl --location 'http://127.0.0.1:8000/api/v2/tutor/question-bank/hierarchy?class_id=1' \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
--header 'Accept: application/json'
```

#### Filter by Class and Subject
```bash
curl --location 'http://127.0.0.1:8000/api/v2/tutor/question-bank/hierarchy?class_id=1&subject_id=5' \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
--header 'Accept: application/json'
```

### Response Example
```json
{
  "status": true,
  "message": "Question hierarchy retrieved successfully",
  "data": {
    "classes": [
      {
        "id": 1,
        "name": "Class 10",
        "description": "Class 10 Mathematics",
        "subjects": [
          {
            "id": 5,
            "name": "Mathematics",
            "title": "Mathematics - Class 10",
            "topics": [
              {
                "id": 23,
                "name": "Algebra",
                "title": "Algebra Basics",
                "question_count": 150
              },
              {
                "id": 24,
                "name": "Geometry",
                "title": "Geometry Fundamentals",
                "question_count": 89
              }
            ]
          }
        ]
      }
    ],
    "cache_enabled": true,
    "cached_until": "2025-11-13T13:00:00+00:00",
    "filters_applied": {
      "class_id": null,
      "subject_id": null
    }
  }
}
```

### Clear Hierarchy Cache

**URL:** `POST /api/v2/tutor/question-bank/clear-cache`

```bash
curl --location --request POST 'http://127.0.0.1:8000/api/v2/tutor/question-bank/clear-cache' \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
--header 'Accept: application/json'
```

**Response:**
```json
{
  "status": true,
  "message": "Question hierarchy cache cleared successfully"
}
```

---

## Day 2-3: Question Edit/Update Functionality

### Endpoint: Get Single Question

**URL:** `GET /api/v2/tutor/questions/{id}`

**Description:** Retrieve a single question with all details including translations and usage statistics.

**Authentication:** Required (Teacher role)

### cURL Example
```bash
curl --location 'http://127.0.0.1:8000/api/v2/tutor/questions/123' \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
--header 'Accept: application/json'
```

### Response Example
```json
{
  "status": true,
  "message": "Question retrieved successfully",
  "data": {
    "id": 123,
    "question": "<p>What is the capital of France?</p>",
    "question_type": "mcq",
    "answer_type": "single",
    "marks": 1,
    "time": 60,
    "category_id": "23",
    "status": 1,
    "added_by": 5,
    "subjective_ans": null,
    "translation": {
      "question_text": "<p>What is the capital of France?</p>",
      "option_a": "<p>Paris</p>",
      "option_b": "<p>London</p>",
      "option_c": "<p>Berlin</p>",
      "option_d": "<p>Madrid</p>",
      "solution": "<p>Paris is the capital and most populous city of France.</p>"
    },
    "available_languages": ["en", "hi"],
    "used_in_tests": 3,
    "created_at": "2025-11-10T10:30:00+00:00",
    "updated_at": "2025-11-13T12:00:00+00:00"
  }
}
```

### Endpoint: Update Question

**URL:** `PUT /api/v2/tutor/questions/{id}`

**Description:** Update question text, options, correct answer, and solution. Teachers can only edit their own questions.

**Authentication:** Required (Teacher role)

**Validation Rules:**
- `question`: String, min 10 characters (optional)
- `question_type`: One of: mcq, subjective, true_false (optional)
- `option_a`, `option_b`: Required if question_type is mcq
- `option_c`, `option_d`: Optional for mcq
- `correct_answer`: Required if question_type is mcq, must be A, B, C, or D
- `solution`: String (optional)
- `marks`: Number, min 1, max 100 (optional)
- `time`: Integer, min 30 seconds, max 3600 seconds (optional)

### cURL Examples

#### Update Question Text and Options
```bash
curl --location --request PUT 'http://127.0.0.1:8000/api/v2/tutor/questions/123' \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data '{
  "question": "<p>What is the capital city of France?</p>",
  "option_a": "<p>Paris</p>",
  "option_b": "<p>London</p>",
  "option_c": "<p>Berlin</p>",
  "option_d": "<p>Madrid</p>",
  "correct_answer": "A",
  "solution": "<p>Paris is the capital and largest city of France, located on the River Seine.</p>",
  "marks": 2,
  "time": 90
}'
```

#### Update Only Marks and Time
```bash
curl --location --request PUT 'http://127.0.0.1:8000/api/v2/tutor/questions/123' \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data '{
  "marks": 3,
  "time": 120
}'
```

### Response Example
```json
{
  "status": true,
  "message": "Question updated successfully",
  "data": {
    "id": 123,
    "question": "<p>What is the capital city of France?</p>",
    "question_type": "mcq",
    "marks": 2,
    "time": 90,
    "category_id": "23",
    "translation": {
      "question_text": "<p>What is the capital city of France?</p>",
      "option_a": "<p>Paris</p>",
      "option_b": "<p>London</p>",
      "option_c": "<p>Berlin</p>",
      "option_d": "<p>Madrid</p>",
      "solution": "<p>Paris is the capital and largest city of France, located on the River Seine.</p>"
    },
    "updated_at": "2025-11-13T12:30:00+00:00"
  }
}
```

### Error Responses

#### Validation Error
```json
{
  "status": false,
  "message": "Validation failed",
  "errors": {
    "question": ["Question text must be at least 10 characters"],
    "correct_answer": ["Correct answer must be one of the provided options"]
  }
}
```

#### Unauthorized (Not Question Owner)
```json
{
  "status": false,
  "message": "Forbidden. You can only edit your own questions.",
  "error_code": "FORBIDDEN"
}
```

---

## Day 4: Soft Deletes for Questions

### Endpoint: Delete Question (Soft Delete)

**URL:** `DELETE /api/v2/tutor/questions/{id}`

**Description:** Soft delete a question. Prevents deletion if the question is used in any active test series.

**Authentication:** Required (Teacher role)

**Query Parameters:**
- `force` (optional, boolean): Force delete even if used in tests (admin only)

### cURL Examples

#### Normal Soft Delete
```bash
curl --location --request DELETE 'http://127.0.0.1:8000/api/v2/tutor/questions/123' \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
--header 'Accept: application/json'
```

#### Force Delete (Admin)
```bash
curl --location --request DELETE 'http://127.0.0.1:8000/api/v2/tutor/questions/123?force=true' \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
--header 'Accept: application/json'
```

### Response Examples

#### Success
```json
{
  "status": true,
  "message": "Question deleted successfully",
  "data": {
    "id": 123,
    "deleted_at": "2025-11-13T12:45:00+00:00"
  }
}
```

#### Error - Question in Use
```json
{
  "status": false,
  "message": "Cannot delete question. It is currently used in 3 active test series.",
  "error_code": "QUESTION_IN_USE",
  "data": {
    "active_test_series_count": 3,
    "suggestion": "Please remove this question from active test series before deleting, or contact admin for force deletion."
  }
}
```

### Endpoint: Restore Question

**URL:** `POST /api/v2/tutor/questions/{id}/restore`

**Description:** Restore a previously soft-deleted question.

**Authentication:** Required (Teacher role)

### cURL Example
```bash
curl --location --request POST 'http://127.0.0.1:8000/api/v2/tutor/questions/123/restore' \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
--header 'Accept: application/json'
```

### Response Example
```json
{
  "status": true,
  "message": "Question restored successfully",
  "data": {
    "id": 123,
    "restored_at": "2025-11-13T13:00:00+00:00"
  }
}
```

---

## Day 5: Question Audit Trail

### Endpoint: Get Question History

**URL:** `GET /api/v2/tutor/questions/{id}/history`

**Description:** Get the audit trail for a question, showing the last 20 changes (or specified limit) with user details.

**Authentication:** Required (Teacher role)

**Query Parameters:**
- `limit` (optional, integer): Number of records to retrieve (default: 20, max: 100)

### cURL Examples

#### Get Last 20 Changes
```bash
curl --location 'http://127.0.0.1:8000/api/v2/tutor/questions/123/history' \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
--header 'Accept: application/json'
```

#### Get Last 50 Changes
```bash
curl --location 'http://127.0.0.1:8000/api/v2/tutor/questions/123/history?limit=50' \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
--header 'Accept: application/json'
```

### Response Example
```json
{
  "status": true,
  "message": "Question history retrieved successfully",
  "data": {
    "question_id": 123,
    "question": {
      "id": 123,
      "question": "<p>What is the capital of France?</p>",
      "question_type": "mcq",
      "is_deleted": false
    },
    "total_changes": 5,
    "showing": 20,
    "history": [
      {
        "id": 45,
        "action": "updated",
        "action_description": "Question was updated",
        "changes": {
          "marks": {
            "old": 1,
            "new": 2
          },
          "time": {
            "old": 60,
            "new": 90
          }
        },
        "user": {
          "id": 5,
          "name": "John Doe",
          "email": "john@example.com"
        },
        "ip_address": "192.168.1.100",
        "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
        "performed_at": "2025-11-13T12:30:00+00:00"
      },
      {
        "id": 44,
        "action": "created",
        "action_description": "Question was created",
        "changes": {
          "question": "<p>What is the capital of France?</p>",
          "question_type": "mcq",
          "marks": 1,
          "time": 60
        },
        "user": {
          "id": 5,
          "name": "John Doe",
          "email": "john@example.com"
        },
        "ip_address": "192.168.1.100",
        "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
        "performed_at": "2025-11-10T10:30:00+00:00"
      }
    ]
  }
}
```

---

## Database Migrations

### Migration 1: Add Soft Deletes to Questions Table

**File:** `database/migrations/2025_11_13_120001_add_soft_deletes_to_questions_table.php`

```bash
# Run migration
php artisan migrate

# Rollback migration
php artisan migrate:rollback --step=1
```

**Schema Changes:**
- Adds `deleted_at` column (timestamp, nullable) to `questions` table

### Migration 2: Create Question Audit Logs Table

**File:** `database/migrations/2025_11_13_120002_create_question_audit_logs_table.php`

```bash
# Run migration
php artisan migrate

# Rollback migration
php artisan migrate:rollback --step=1
```

**Schema:**
```sql
CREATE TABLE question_audit_logs (
    id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
    question_id BIGINT UNSIGNED,
    user_id BIGINT UNSIGNED,
    action ENUM('created', 'updated', 'deleted', 'restored'),
    old_values JSON,
    new_values JSON,
    ip_address VARCHAR(45),
    user_agent TEXT,
    created_at TIMESTAMP,
    updated_at TIMESTAMP,
    FOREIGN KEY (question_id) REFERENCES questions(id) ON DELETE CASCADE,
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
    INDEX idx_question_created (question_id, created_at),
    INDEX idx_user (user_id),
    INDEX idx_action (action)
);
```

---

## Testing Guide

### Prerequisites
1. Valid teacher authentication token
2. At least one class, subject, and topic in the database
3. At least one question created by the authenticated teacher

### Test Sequence

#### 1. Test Question Hierarchy
```bash
# Get full hierarchy
curl --location 'http://127.0.0.1:8000/api/v2/tutor/question-bank/hierarchy' \
--header 'Authorization: Bearer YOUR_TOKEN' \
--header 'Accept: application/json'

# Expected: Full class → subject → topic hierarchy with question counts
```

#### 2. Test Question Retrieval
```bash
# Get question details
curl --location 'http://127.0.0.1:8000/api/v2/tutor/questions/1' \
--header 'Authorization: Bearer YOUR_TOKEN' \
--header 'Accept: application/json'

# Expected: Full question details with translations
```

#### 3. Test Question Update
```bash
# Update question
curl --location --request PUT 'http://127.0.0.1:8000/api/v2/tutor/questions/1' \
--header 'Authorization: Bearer YOUR_TOKEN' \
--header 'Content-Type: application/json' \
--data '{
  "question": "<p>Updated question text</p>",
  "marks": 5,
  "time": 120
}'

# Expected: Updated question data
# Side effect: Audit log entry created automatically
```

#### 4. Test Question History
```bash
# Get question history
curl --location 'http://127.0.0.1:8000/api/v2/tutor/questions/1/history' \
--header 'Authorization: Bearer YOUR_TOKEN' \
--header 'Accept: application/json'

# Expected: List of all changes with user details
```

#### 5. Test Soft Delete
```bash
# Delete question
curl --location --request DELETE 'http://127.0.0.1:8000/api/v2/tutor/questions/1' \
--header 'Authorization: Bearer YOUR_TOKEN' \
--header 'Accept: application/json'

# Expected: Success if not used in active tests
# Side effect: Audit log entry created
```

#### 6. Test Restore
```bash
# Restore question
curl --location --request POST 'http://127.0.0.1:8000/api/v2/tutor/questions/1/restore' \
--header 'Authorization: Bearer YOUR_TOKEN' \
--header 'Accept: application/json'

# Expected: Question restored successfully
# Side effect: Audit log entry created
```

---

## Features Summary

### ✅ Day 1: Question Hierarchy Browsing
- [x] GET endpoint for hierarchical view
- [x] Redis caching (1 hour)
- [x] Optional filtering by class_id and subject_id
- [x] Question counts per topic
- [x] Teacher role authorization
- [x] Cache clearing endpoint

### ✅ Day 2-3: Question Edit/Update
- [x] PUT endpoint for question updates
- [x] FormRequest validation
- [x] CKEditor HTML preservation
- [x] Authorization (teacher owns question)
- [x] GET endpoint to retrieve single question
- [x] Comprehensive validation rules

### ✅ Day 4: Soft Deletes
- [x] Soft deletes migration
- [x] SoftDeletes trait on Question model
- [x] DELETE endpoint with usage checks
- [x] POST restore endpoint
- [x] Prevents deletion if used in active tests
- [x] Force delete option (admin only)

### ✅ Day 5: Audit Trail
- [x] question_audit_logs table migration
- [x] QuestionAuditLog model
- [x] QuestionObserver for automatic logging
- [x] GET history endpoint
- [x] Tracks: created, updated, deleted, restored
- [x] Stores old/new values, user, IP, user agent

---

## API Route Summary

All routes require `auth:sanctum` middleware:

```
GET    /api/v2/tutor/question-bank/hierarchy                  - Get hierarchy
POST   /api/v2/tutor/question-bank/clear-cache               - Clear cache
GET    /api/v2/tutor/questions/{id}                          - Get question
PUT    /api/v2/tutor/questions/{id}                          - Update question
DELETE /api/v2/tutor/questions/{id}                          - Delete question
POST   /api/v2/tutor/questions/{id}/restore                  - Restore question
GET    /api/v2/tutor/questions/{id}/history                  - Get history
```

---

## Files Created/Modified

### New Files Created:
1. `/app/Http/Controllers/Api/V2/QuestionBankController.php`
2. `/app/Http/Requests/UpdateQuestionRequest.php`
3. `/app/Models/QuestionAuditLog.php`
4. `/app/Observers/QuestionObserver.php`
5. `/database/migrations/2025_11_13_120001_add_soft_deletes_to_questions_table.php`
6. `/database/migrations/2025_11_13_120002_create_question_audit_logs_table.php`

### Modified Files:
1. `/routes/api.php` - Added new routes
2. `/app/Models/Question.php` - Added SoftDeletes trait and auditLogs relationship
3. `/app/Providers/AppServiceProvider.php` - Registered QuestionObserver

---

## Notes

1. **Caching:** The hierarchy endpoint uses Redis caching with a 1-hour TTL. Cache is automatically cleared when questions are added/updated/deleted.

2. **Authorization:** All endpoints require teacher authentication. Teachers can only edit/delete their own questions (checked via `added_by` field).

3. **Audit Logging:** The QuestionObserver automatically logs all question changes (create, update, delete, restore) with full details including user, IP address, and user agent.

4. **Soft Deletes:** Questions are soft-deleted by default. Hard deletion is not implemented to maintain referential integrity.

5. **Validation:** The UpdateQuestionRequest provides comprehensive validation for all question fields, including MCQ-specific validation.

6. **HTML Preservation:** All question text and options support CKEditor HTML formatting, which is preserved during updates.

---

## Support

For issues or questions, please refer to the main project documentation or contact the development team.
