# Group Activity Logging and Enrollment System

This document describes the comprehensive activity logging and enrollment system for group/batch management.

## Table of Contents

- [Overview](#overview)
- [Database Schema](#database-schema)
- [Activity Logging](#activity-logging)
- [Enrollment System](#enrollment-system)
- [API Endpoints](#api-endpoints)
- [Examples](#examples)

---

## Overview

The system provides:

1. **Comprehensive Activity Logging**: Track all actions performed on groups including creation, updates, deletions, student enrollments, test assignments, and enrollment code management.

2. **Student Enrollment System**: Students can enroll in groups using unique enrollment codes with expiration dates.

3. **GroupLogService**: Centralized service for logging and retrieving group activities.

---

## Database Schema

### 1. groups Table (Enhanced)

New columns added:

```sql
enrollment_code VARCHAR(20) UNIQUE   -- Unique 10-character alphanumeric code
expires_at DATETIME                  -- When the enrollment code expires
```

### 2. group_activity_log Table

Stores all group-related activities:

```sql
id BIGINT PRIMARY KEY
group_id BIGINT                      -- Reference to groups table
user_id BIGINT                       -- User affected by the action
student_id BIGINT (nullable)         -- Student ID for student-specific actions
action VARCHAR(50)                   -- Action type (see constants below)
performed_by BIGINT                  -- User who performed the action
metadata JSON                        -- Additional details about the action
created_at TIMESTAMP                 -- When the action occurred
```

### 3. group_users Table

Tracks student enrollments:

```sql
id BIGINT PRIMARY KEY
group_id BIGINT                      -- Reference to groups table
user_id BIGINT                       -- Reference to users table
type TINYINT                         -- 1=Teacher, 2=Student
status ENUM('active', 'inactive', 'withdrawn')
enrolled_at TIMESTAMP                -- When the user was enrolled
```

---

## Activity Logging

### Action Types

The following action types are logged:

| Action Constant | Description |
|----------------|-------------|
| `group_created` | Group was created |
| `group_updated` | Group details were modified |
| `group_deleted` | Group was soft-deleted |
| `student_added` | Student was manually added to group |
| `student_removed` | Student was removed from group |
| `student_updated` | Student enrollment was updated |
| `student_enrolled` | Student self-enrolled using enrollment code |
| `teacher_assigned` | Teacher was assigned to group |
| `teacher_removed` | Teacher was removed from group |
| `test_series_added` | Test series was assigned to group |
| `test_series_removed` | Test series was removed from group |
| `enrollment_code_generated` | Enrollment code was created |
| `enrollment_code_regenerated` | Enrollment code was renewed/extended |

### GroupLogService

Located at: `app/Services/GroupLogService.php`

Key methods:

```php
// Log an action
logAction(int $groupId, string $action, ?array $details, ?int $userId, ?int $studentId)

// Get activity logs for a group
getGroupActivity(int $groupId, int $limit = 50, array $filters = [])

// Get paginated activity logs
getPaginatedGroupActivity(int $groupId, int $perPage = 15, array $filters = [])

// Get recent activity across all groups in a school
getRecentActivity(int $schoolId, int $days = 7, int $limit = 100)

// Get activity statistics
getActivityStatistics(int $groupId, int $days = 30)
```

---

## Enrollment System

### How It Works

1. **Code Generation**: Tutors can generate unique 10-character enrollment codes for their groups
2. **Expiration**: Codes expire after a specified number of days (default: 7 days)
3. **Student Enrollment**: Students use the code to enroll themselves in the group
4. **Validation**: System validates code existence, expiration, and duplicate enrollments
5. **Activity Logging**: All enrollment actions are logged

### Group Model Helper Methods

```php
// Generate a new enrollment code
$group->generateEnrollmentCode(int $daysValid = 7): string

// Check if code is expired
$group->isEnrollmentCodeExpired(): bool

// Check if group has an active enrollment code
$group->hasActiveEnrollmentCode(): bool

// Regenerate or extend enrollment code
$group->regenerateEnrollmentCode(int $daysValid = 7, bool $keepSameCode = false): string
```

---

## API Endpoints

### 1. Get Group Activity Logs

**Endpoint**: `GET /api/v2/tutor/groups/{id}/activity`

**Description**: Retrieve paginated activity logs for a specific group

**Authentication**: Required (Tutor)

**Query Parameters**:
- `per_page` (optional): Items per page (default: 15)
- `page` (optional): Page number (default: 1)
- `action` (optional): Filter by action type
- `date_from` (optional): Filter logs from date (Y-m-d H:i:s)
- `date_to` (optional): Filter logs to date (Y-m-d H:i:s)
- `performed_by` (optional): Filter by user ID who performed action

**Response**: See [Example 1](#example-1-get-group-activity-logs)

---

### 2. Regenerate Enrollment Code

**Endpoint**: `POST /api/v2/tutor/groups/{id}/regenerate-code`

**Description**: Generate or regenerate an enrollment code for a group

**Authentication**: Required (Tutor)

**Request Body**:
```json
{
  "days_valid": 7,           // Optional, default: 7
  "keep_same_code": false    // Optional, default: false (true = extend expiry only)
}
```

**Response**: See [Example 2](#example-2-regenerate-enrollment-code)

---

### 3. Get Enrollment Status

**Endpoint**: `GET /api/v2/tutor/groups/{id}/enrollment-status`

**Description**: Get enrollment code and statistics for a group

**Authentication**: Required (Tutor)

**Response**: See [Example 3](#example-3-get-enrollment-status)

---

### 4. Student Enrollment

**Endpoint**: `POST /api/v2/student/enroll`

**Description**: Enroll in a group using an enrollment code

**Authentication**: Required (Student)

**Request Body**:
```json
{
  "enrollment_code": "ABC123XYZ9"
}
```

**Response**: See [Example 4](#example-4-student-enrollment)

---

### 5. List Groups (Enhanced)

**Endpoint**: `GET /api/v2/tutor/groups`

**Description**: List all groups (now includes enrollment information)

**Authentication**: Required (Tutor)

**Query Parameters**:
- `per_page` (optional): Items per page (default: 15)
- `page` (optional): Page number (default: 1)

**Response**: See [Example 5](#example-5-list-groups-with-enrollment-info)

---

## Examples

### Example 1: Get Group Activity Logs

**Request**:
```bash
curl -X GET "http://127.0.0.1:8000/api/v2/tutor/groups/1/activity?per_page=10&action=student_enrolled" \
  -H "Authorization: Bearer YOUR_TOKEN_HERE" \
  -H "Accept: application/json"
```

**Response**:
```json
{
  "status": true,
  "message": "Group activity retrieved successfully",
  "data": [
    {
      "id": 45,
      "group_id": 1,
      "group_name": "Mathematics Grade 10A",
      "action": "student_enrolled",
      "action_display": "Student Enrolled",
      "performed_by": {
        "id": 123,
        "name": "John Doe",
        "email": "john@example.com"
      },
      "subject": {
        "id": 123,
        "name": "John Doe",
        "email": "john@example.com"
      },
      "student": {
        "id": 123,
        "name": "John Doe",
        "email": "john@example.com"
      },
      "metadata": {
        "enrollment_type": "new",
        "enrollment_code": "ABC123XYZ9"
      },
      "timestamp": "2025-11-13T10:30:00Z",
      "timestamp_human": "2 hours ago"
    },
    {
      "id": 44,
      "group_id": 1,
      "group_name": "Mathematics Grade 10A",
      "action": "enrollment_code_generated",
      "action_display": "Enrollment Code Generated",
      "performed_by": {
        "id": 5,
        "name": "Teacher Smith",
        "email": "teacher@example.com"
      },
      "subject": {
        "id": 5,
        "name": "Teacher Smith",
        "email": "teacher@example.com"
      },
      "student": null,
      "metadata": {
        "new_code": "ABC123XYZ9",
        "new_expiry": "2025-11-20 10:00:00",
        "days_valid": 7
      },
      "timestamp": "2025-11-13T10:00:00Z",
      "timestamp_human": "3 hours ago"
    }
  ],
  "pagination": {
    "current_page": 1,
    "last_page": 3,
    "per_page": 10,
    "total": 25
  }
}
```

---

### Example 2: Regenerate Enrollment Code

**Request**:
```bash
curl -X POST "http://127.0.0.1:8000/api/v2/tutor/groups/1/regenerate-code" \
  -H "Authorization: Bearer YOUR_TOKEN_HERE" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "days_valid": 14,
    "keep_same_code": false
  }'
```

**Response**:
```json
{
  "status": true,
  "message": "Enrollment code regenerated successfully",
  "data": {
    "enrollment_code": "XYZ789ABCD",
    "expires_at": "2025-11-27 10:30:00",
    "expires_at_human": "in 14 days"
  }
}
```

**Example (Extend Existing Code)**:
```bash
curl -X POST "http://127.0.0.1:8000/api/v2/tutor/groups/1/regenerate-code" \
  -H "Authorization: Bearer YOUR_TOKEN_HERE" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "days_valid": 7,
    "keep_same_code": true
  }'
```

---

### Example 3: Get Enrollment Status

**Request**:
```bash
curl -X GET "http://127.0.0.1:8000/api/v2/tutor/groups/1/enrollment-status" \
  -H "Authorization: Bearer YOUR_TOKEN_HERE" \
  -H "Accept: application/json"
```

**Response**:
```json
{
  "status": true,
  "message": "Enrollment status retrieved successfully",
  "data": {
    "enrollment_code": "ABC123XYZ9",
    "expires_at": "2025-11-20 10:00:00",
    "expires_at_human": "in 7 days",
    "is_expired": false,
    "is_active": true,
    "enrolled_count": 25,
    "group_name": "Mathematics Grade 10A"
  }
}
```

---

### Example 4: Student Enrollment

**Request**:
```bash
curl -X POST "http://127.0.0.1:8000/api/v2/student/enroll" \
  -H "Authorization: Bearer STUDENT_TOKEN_HERE" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "enrollment_code": "ABC123XYZ9"
  }'
```

**Success Response**:
```json
{
  "status": true,
  "message": "Successfully enrolled in the group",
  "data": {
    "group_id": 1,
    "group_name": "Mathematics Grade 10A",
    "class": "Grade 10",
    "school": "Springfield High School",
    "subjects": [
      {"id": 1, "name": "Mathematics"},
      {"id": 2, "name": "Physics"}
    ],
    "enrolled_at": "2025-11-13 10:30:00"
  }
}
```

**Error Response (Expired Code)**:
```json
{
  "status": false,
  "message": "Enrollment code has expired",
  "error_code": "ENROLLMENT_CODE_EXPIRED",
  "data": {
    "expired_at": "2025-11-10 10:00:00",
    "expired_at_human": "3 days ago"
  }
}
```

**Error Response (Already Enrolled)**:
```json
{
  "status": false,
  "message": "You are already enrolled in this group",
  "error_code": "ALREADY_ENROLLED",
  "data": {
    "group_name": "Mathematics Grade 10A",
    "enrolled_at": "2025-11-10 09:00:00"
  }
}
```

**Error Response (Invalid Code)**:
```json
{
  "status": false,
  "message": "Invalid enrollment code",
  "error_code": "INVALID_ENROLLMENT_CODE"
}
```

---

### Example 5: List Groups with Enrollment Info

**Request**:
```bash
curl -X GET "http://127.0.0.1:8000/api/v2/tutor/groups?per_page=5" \
  -H "Authorization: Bearer YOUR_TOKEN_HERE" \
  -H "Accept: application/json"
```

**Response**:
```json
{
  "status": true,
  "message": "Groups retrieved successfully",
  "data": [
    {
      "id": 1,
      "name": "Mathematics Grade 10A",
      "school_id": 5,
      "class_id": 10,
      "subject_ids": [1, 2],
      "status": true,
      "created_at": "2025-11-01T10:00:00Z",
      "updated_at": "2025-11-13T10:00:00Z",
      "student_count": 25,
      "test_count": 5,
      "class": {
        "id": 10,
        "name": "Grade 10"
      },
      "school": {
        "id": 5,
        "school_name": "Springfield High School"
      },
      "subjects": [
        {"id": 1, "name": "Mathematics"},
        {"id": 2, "name": "Physics"}
      ],
      "enrollment_info": {
        "enrollment_code": "ABC123XYZ9",
        "expires_at": "2025-11-20 10:00:00",
        "is_expired": false,
        "is_active": true,
        "expires_at_human": "in 7 days"
      }
    }
  ],
  "pagination": {
    "current_page": 1,
    "last_page": 2,
    "per_page": 5,
    "total": 8
  }
}
```

---

## Activity Log Format Examples

### Group Created
```json
{
  "action": "group_created",
  "metadata": {
    "group_name": "Mathematics Grade 10A",
    "school_id": 5,
    "class_id": 10,
    "subject_ids": [1, 2]
  }
}
```

### Group Updated
```json
{
  "action": "group_updated",
  "metadata": {
    "changes": {
      "name": {
        "old": "Math Grade 10",
        "new": "Mathematics Grade 10A"
      },
      "subject_ids": {
        "old": [1],
        "new": [1, 2]
      }
    },
    "updated_at": "2025-11-13 10:30:00"
  }
}
```

### Group Deleted
```json
{
  "action": "group_deleted",
  "metadata": {
    "group_name": "Mathematics Grade 10A",
    "school_id": 5,
    "class_id": 10,
    "deleted_at": "2025-11-13 10:30:00"
  }
}
```

### Student Enrolled
```json
{
  "action": "student_enrolled",
  "metadata": {
    "enrollment_type": "new",
    "enrollment_code": "ABC123XYZ9"
  }
}
```

### Enrollment Code Generated
```json
{
  "action": "enrollment_code_generated",
  "metadata": {
    "new_code": "ABC123XYZ9",
    "new_expiry": "2025-11-20 10:00:00",
    "days_valid": 7
  }
}
```

### Enrollment Code Regenerated
```json
{
  "action": "enrollment_code_regenerated",
  "metadata": {
    "old_code": "ABC123XYZ9",
    "new_code": "XYZ789ABCD",
    "old_expiry": "2025-11-20 10:00:00",
    "new_expiry": "2025-11-27 10:00:00",
    "days_valid": 14,
    "kept_same_code": false
  }
}
```

### Test Series Added
```json
{
  "action": "test_series_added",
  "metadata": {
    "test_series_id": 42,
    "test_series_name": "Mid-term Exam 2025"
  }
}
```

---

## Security Considerations

1. **School Ownership**: All tutor endpoints verify that the group belongs to the tutor's school
2. **Role Validation**: Student enrollment endpoint validates user has student role (role_id = 4)
3. **Code Expiration**: Expired codes are automatically rejected during enrollment
4. **Duplicate Prevention**: System prevents duplicate enrollments
5. **Activity Audit**: All actions are logged with performer ID for accountability

---

## Implementation Notes

### Files Modified/Created

**Migrations**:
- `2025_11_13_000002_add_enrollment_code_and_expires_at_to_groups_table.php`

**Models**:
- `app/Models/Group.php` (enhanced with enrollment methods)
- `app/Models/GroupActivityLog.php` (added new action constants)

**Services**:
- `app/Services/GroupLogService.php` (new)

**Controllers**:
- `app/Http/Controllers/Api/V2/GroupController.php` (enhanced)
- `app/Http/Controllers/Api/V2/StudentEnrollmentController.php` (new)

**Routes**:
- `routes/api.php` (added new endpoints)

---

## Future Enhancements

1. **Bulk Operations**: Add bulk student enrollment via CSV
2. **Email Notifications**: Send enrollment code to students via email
3. **Code Templates**: Allow custom code formats
4. **Usage Statistics**: Track enrollment code usage analytics
5. **Automatic Expiry**: Scheduled job to clean expired codes
6. **Enrollment Limits**: Set maximum student capacity per group

---

## Support

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