301 lines
8.2 KiB
Markdown
301 lines
8.2 KiB
Markdown
# Learning Tree + Sequential Access Integration (Admin Panel)
|
|
|
|
Complete backend-compatible documentation for the changes implemented today:
|
|
|
|
- flexible drag-and-drop reorder for learning tree entities
|
|
- sub-course level/sub-level model
|
|
- sub-course entry assessment model
|
|
- learner sequential unlock rules for videos and practices
|
|
|
|
---
|
|
|
|
## 1) What Changed Today
|
|
|
|
### 1.1 Reorder + Route/RBAC hardening
|
|
|
|
- Reorder endpoints are active and route-safe (static `/reorder` routes registered before dynamic `/:id` routes).
|
|
- Reorder permissions are now seeded in RBAC and included in default `ADMIN` permissions:
|
|
- `course_categories.reorder`
|
|
- `courses.reorder`
|
|
- `subcourses.reorder`
|
|
- `videos.reorder`
|
|
- `practices.reorder`
|
|
|
|
### 1.2 Sub-course academic structure
|
|
|
|
- Added `sub_courses.sub_level` with enforced mapping:
|
|
- `BEGINNER` -> `A1`, `A2`, `A3`
|
|
- `INTERMEDIATE` -> `B1`, `B2`, `B3`
|
|
- `ADVANCED` -> `C1`, `C2`, `C3`
|
|
|
|
### 1.3 Entry assessment per sub-course
|
|
|
|
- Each sub-course has its own `INITIAL_ASSESSMENT` question set (`owner_type=SUB_COURSE`).
|
|
- Backfill creates missing sets for existing sub-courses.
|
|
- Trigger auto-creates entry assessment for newly created sub-courses.
|
|
- Existing default standalone initial-assessment questions are cloned into sub-course entry sets when empty.
|
|
|
|
### 1.4 Learner sequential unlock (videos + practices)
|
|
|
|
- Videos: learner cannot access higher `display_order` videos before completing earlier ones.
|
|
- Practices: learner cannot access higher `display_order` practices before completing earlier ones.
|
|
- Completion is tracked per learner using dedicated progress tables.
|
|
|
|
---
|
|
|
|
## 2) Migrations Added
|
|
|
|
Apply in order:
|
|
|
|
1. `000024_subcourse_entry_assessment_and_sub_levels`
|
|
2. `000025_video_sequence_progress`
|
|
3. `000026_practice_sequence_progress`
|
|
|
|
### 2.1 `000024_subcourse_entry_assessment_and_sub_levels`
|
|
|
|
- adds `sub_courses.sub_level`
|
|
- adds level/sub-level check constraint
|
|
- adds `idx_sub_courses_level_sub_level`
|
|
- enforces one active sub-course entry assessment set (unique index on `question_sets`)
|
|
- backfills missing sub-course entry assessment sets
|
|
- adds trigger for automatic entry assessment creation
|
|
|
|
### 2.2 `000025_video_sequence_progress`
|
|
|
|
- creates `user_sub_course_video_progress`
|
|
- tracks learner completion by `user_id + video_id`
|
|
|
|
### 2.3 `000026_practice_sequence_progress`
|
|
|
|
- creates `user_practice_progress`
|
|
- tracks learner completion by `user_id + question_set_id` (practice set)
|
|
|
|
---
|
|
|
|
## 3) Required Permissions
|
|
|
|
### 3.1 Admin panel (read + reorder + content management)
|
|
|
|
- `learning_tree.get`
|
|
- `course_categories.reorder`
|
|
- `courses.reorder`
|
|
- `subcourses.reorder`
|
|
- `videos.reorder`
|
|
- `practices.reorder`
|
|
- `question_sets.list_by_owner` (entry-assessment fetch by sub-course)
|
|
|
|
### 3.2 Learner runtime (sequential flow)
|
|
|
|
- `videos.get`
|
|
- `progress.update` (for completion endpoints)
|
|
- `question_sets.get`
|
|
- `question_set_items.list`
|
|
|
|
---
|
|
|
|
## 4) Reorder APIs (Admin)
|
|
|
|
All reorder APIs expect:
|
|
|
|
```json
|
|
{
|
|
"items": [
|
|
{ "id": 12, "position": 0 },
|
|
{ "id": 7, "position": 1 }
|
|
]
|
|
}
|
|
```
|
|
|
|
- `id`: entity ID
|
|
- `position`: target 0-based `display_order`
|
|
- send the full sibling list in the target order
|
|
|
|
| Method | Endpoint | Effect |
|
|
|---|---|---|
|
|
| `PUT` | `/api/v1/course-management/categories/reorder` | updates `course_categories.display_order` |
|
|
| `PUT` | `/api/v1/course-management/courses/reorder` | updates `courses.display_order` |
|
|
| `PUT` | `/api/v1/course-management/sub-courses/reorder` | updates `sub_courses.display_order` |
|
|
| `PUT` | `/api/v1/course-management/videos/reorder` | updates `sub_course_videos.display_order` |
|
|
| `PUT` | `/api/v1/course-management/practices/reorder` | updates `question_sets.display_order` (practice sets) |
|
|
|
|
Common 400 causes:
|
|
- invalid body shape
|
|
- empty `items`
|
|
|
|
---
|
|
|
|
## 5) Data Fetch APIs for Admin UI
|
|
|
|
| Method | Endpoint | Purpose |
|
|
|---|---|---|
|
|
| `GET` | `/api/v1/course-management/learning-tree` | high-level tree |
|
|
| `GET` | `/api/v1/course-management/courses/{courseId}/learning-path` | detailed nested structure |
|
|
| `GET` | `/api/v1/question-sets/by-owner?owner_type=SUB_COURSE&owner_id={subCourseId}` | sets under a sub-course |
|
|
| `GET` | `/api/v1/question-sets/sub-courses/{subCourseId}/entry-assessment` | entry assessment set for sub-course |
|
|
|
|
---
|
|
|
|
## 6) Sub-course Create/Update Contract (Admin)
|
|
|
|
### 6.1 Create sub-course
|
|
|
|
`POST /api/v1/course-management/sub-courses`
|
|
|
|
Required fields now include:
|
|
|
|
- `course_id`
|
|
- `title`
|
|
- `level` (`BEGINNER|INTERMEDIATE|ADVANCED`)
|
|
- `sub_level` (`A1..C3` mapped by level)
|
|
|
|
Example:
|
|
|
|
```json
|
|
{
|
|
"course_id": 1,
|
|
"title": "Speaking Foundations",
|
|
"level": "BEGINNER",
|
|
"sub_level": "A2",
|
|
"display_order": 1
|
|
}
|
|
```
|
|
|
|
### 6.2 Update sub-course
|
|
|
|
`PATCH /api/v1/course-management/sub-courses/{id}`
|
|
|
|
If `level` or `sub_level` is changed, backend validates the pair.
|
|
|
|
---
|
|
|
|
## 7) Entry Assessment Model (Sub-course)
|
|
|
|
Each sub-course has one entry assessment set:
|
|
|
|
- `set_type = INITIAL_ASSESSMENT`
|
|
- `owner_type = SUB_COURSE`
|
|
- `owner_id = {subCourseId}`
|
|
|
|
### Behavior
|
|
|
|
- created automatically for new sub-courses
|
|
- backfilled for existing sub-courses
|
|
- intended to evaluate learner before joining/starting that sub-course
|
|
|
|
---
|
|
|
|
## 8) Learner Sequential Unlock Rules (Runtime, Not Admin Panel)
|
|
|
|
## 8.1 Videos
|
|
|
|
Access endpoint:
|
|
|
|
- `GET /api/v1/course-management/videos/{id}`
|
|
|
|
Completion endpoint:
|
|
|
|
- `POST /api/v1/progress/videos/{id}/complete`
|
|
|
|
Rule:
|
|
- learner must complete all previous published videos in same sub-course by `display_order` (and `id` tie-breaker)
|
|
|
|
## 8.2 Practices
|
|
|
|
Access endpoints:
|
|
|
|
- `GET /api/v1/question-sets/{id}` (for practice set)
|
|
- `GET /api/v1/question-sets/{setId}/questions`
|
|
|
|
Completion endpoint:
|
|
|
|
- `POST /api/v1/progress/practices/{id}/complete`
|
|
|
|
Rule:
|
|
- applies to sets with:
|
|
- `set_type = PRACTICE`
|
|
- `owner_type = SUB_COURSE`
|
|
- `status = PUBLISHED`
|
|
- learner must complete all previous published practices in same sub-course by `display_order` (and `id` tie-breaker)
|
|
|
|
## 8.3 Role scope
|
|
|
|
- Sequence enforcement currently applies to `STUDENT` role.
|
|
- Admin/instructor/support are not sequence-blocked.
|
|
- Admin panel does not need to call completion endpoints.
|
|
|
|
---
|
|
|
|
## 9) Mid-Progress Reorder Behavior
|
|
|
|
Current behavior (by design):
|
|
|
|
- Access checks always use the **latest `display_order` in DB**.
|
|
- If admin reorders while learner is in progress, next unlock path updates immediately.
|
|
- Completion records are by entity ID, so already completed items remain completed.
|
|
|
|
Implication:
|
|
- learner may be asked to complete a newly moved earlier item before continuing.
|
|
|
|
---
|
|
|
|
## 10) Recommended Frontend Integration Flow
|
|
|
|
### 10.1 Admin panel
|
|
|
|
1. Load learning path/tree.
|
|
2. Render sortable lists per sibling scope.
|
|
3. On drop:
|
|
- optimistic reorder in UI
|
|
- call matching reorder endpoint with full sibling list
|
|
4. Handle `400/401/403/500` and rollback on failure.
|
|
|
|
---
|
|
|
|
## 11) Quick API Examples
|
|
|
|
### Reorder videos
|
|
|
|
```bash
|
|
curl -X PUT "http://localhost:8080/api/v1/course-management/videos/reorder" \
|
|
-H "Authorization: Bearer <TOKEN>" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"items":[{"id":45,"position":0},{"id":42,"position":1},{"id":50,"position":2}]}'
|
|
```
|
|
|
|
### Reorder practices
|
|
|
|
```bash
|
|
curl -X PUT "http://localhost:8080/api/v1/course-management/practices/reorder" \
|
|
-H "Authorization: Bearer <TOKEN>" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"items":[{"id":88,"position":0},{"id":91,"position":1},{"id":95,"position":2}]}'
|
|
```
|
|
|
|
### Get sub-course entry assessment
|
|
|
|
```bash
|
|
curl -X GET "http://localhost:8080/api/v1/question-sets/sub-courses/10/entry-assessment" \
|
|
-H "Authorization: Bearer <TOKEN>"
|
|
```
|
|
|
|
### Runtime-only completion endpoints (learner app, optional reference)
|
|
|
|
```text
|
|
POST /api/v1/progress/videos/{id}/complete
|
|
POST /api/v1/progress/practices/{id}/complete
|
|
```
|
|
|
|
---
|
|
|
|
## 12) Validation and Testing Checklist
|
|
|
|
- [ ] Run migrations 000024, 000025, 000026
|
|
- [ ] Sync RBAC permissions and ensure admin role contains reorder keys
|
|
- [ ] Create/update sub-course with valid `level + sub_level`
|
|
- [ ] Verify auto-created entry assessment for new sub-course
|
|
- [ ] Reorder categories/courses/sub-courses/videos/practices and confirm persistence
|
|
- [ ] Learner cannot access video N+1 before completing N
|
|
- [ ] Learner cannot access practice N+1 before completing N
|
|
- [ ] Reorder during learner progress and confirm latest-order behavior
|
|
|