# 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 " \ -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 " \ -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 " ``` ### 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