From 4383db7fa133dee677a6a4570ee780ba02991405 Mon Sep 17 00:00:00 2001 From: devops Date: Mon, 6 Apr 2026 12:57:52 +0400 Subject: [PATCH] docs: update all SRS documents to reflect implemented state - ENCOACH_UNIFIED_SRS.md v2.0: updated header, added 8 new Part VIII-B sections (student leave, fees, lessons, gradebook, student progress, library, activities, facilities), extended permissions with roles CRUD and authority matrix, updated tech specs (93 pages, ~377 API routes, 41 modules), added implementation traceability to all sections - ENCOACH_ODOO19_BACKEND_SRS.md v3.0: updated status to implemented, added beyond-SRS features section, updated module count to 41, endpoint count to ~377 - ODOO_DEVELOPER_HANDOFF.md: rewritten with current repo references and implementation status - ENCOACH_SYSTEM_FEATURES_GUIDE.md: added system features guide - Superseded notices added to ODOO_BACKEND_SRS_v3.md, ODOO_MIGRATION_SRS_v2.md, ODOO_MIGRATION_SRS.md, ODOO_MIGRATION_FRONTEND_SRS.md, MATH_IT_ADAPTIVE_LEARNING_SRS.md Made-with: Cursor --- docs/ENCOACH_ODOO19_BACKEND_SRS.md | 344 +++- docs/ENCOACH_SYSTEM_FEATURES_GUIDE.md | 308 ++++ docs/ENCOACH_UNIFIED_SRS.md | 1058 +++++++++-- docs/MATH_IT_ADAPTIVE_LEARNING_SRS.md | 4 +- docs/ODOO_BACKEND_SRS_v3.md | 4 +- docs/ODOO_DEVELOPER_HANDOFF.md | 100 ++ docs/ODOO_MIGRATION_FRONTEND_SRS.md | 910 ++++++++++ docs/ODOO_MIGRATION_SRS.md | 2337 +++++++++++++++++++++++++ docs/ODOO_MIGRATION_SRS_v2.md | 4 +- 9 files changed, 4841 insertions(+), 228 deletions(-) create mode 100644 docs/ENCOACH_SYSTEM_FEATURES_GUIDE.md create mode 100644 docs/ODOO_DEVELOPER_HANDOFF.md create mode 100644 docs/ODOO_MIGRATION_FRONTEND_SRS.md create mode 100644 docs/ODOO_MIGRATION_SRS.md diff --git a/docs/ENCOACH_ODOO19_BACKEND_SRS.md b/docs/ENCOACH_ODOO19_BACKEND_SRS.md index 84d0ba3..f93faaa 100644 --- a/docs/ENCOACH_ODOO19_BACKEND_SRS.md +++ b/docs/ENCOACH_ODOO19_BACKEND_SRS.md @@ -1,9 +1,26 @@ # EnCoach Platform — Odoo 19 Backend SRS -**Version:** 2.0 -**Date:** March 2026 -**Status:** Definitive -**Purpose:** Complete backend specification for an Odoo 19 developer to build all required modules, models, and REST API endpoints for the EnCoach Adaptive Learning Platform. Includes courseware, communication, notification, FAQ, enhanced approval workflows, plagiarism detection, and official exam access modes. +**Version:** 3.0 +**Date:** March 11, 2026 +**Status:** Implemented — Staging Verified +**Supersedes:** `ODOO_BACKEND_SRS_v3.md`, `ODOO_MIGRATION_SRS_v2.md`, `ODOO_MIGRATION_SRS.md` +**Frontend Reference:** `ENCOACH_UNIFIED_SRS.md` (v2.0) +**Purpose:** Complete backend specification for the EnCoach Adaptive Learning Platform on Odoo 19. All modules, models, and REST API endpoints have been implemented and deployed to staging. + +### Implementation Status + +| Artifact | Location | +|----------|----------| +| **Backend Repository** | `https://git.albousalh.com/devops/encoach_backend_new_v2.git` (branch: `main`) | +| **Frontend Repository** | `https://git.albousalh.com/devops/encoach_frontend_new_v2.git` (branch: `main`) | +| **Staging Backend (Odoo 19)** | `http://5.189.151.117:8069` | +| **Staging Frontend** | `http://5.189.151.117:3000` | +| **Custom EnCoach Modules** | 27 modules in `new_project/custom_addons/` | +| **OpenEduCat Modules** | 14 community modules in `new_project/openeducat_erp-19.0/` | +| **Total API Routes** | ~377 REST endpoints across 4 controller packages | +| **Deployment** | Docker Compose (Odoo 19 + PostgreSQL 16) | + +**Note:** The developer implemented all features in this SRS plus additional OpenEduCat Enterprise features documented in Section 34 (Beyond-SRS Features). --- @@ -42,6 +59,7 @@ 31. [Official Exam Access](#31-official-exam-access) 32. [Non-Functional Requirements](#32-non-functional-requirements) 33. [Implementation Priority](#33-implementation-priority) +34. [Beyond-SRS Features (Implemented)](#34-beyond-srs-features-implemented) --- @@ -174,7 +192,22 @@ All OpenEduCat models need `to_api_dict()` methods on the `encoach_lms_api` inhe | 34 | `encoach_notification` | Custom | Notification engine, configurable rules, email/in-app delivery, user preferences | | 35 | `encoach_faq` | Custom | FAQ categories and items, role-filtered, searchable | -**Total: 8 OpenEduCat (ported) + 27 custom = 35 modules** +**Original plan: 8 OpenEduCat + 27 custom = 35 modules** + +### 4.2 Additional Modules (Implemented Beyond SRS) + +The developer added 6 more OpenEduCat community modules: + +| # | Module | Type | Description | +|---|--------|------|-------------| +| 36 | `openeducat_fees` | OpenEduCat (port v19) | Fee plans, student fees, fee terms | +| 37 | `openeducat_library` | OpenEduCat (port v19) | Media catalog, movements, library cards | +| 38 | `openeducat_activity` | OpenEduCat (port v19) | Student activities, activity types | +| 39 | `openeducat_parent` | OpenEduCat (port v19) | Parent-student relationships | +| 40 | `openeducat_erp` | OpenEduCat (port v19) | ERP connector meta-module | +| 41 | `theme_web_openeducat` | OpenEduCat (port v19) | Web theme | + +**Deployed total: 14 OpenEduCat + 27 custom = 41 modules** --- @@ -1621,78 +1654,245 @@ Add to `encoach.exam`: --- -## 33. Implementation Priority +## 33. Implementation Status -| Priority | Modules | Rationale | -|----------|---------|-----------| -| **P0** | `encoach_core`, `encoach_api` (auth, users, entities, permissions) | Foundation — blocks everything | -| **P0** | `openeducat_core` (port to v19), `encoach_lms_api` (courses, batches, basic serialization) | LMS foundation | -| **P1** | `encoach_taxonomy`, `encoach_adaptive`, `encoach_adaptive_api`, `encoach_adaptive_ai` | Core adaptive learning loop | -| **P1** | `encoach_exam`, `encoach_ai_generation`, `encoach_ai_grading` | Exam engine | -| **P1** | `encoach_resources` | Learning content | -| **P2** | `encoach_courseware` (chapters, materials, progress, AI workbench) | Structured course delivery | -| **P2** | `encoach_communication` (discussions, announcements, messaging) | Collaboration | -| **P2** | `openeducat_timetable`, `openeducat_attendance`, `openeducat_classroom` (port to v19) | LMS timetable/attendance | -| **P2** | `openeducat_admission` (port to v19) + admission endpoints | Enrollment workflow | -| **P2** | Academic years/terms, departments endpoints | Institutional calendar | -| **P2** | `encoach_ai`, `encoach_ai_media` | AI services + media | -| **P2** | `encoach_assignment`, `encoach_classroom` | Assignments + groups | -| **P3** | `encoach_notification` (rules, email delivery, preferences) | User engagement | -| **P3** | Enhanced approval workflows (stages, escalation, bypass) | Governance | -| **P3** | Plagiarism detection (GPTZero integration) | Academic integrity | -| **P3** | Official exam access modes (link, landing, separate login) | Exam security | -| **P3** | Late submission handling, extension requests | Assignment workflow | -| **P3** | `openeducat_exam` (port to v19) + institutional exam endpoints | Institutional assessment | -| **P3** | `openeducat_assignment` (port to v19) + submission endpoints | Homework workflow | -| **P3** | Subject registration endpoints | Student subject selection | -| **P3** | `encoach_training`, analytics endpoints | Training + analytics | -| **P3** | `encoach_sis`, `encoach_branding` | University integration | -| **P4** | `encoach_faq` (categories, items, role-filtered) | User support | -| **P4** | `encoach_subscription` (Stripe, PayPal, Paymob) | Payments | -| **P4** | `encoach_ticket` | Support | -| **P4** | Storage | Operational features | +All modules have been implemented and deployed. The original priority ordering is preserved for reference. + +| Priority | Modules | Status | +|----------|---------|--------| +| **P0** | `encoach_core`, `encoach_api` (auth, users, entities, permissions) | **DONE** | +| **P0** | `openeducat_core` (port to v19), `encoach_lms_api` | **DONE** | +| **P1** | `encoach_taxonomy`, `encoach_adaptive`, `encoach_adaptive_api`, `encoach_adaptive_ai` | **DONE** | +| **P1** | `encoach_exam`, `encoach_ai_generation`, `encoach_ai_grading` | **DONE** | +| **P1** | `encoach_resources` | **DONE** | +| **P2** | `encoach_courseware` (chapters, materials, progress, AI workbench) | **DONE** | +| **P2** | `encoach_communication` (discussions, announcements, messaging) | **DONE** | +| **P2** | `openeducat_timetable`, `openeducat_attendance`, `openeducat_classroom` | **DONE** | +| **P2** | `openeducat_admission` + admission endpoints | **DONE** | +| **P2** | Academic years/terms, departments endpoints | **DONE** | +| **P2** | `encoach_ai`, `encoach_ai_media` | **DONE** | +| **P2** | `encoach_assignment`, `encoach_classroom` | **DONE** | +| **P3** | `encoach_notification` (rules, email delivery, preferences) | **DONE** | +| **P3** | Enhanced approval workflows (stages, escalation, bypass) | **DONE** | +| **P3** | Plagiarism detection (GPTZero integration) | **DONE** | +| **P3** | Official exam access modes (link, landing, separate login) | **DONE** | +| **P3** | Late submission handling, extension requests | **DONE** | +| **P3** | `openeducat_exam` + institutional exam endpoints | **DONE** | +| **P3** | `openeducat_assignment` + submission endpoints | **DONE** | +| **P3** | Subject registration endpoints | **DONE** | +| **P3** | `encoach_training`, analytics endpoints | **DONE** | +| **P3** | `encoach_sis`, `encoach_branding` | **DONE** | +| **P4** | `encoach_faq` (categories, items, role-filtered) | **DONE** | +| **P4** | `encoach_subscription` (Stripe, PayPal, Paymob) | **DONE** | +| **P4** | `encoach_ticket` | **DONE** | +| **P4** | Storage | **DONE** | --- -## Appendix A: Complete Endpoint Summary +## 34. Beyond-SRS Features (Implemented) -Total API endpoints: **280+** +The developer implemented the following features beyond the original SRS scope. These leverage OpenEduCat Enterprise modules and add significant institutional management capabilities. -| Service Area | Endpoint Count | -|-------------|---------------| -| Auth & Users | 10 | -| Entities & Permissions | 9 | -| LMS (Courses, Batches, Timetable, Attendance, Grades) | 16 | -| Academic Years, Terms, Departments | 14 | -| Admissions | 12 | -| Subject Registration | 6 | -| EnCoach Exams (AI) | 15 | -| Institutional Exams | 21 | -| EnCoach Assignments | 7 | -| Course Assignments & Submissions | 11 | -| Classrooms & Groups | 7 | -| Taxonomy | 16 | -| Adaptive Learning | 17 | -| Resources | 7 | -| AI Coaching | 6 | -| AI Evaluation | 4 | -| AI Generation | 2 | -| AI Media | 3 | -| AI Analytics | 6 | -| Training | 3 | -| Statistics | 4 | -| Subscriptions & Payments | 8 + 3 webhooks | -| Tickets | 4 | -| Storage | 2 | -| Approval Workflows (Enhanced) | 11 | -| **Courseware (Chapters + Materials + Workbench)** | **23** | -| **Discussion Boards + Posts** | **9** | -| **Announcements** | **5** | -| **Messaging** | **6** | -| **Notifications + Rules + Preferences** | **10** | -| **FAQ (Categories + Items)** | **8** | -| **Plagiarism Detection** | **3** | -| **Official Exam Access** | **5** | +### 34.1 Student Leave Management + +**Module:** `openeducat_student_leave_enterprise` (via `encoach_lms_api`) +**Controller:** `encoach_lms_api/controllers/student_leave.py` +**Frontend:** `student-leave.service.ts` | `AdminStudentLeave.tsx` + +| Method | Path | Description | +|--------|------|-------------| +| `GET` | `/api/student-leaves` | List leave requests | +| `POST` | `/api/student-leaves` | Create leave request | +| `PATCH` | `/api/student-leaves/{id}` | Update leave request | +| `POST` | `/api/student-leaves/{id}/approve` | Approve request | +| `POST` | `/api/student-leaves/{id}/reject` | Reject request | +| `GET` | `/api/student-leave-types` | List leave types | +| `POST` | `/api/student-leave-types` | Create leave type | + +### 34.2 Fees Management + +**Module:** `openeducat_fees` (via `encoach_lms_api`) +**Controller:** `encoach_lms_api/controllers/fees.py` +**Frontend:** `fees.service.ts` | `AdminFees.tsx` + +| Method | Path | Description | +|--------|------|-------------| +| `GET` | `/api/fees-plans` | List fee plans | +| `GET` | `/api/fees-plans/{id}` | Fee plan detail | +| `GET` | `/api/student-fees` | Student fee details | +| `GET` | `/api/fees-terms` | Fee terms | + +### 34.3 Lessons Management + +**Module:** `openeducat_lesson` (via `encoach_lms_api`) +**Controller:** `encoach_lms_api/controllers/lessons.py` +**Frontend:** `lesson.service.ts` | `AdminLessons.tsx` + +| Method | Path | Description | +|--------|------|-------------| +| `GET` | `/api/lessons` | List lessons | +| `POST` | `/api/lessons` | Create lesson | +| `PATCH` | `/api/lessons/{id}` | Update lesson | +| `DELETE` | `/api/lessons/{id}` | Delete lesson | + +### 34.4 Gradebook and Grading Assignments + +**Module:** `openeducat_grading` (via `encoach_lms_api`) +**Controller:** `encoach_lms_api/controllers/gradebook.py` +**Frontend:** `gradebook.service.ts` | `AdminGradebook.tsx` + +| Method | Path | Description | +|--------|------|-------------| +| `GET` | `/api/gradebooks` | List gradebooks | +| `GET` | `/api/gradebook-lines` | Gradebook lines | +| `GET` | `/api/grading-assignments` | List grading assignments | +| `POST` | `/api/grading-assignments` | Create grading assignment | +| `PATCH` | `/api/grading-assignments/{id}` | Update grading assignment | +| `DELETE` | `/api/grading-assignments/{id}` | Delete grading assignment | + +### 34.5 Student Progress Tracking + +**Module:** `openeducat_student_progress_enterprise` (via `encoach_lms_api`) +**Controller:** `encoach_lms_api/controllers/student_progress.py` +**Frontend:** `student-progress.service.ts` | `AdminStudentProgress.tsx` + +| Method | Path | Description | +|--------|------|-------------| +| `GET` | `/api/student-progress` | List student progression records | + +### 34.6 Library Management + +**Module:** `openeducat_library` (via `encoach_lms_api`) +**Controller:** `encoach_lms_api/controllers/library.py` +**Frontend:** `library.service.ts` | `AdminLibrary.tsx` + +| Method | Path | Description | +|--------|------|-------------| +| `GET` | `/api/library/media` | List media items | +| `POST` | `/api/library/media` | Create media item | +| `DELETE` | `/api/library/media/{id}` | Delete media item | +| `GET` | `/api/library/movements` | List movements | +| `POST` | `/api/library/movements` | Create movement (issue) | +| `PATCH` | `/api/library/movements/{id}` | Update movement | +| `POST` | `/api/library/movements/{id}/return` | Return media | +| `GET` | `/api/library/cards` | List library cards | +| `POST` | `/api/library/cards` | Create library card | + +### 34.7 Activity Management + +**Module:** `openeducat_activity` (via `encoach_lms_api`) +**Controller:** `encoach_lms_api/controllers/activities.py` +**Frontend:** `activity.service.ts` | `AdminActivities.tsx` + +| Method | Path | Description | +|--------|------|-------------| +| `GET` | `/api/activities` | List activities | +| `POST` | `/api/activities` | Create activity | +| `PATCH` | `/api/activities/{id}` | Update activity | +| `DELETE` | `/api/activities/{id}` | Delete activity | +| `GET` | `/api/activity-types` | List activity types | +| `POST` | `/api/activity-types` | Create activity type | +| `DELETE` | `/api/activity-types/{id}` | Delete activity type | + +### 34.8 Facility and Asset Management + +**Module:** `openeducat_facility` (extended via `encoach_lms_api`) +**Controller:** `encoach_lms_api/controllers/facilities.py` +**Frontend:** `facility.service.ts` | `AdminFacilities.tsx` + +| Method | Path | Description | +|--------|------|-------------| +| `GET` | `/api/facilities` | List facilities | +| `POST` | `/api/facilities` | Create facility | +| `PATCH` | `/api/facilities/{id}` | Update facility | +| `DELETE` | `/api/facilities/{id}` | Delete facility | +| `GET` | `/api/assets` | List assets | +| `POST` | `/api/assets` | Create asset | +| `DELETE` | `/api/assets/{id}` | Delete asset | + +### 34.9 Roles CRUD, User Role Assignment, and Authority Matrix + +**Module:** `encoach_core` (extended) +**Controller:** `encoach_api/controllers/roles.py` +**Frontend:** `entities.service.ts` | `RolesPermissions.tsx`, `UserRoles.tsx`, `AuthorityMatrix.tsx` + +| Method | Path | Description | +|--------|------|-------------| +| `GET` | `/api/roles` | List all roles | +| `POST` | `/api/roles` | Create role | +| `GET` | `/api/roles/{id}` | Get role detail | +| `PATCH` | `/api/roles/{id}` | Update role | +| `DELETE` | `/api/roles/{id}` | Delete role | +| `PATCH` | `/api/roles/{id}/permissions` | Update role permissions | +| `GET` | `/api/permissions` | List all permissions | +| `POST` | `/api/permissions` | Create permission | +| `DELETE` | `/api/permissions/{id}` | Delete permission | +| `GET` | `/api/users/with-roles` | List users with roles | +| `GET/PATCH` | `/api/users/{id}/roles` | Get/update user roles | +| `POST` | `/api/users/{id}/roles/toggle` | Toggle role for user | +| `GET` | `/api/authority-matrix` | Get role-permission matrix | +| `POST` | `/api/authority-matrix/toggle` | Toggle a matrix cell | +| `GET` | `/api/user-authority-matrix` | Get user-level authority | + +--- + +## Appendix A: Complete Endpoint Summary (Verified Against Deployment) + +Total API endpoints: **~377** (deployed across 4 controller packages) + +| Controller Package | Route Count | Service Areas | +|-------------------|-------------|---------------| +| `encoach_api` | ~120 | Auth, users, entities, roles, exams, assignments, classrooms, storage, stats, subscriptions, tickets, approvals, training, generation, AI analytics | +| `encoach_lms_api` | ~209 | Courses, students, teachers, batches, timetable, attendance, grades, departments, academic, admissions, subject registration, institutional exams, course assignments, student leave, fees, lessons, gradebook, student progress, library, activities, facilities, notifications, FAQ, courseware, plagiarism, communication, classrooms | +| `encoach_adaptive_api` | ~41 | Taxonomy (subjects, domains, topics), diagnostic, proficiency, learning plans, content, coaching | +| `encoach_resources` | ~7 | Learning resources (CRUD, download, complete, rate) | + +**Breakdown by Service Area:** + +| Service Area | Endpoint Count | Status | +|-------------|---------------|--------| +| Auth & Users | 10 | Deployed | +| Entities & Permissions | 9 | Deployed | +| Roles CRUD & Authority Matrix | 12 | **Deployed (Beyond SRS)** | +| LMS (Courses, Batches, Timetable, Attendance, Grades) | 16 | Deployed | +| Academic Years, Terms, Departments | 14 | Deployed | +| Admissions | 12 | Deployed | +| Subject Registration | 6 | Deployed | +| EnCoach Exams (AI) | 15 | Deployed | +| Institutional Exams | 21 | Deployed | +| EnCoach Assignments | 7 | Deployed | +| Course Assignments & Submissions | 11 | Deployed | +| Classrooms & Groups | 7 | Deployed | +| Taxonomy | 16 | Deployed | +| Adaptive Learning | 17 | Deployed | +| Resources | 7 | Deployed | +| AI Coaching | 6 | Deployed | +| AI Evaluation | 4 | Deployed | +| AI Generation | 2 | Deployed | +| AI Media | 3 | Deployed | +| AI Analytics | 6 | Deployed | +| Training | 3 | Deployed | +| Statistics | 4 | Deployed | +| Subscriptions & Payments | 8 + 3 webhooks | Deployed | +| Tickets | 4 | Deployed | +| Storage | 2 | Deployed | +| Approval Workflows (Enhanced) | 11 | Deployed | +| Courseware (Chapters + Materials + Workbench) | 23 | Deployed | +| Discussion Boards + Posts | 9 | Deployed | +| Announcements | 5 | Deployed | +| Messaging | 6 | Deployed | +| Notifications + Rules + Preferences | 10 | Deployed | +| FAQ (Categories + Items) | 8 | Deployed | +| Plagiarism Detection | 3 | Deployed | +| Official Exam Access | 5 | Deployed | +| Student Leave Management | 7 | **Deployed (Beyond SRS)** | +| Fees Management | 4 | **Deployed (Beyond SRS)** | +| Lessons Management | 4 | **Deployed (Beyond SRS)** | +| Gradebook & Grading | 6 | **Deployed (Beyond SRS)** | +| Student Progress | 1 | **Deployed (Beyond SRS)** | +| Library Management | 9 | **Deployed (Beyond SRS)** | +| Activity Management | 7 | **Deployed (Beyond SRS)** | +| Facility & Asset Management | 7 | **Deployed (Beyond SRS)** | --- @@ -1756,4 +1956,4 @@ res.users ──extends──> encoach.user --- -*This SRS is the definitive backend specification for the EnCoach platform on Odoo 19. It covers all 280+ REST API endpoints expected by the React frontend, 35 Odoo modules (8 OpenEduCat + 27 custom), and all AI service integrations.* +*This SRS is the definitive backend specification for the EnCoach platform on Odoo 19. All ~377 REST API endpoints, 41 Odoo modules (14 OpenEduCat + 27 custom), and all AI service integrations have been implemented and deployed to staging at `http://5.189.151.117:8069`. All previous backend SRS documents (`ODOO_BACKEND_SRS_v3.md`, `ODOO_MIGRATION_SRS_v2.md`, `ODOO_MIGRATION_SRS.md`) are superseded by this document.* diff --git a/docs/ENCOACH_SYSTEM_FEATURES_GUIDE.md b/docs/ENCOACH_SYSTEM_FEATURES_GUIDE.md new file mode 100644 index 0000000..6ebba0b --- /dev/null +++ b/docs/ENCOACH_SYSTEM_FEATURES_GUIDE.md @@ -0,0 +1,308 @@ +# EnCoach Platform -- System Features Guide + +**Version:** 1.0 +**Date:** March 2026 +**Purpose:** Describe every section and feature accessible through the platform navigation, organized by user role. + +--- + +## Part 1: Administrator Panel + +The Administrator Panel is the central management hub for the entire platform. It is accessible to users with roles: Admin, Corporate, Master Corporate, Agent, and Developer. + +--- + +### 1. Overview + +The Overview section provides high-level dashboards that give administrators an at-a-glance view of the entire platform's health and activity. + +| Menu Item | Description | +|-----------|-------------| +| **Admin Dashboard** | The LMS-focused dashboard showing real-time counts of courses, students, teachers, batches, and enrollment status. Displays course capacity charts, student status distribution, and recent activity. | +| **Platform Dashboard** | The original platform dashboard focused on exam and assignment activity. Shows exam creation statistics, assignment completion rates, user activity trends, and entity-level performance summaries. | + +--- + +### 2. LMS + +The LMS (Learning Management System) section is the core of institutional course management. It handles the full lifecycle of courses, students, teachers, and class scheduling. + +| Menu Item | Description | +|-----------|-------------| +| **Courses** | Create, view, and manage courses. Each course has a title, code, description, maximum capacity, status (draft/active/archived), and is linked to a department. Administrators can view enrollment counts and manage course settings. | +| **Students** | Manage student records. Create new students (which automatically creates a portal user account), view student lists with filters, export student data, and manage individual student profiles including their course enrollments. | +| **Teachers** | Manage teacher records. Create teacher profiles with specialization areas, link them to portal user accounts, assign them to courses and batches, and view their teaching schedules. | +| **Batches** | Manage class batches (sections/cohorts). Each batch belongs to a course and has a date range, capacity, and enrolled students. Administrators can view batch details, manage student enrollment per batch, and track batch capacity. | +| **Lessons** | Create and manage individual lessons linked to a course, batch, and subject. Each lesson has a faculty member, date, and duration. Used to organize the day-to-day teaching schedule within a course. | +| **Timetable** | Visual timetable management with a day/time grid. Create, view, and delete teaching sessions. Sessions are linked to courses, batches, subjects, and classrooms with specific day and time slots. | +| **Reports** | LMS-specific reporting dashboards showing course enrollment trends, batch capacity utilization, student status distributions, teacher workload, and overall LMS usage analytics. | + +--- + +### 3. Adaptive Learning + +The Adaptive Learning section manages the AI-powered personalized learning engine. It controls the knowledge structure that drives diagnostic tests, proficiency tracking, and personalized learning plans. + +| Menu Item | Description | +|-----------|-------------| +| **Taxonomy** | Manage the subject knowledge hierarchy: Subjects (e.g., English, Math, IT) contain Domains, which contain Topics, which contain Learning Objectives. This taxonomy drives the adaptive engine -- diagnostic tests assess proficiency at the topic level, and learning plans are generated based on this structure. Administrators can create subjects, add domains/topics manually, or use AI to suggest topic structures. | +| **Resources** | Manage the learning resource library. Upload educational materials (PDFs, videos, links, documents, interactive content) and tag them to specific topics in the taxonomy. Resources go through a review workflow (pending, approved, rejected) and are served to students through their personalized learning plans. Track resource downloads, completion, and ratings. | + +--- + +### 4. Institutional + +The Institutional section handles university-level academic administration -- the calendar, departments, enrollment pipeline, formal exam sessions, grading, and student lifecycle. + +| Menu Item | Description | +|-----------|-------------| +| **Academic Years** | Define academic years with start and end dates. Auto-generate academic terms (semesters/quarters) within each year. Academic years organize all institutional activities -- courses, batches, exams, and grades are all scoped to an academic year. | +| **Departments** | Manage the department hierarchy with parent-child relationships. Departments organize courses and faculty. Each department can have sub-departments, a head of department, and associated courses. | +| **Admissions** | View and process individual student admission applications. Each admission goes through a workflow: submitted, confirmed, admitted, or rejected. Administrators can review application details, update status, and convert admitted applicants into enrolled students. | +| **Admission Register** | Manage admission campaigns/registers. Each register defines an admission period (open/closed), linked course, available seats, and start/end dates. Registers go through a workflow: create, confirm (open for applications), close (stop accepting). | +| **Exam Sessions** | Schedule and manage institutional exam sessions. Each session is linked to a course, batch, and academic term. Sessions go through a workflow: draft, scheduled, in progress, done. Manage exam rooms, attendees, and timing within each session. | +| **Marksheets** | Generate and validate student marksheets (grade reports). Marksheets aggregate student scores across exams within a session, apply grade configurations and result templates, and compute pass/fail status. Supports validation workflow before official release. | +| **Student Leave** | Manage student leave requests. Students submit leave requests with reasons and dates; administrators or teachers can approve or reject them. Tracks leave history per student. | +| **Fees** | View fee plans, fee terms, and individual student fee records. Manage fee structures attached to courses, including installment plans and payment tracking. | +| **Gradebook** | View and manage the institutional grading system. Displays grades per student, per course, and per academic year. Supports grading assignment types, weighted grading, and grade configuration (letter grades, percentage scales). | +| **Student Progress** | Track longitudinal student progress across courses, subjects, and academic terms. Provides a historical view of student performance, showing trends and areas that need attention. | + +--- + +### 5. Academic + +The Academic section manages the AI-powered exam engine -- creating exams, defining grading rubrics, generating content with AI, and managing the approval workflow for publishing exams. + +| Menu Item | Description | +|-----------|-------------| +| **Assignments** | Create and manage exam-linked assignments. Each assignment wraps an exam and assigns it to specific students or classrooms with deadlines. Supports tabs for Active, Planned, Past, and Archived assignments. Includes late submission policies, extension requests, penalty configuration, and reminder settings. | +| **Exams List** | Browse, search, and manage all exams in the system. Filter by subject, module (Reading, Writing, Listening, Speaking), and difficulty. Each exam contains exercises, passages, timer settings, and access controls (public/private). Supports both practice exercises and official exams. | +| **Exam Structures** | Define exam blueprints (templates) that specify the section layout of exams -- how many sections, what type of questions in each, difficulty distribution, and time allocation per section. Structures are reusable across multiple exams. | +| **Rubrics** | Create and manage grading rubrics that define the criteria for evaluating student responses. Rubrics specify scoring dimensions (e.g., Task Achievement, Coherence, Grammar for IELTS writing). Rubric groups organize related rubrics. Used by both human graders and the AI grading engine. | +| **Generation** | The AI exam generation interface. Select a subject, module, and topic; configure difficulty and question types; and let the AI (GPT-4o) generate complete exams with passages, questions, and answer keys. Supports generation from scratch or from existing content. | +| **Approval Workflows** | Manage the approval process for publishing exams and course materials. Configure multi-stage workflows with specific approvers, time limits per stage, auto-escalation rules, and bypass options. Track approval status (pending, approved, rejected, escalated) with comments through each stage. | + +--- + +### 6. Management + +The Management section handles platform-wide user, organization, and infrastructure management. + +| Menu Item | Description | +|-----------|-------------| +| **Users** | Full user management. Create, update, search, filter, and export users. View user details including role, entity, verification status, and activity history. Supports batch user import from spreadsheets. | +| **Entities** | Manage organizations (multi-tenant). Each entity is an institution or company using the platform. Configure entity settings, manage entity-specific roles and permissions, generate invite codes for onboarding, and set per-entity branding (logo, colors). | +| **Classrooms** | Manage virtual and physical classroom groups. Create classrooms with capacity tracking, assign students to classrooms, and use classrooms for assigning exams and assignments to groups of students. | +| **Roles & Permissions** | Create and manage roles within entities. Each role has a name and a set of granular permissions. Administrators can create custom roles, assign/remove permissions from roles, and manage the permission catalog. | +| **Authority Matrix** | A cross-reference visualization of all roles and their permissions. Displayed as an interactive grid where rows are roles and columns are permissions. Administrators can toggle permissions on/off directly from the matrix view. | +| **User Roles** | Assign roles to individual users. View all users with their current role assignments, search and filter, and assign or remove roles. Supports user-level permission overrides beyond their assigned role. | + +--- + +### 7. Reports + +The Reports section provides analytical views of platform performance and student outcomes. + +| Menu Item | Description | +|-----------|-------------| +| **Student Performance** | Detailed performance analytics per student. Shows exam scores, assignment completion rates, proficiency levels across subjects, and trends over time. Supports filtering by entity, course, and date range. | +| **Stats Corporate** | Entity-level statistics for corporate/institutional managers. Shows aggregated data across all students within an entity -- enrollment counts, average scores, completion rates, and comparative performance across courses. | +| **Record** | Historical activity records. Browse past exam sessions, assignment submissions, and user activity logs. Supports searching and filtering by date, user, and activity type. | + +--- + +### 8. Configuration + +The Configuration section manages platform-wide settings for notifications, FAQs, and approval processes. + +| Menu Item | Description | +|-----------|-------------| +| **FAQ Manager** | Create and manage Frequently Asked Questions. Organize FAQs into categories, set target audience per item (student, entity, or both), add rich content including text, images, and video links. FAQs are displayed on a public searchable page with accordion-style expand/collapse. | +| **Notification Rules** | Configure automated notification triggers. Define rules based on event types (assignment due, exam due, chapter unlock, result release), set timing (how many days before the event), frequency (once, daily, custom intervals), and delivery channel (in-app, email, or both). | +| **Approval Config** | Configure the enhanced approval workflow system. Define multi-stage approval templates with specific approvers per stage, maximum days before auto-escalation, notification emails, and bypass permissions. Applied to exam publishing and course material approval. | + +--- + +### 9. Training + +The Training section provides reference materials for language learning support. + +| Menu Item | Description | +|-----------|-------------| +| **Vocabulary** | Browse vocabulary training content. Displays categorized vocabulary lists, definitions, usage examples, and related exercises. Linked to the FAISS-based recommendation engine for contextual suggestions. | +| **Grammar** | Browse grammar training content. Displays grammar rules, examples, common mistakes, and practice exercises organized by topic and difficulty level. | + +--- + +### 10. Support + +The Support section handles financial tracking, user support, and system settings. + +| Menu Item | Description | +|-----------|-------------| +| **Payment Record** | View payment history and transaction records. Shows all subscription payments, amounts, providers (Stripe/PayPal/Paymob), status, and associated packages. Supports filtering by date, user, and payment status. | +| **Tickets** | Manage support tickets. View all tickets submitted by users, assign tickets to support agents, update ticket status (open, in progress, resolved, closed), and communicate with ticket reporters. | +| **Settings** | Platform-wide settings management. Configure system parameters, AI service settings (API keys stored securely), default behaviors, and platform-level preferences. | + +--- + +### 11. Other Admin Pages (Accessible but not in main sidebar) + +| Page | Description | +|------|-------------| +| **Library** | Manage the institutional library. CRUD operations for library media (books, journals, digital resources), track media movements (issue, return), and manage student library cards. | +| **Activities** | Log and track student activities. Define activity types and record student participation in extracurricular or academic activities outside the standard course structure. | +| **Facilities** | Manage institutional facilities and assets. Track rooms, equipment, and other physical resources used for teaching and examinations. | + +--- + +## Part 2: Teacher Panel + +The Teacher Panel provides instructors with tools to manage their courses, create content, track student progress, and communicate with their classes. + +--- + +### 1. Teaching + +The Teaching section is the teacher's primary workspace for delivering courses and managing assignments. + +| Menu Item | Description | +|-----------|-------------| +| **Dashboard** | The teacher's home screen showing an overview of their assigned courses, upcoming assignments, recent student submissions, and quick statistics (number of students, pending grading, upcoming sessions). | +| **Courses** | View and manage assigned courses. From here, teachers can access three key sub-pages per course: **Chapters** (organize course content into sequential chapters with materials, set unlock dates, and control access), **Chapter Detail** (upload and manage materials within a chapter -- PDFs, videos, audio, images, links -- with download permission controls), and **AI Workbench** (generate course content using AI by inputting topic, objectives, and complexity level; review and publish AI-generated chapters, materials, exercises, and rubrics). | +| **Assignments** | Create and manage assignments for classes. Define deadlines, late submission policies, penalty structures, and reminder frequencies. View assignment submissions, check plagiarism reports, grade with AI assistance, and release results. Drill into individual assignments to see per-student submission status and grading. | + +--- + +### 2. Management + +The Management section gives teachers tools to track student attendance and schedules. + +| Menu Item | Description | +|-----------|-------------| +| **Attendance** | Take and manage attendance for classes. Mark students as present, absent, or late for each session. View attendance history and trends per batch. | +| **Students** | View the list of students enrolled in the teacher's courses and batches. Access individual student profiles and performance summaries. | +| **Timetable** | View the teacher's personal teaching schedule in a visual day/time grid format. Shows all assigned sessions across courses and batches. | + +--- + +### 3. Communication + +The Communication section enables teacher-student interaction and class announcements. + +| Menu Item | Description | +|-----------|-------------| +| **Discussions** | View and manage discussion boards for courses. Teachers can enable/disable discussion boards per course or chapter, create discussion threads, reply to student questions, pin important posts, and mark questions as resolved. Supports file attachments. | +| **Announcements** | Create and broadcast announcements to classes. Set priority (normal, important, urgent), target specific courses or batches, optionally send via email in addition to in-app notification. Manage drafts and publish when ready. | + +--- + +### 4. Account + +| Menu Item | Description | +|-----------|-------------| +| **Profile** | View and update personal profile information (name, email, specialization, contact details). | + +--- + +## Part 3: Student Panel + +The Student Panel provides learners with access to their courses, adaptive learning engine, progress tracking, and communication tools. + +--- + +### 1. Learning + +The Learning section is the student's primary workspace for accessing courses and completing assignments. + +| Menu Item | Description | +|-----------|-------------| +| **Dashboard** | The student's home screen showing enrolled subjects, upcoming deadlines (assignments, quizzes, exams), recent announcements, personal progress statistics, and AI study tips. Includes an AI coaching assistant for on-demand help. | +| **My Courses** | Browse all enrolled courses. Each course shows its chapters, completion progress, and available materials. Students can navigate into individual courses to see the chapter structure, access unlocked chapter content, download materials (when permitted by the teacher), and track their progress through the course. | +| **Subject Registration** | Register for available subjects within the current academic term. View available subjects, prerequisites, and capacity. Submit registration requests for subjects the student wants to take. | +| **Assignments** | View all active, upcoming, and past assignments. Submit completed work through the platform, view deadlines and submission status, request deadline extensions (when allowed), track submission history, and receive AI-generated feedback and plagiarism reports. | + +--- + +### 2. Adaptive Learning + +The Adaptive Learning section provides AI-powered personalized education that adapts to each student's level. + +| Menu Item | Description | +|-----------|-------------| +| **My Subjects** | The entry point for the adaptive learning engine. Displays all subjects the student is studying with their overall mastery level. From here, students can: take a **Diagnostic Test** (AI-administered assessment to determine initial proficiency across topics), view their **Proficiency Profile** (detailed breakdown of mastery per topic within a subject), access their **Learning Plan** (AI-generated personalized study path with ordered topics based on proficiency gaps), and study individual **Topics** (AI-curated learning content with practice exercises and mastery quizzes that adapt difficulty based on performance). | + +--- + +### 3. Progress + +The Progress section shows academic performance, attendance, and the overall learning journey. + +| Menu Item | Description | +|-----------|-------------| +| **Grades** | View grades for all courses, assignments, and exams. Shows current marks, feedback from teachers, and detailed score breakdowns by grading criteria. | +| **Attendance** | View personal attendance records across all enrolled courses. Shows attendance percentage, absent dates, and any leave requests with their approval status. | +| **Timetable** | View personal class schedule in a visual day/time grid. Shows all upcoming sessions with course, subject, teacher, and room information. | +| **My Journey** | A longitudinal progress timeline showing the student's overall academic journey. Displays enrolled courses with completion percentages, per-subject proficiency trends, and a recent activity timeline (exams taken, assignments submitted, chapters completed). Provides a holistic view of growth over time. | + +--- + +### 4. Communication + +The Communication section enables students to interact with teachers and classmates. + +| Menu Item | Description | +|-----------|-------------| +| **Discussions** | Participate in course and chapter discussion boards. Create new discussion threads, reply to existing threads (nested replies), ask questions about assignments or course content, and view pinned/resolved posts. Students can see other participants within the same class. | +| **Messages** | Direct messaging between users. View inbox (with read/unread indicators and unread count badge), send messages to teachers or classmates within the same class, attach files, and optionally send an email copy. Includes a sent messages view. | +| **Announcements** | View announcements from teachers and system administrators. Announcements are displayed with priority indicators (urgent, important, normal) and sorted by date. | + +--- + +### 5. Account + +| Menu Item | Description | +|-----------|-------------| +| **Profile** | View and update personal profile information (name, email, contact details, preferences). | + +--- + +## Part 4: Public Pages (No Login Required) + +These pages are accessible without authentication. + +| Page | Description | +|------|-------------| +| **Login** | User authentication with email and password. Redirects to the appropriate dashboard based on user role after successful login. | +| **Register** | New user registration. Supports open registration or invite-code-based registration to join a specific entity with a predefined role. | +| **Forgot Password** | Password recovery via email. Users enter their email to receive a verification link for password reset. | +| **Admission Application** | Public admission form for prospective students. Users can apply to an open admission register without logging in, providing personal details and required documents. They can check application status afterward. | +| **FAQ** | Public Frequently Asked Questions page. Searchable, accordion-style display of FAQ items organized by category. Content is filtered based on the user's role (student or entity) if logged in, showing all items if accessed publicly. | +| **Official Exam Access** | Special exam access pages for official/proctored exams. Supports three modes: (1) token-based link access where students open a unique URL, (2) landing page access with an exam code, and (3) a dedicated exam login screen isolated from the rest of the platform. | + +--- + +## Part 5: AI Features (Embedded Across the Platform) + +AI capabilities are embedded throughout the platform rather than being a standalone section. Here is where AI appears: + +| Feature | Where It Appears | What It Does | +|---------|-----------------|-------------| +| **AI Study Coach** | Student Dashboard | Chat-based coaching assistant that provides hints, concept explanations, writing help, and study tips. | +| **AI Exam Generation** | Admin > Generation, Teacher > AI Workbench | Generates complete exams (passages, questions, answer keys) from subject taxonomy using GPT-4o. | +| **AI Grading** | Admin > Assignments, Teacher > Assignments | Automatically grades writing (rubric-based IELTS band scoring), speaking (transcription + evaluation), math (step evaluation), and IT (code evaluation) using GPT-4o. | +| **AI Course Content** | Teacher > AI Workbench | Generates course outlines, chapter content, exercises, and grading rubrics from high-level requirements. | +| **AI Diagnostics** | Student > My Subjects | Administers adaptive diagnostic tests that adjust question difficulty based on responses to accurately assess proficiency. | +| **AI Learning Plans** | Student > My Subjects | Generates personalized learning plans based on diagnostic results and proficiency gaps. | +| **AI Content Recommendations** | Student > Topic Learning | Suggests additional learning materials based on student performance and learning history using FAISS similarity search. | +| **AI Plagiarism Detection** | Teacher > Assignments, Admin > Assignments | Analyzes submitted text using GPTZero to detect AI-generated content, providing per-sentence analysis and downloadable reports. | +| **AI Search** | Admin Header Bar | Semantic search across the platform using AI. | +| **AI Analytics** | Admin > Reports | Generates narrative reports, identifies content gaps, and provides batch optimization suggestions. | +| **AI Tip Banner** | Student Dashboard | Context-aware training tips selected using FAISS-based recommendation. | +| **Text-to-Speech** | Listening Exams | Converts exam text to natural speech using AWS Polly (11 neural voices). | +| **Speech-to-Text** | Speaking Exams | Transcribes student speaking responses using local Whisper model. | +| **AI Avatar Videos** | Speaking Exams | Generates avatar-based video prompts for speaking exams using ELAI. | + +--- + +*End of System Features Guide* diff --git a/docs/ENCOACH_UNIFIED_SRS.md b/docs/ENCOACH_UNIFIED_SRS.md index ebf819c..c645849 100644 --- a/docs/ENCOACH_UNIFIED_SRS.md +++ b/docs/ENCOACH_UNIFIED_SRS.md @@ -1,11 +1,31 @@ # EnCoach Unified Platform -- Software Requirements Specification -**Document Version:** 1.0 -**Date:** March 24, 2026 -**Status:** Draft -- Architect Review -**Supersedes:** `ielts-ui/SRS-EnCoach.md` (v2.0), `MATH_IT_ADAPTIVE_LEARNING_SRS.md` (v1.0) +**Document Version:** 2.0 +**Date:** March 11, 2026 +**Status:** Implemented -- Staging Verified +**Supersedes:** `ielts-ui/SRS-EnCoach.md` (v2.0), `MATH_IT_ADAPTIVE_LEARNING_SRS.md` (v1.0), `ENCOACH_UNIFIED_SRS.md` (v1.0) **Author:** EnCoach Engineering Team +### Implementation Status + +| Artifact | Location | +|----------|----------| +| **Frontend Repository** | `https://git.albousalh.com/devops/encoach_frontend_new_v2.git` (branch: `main`) | +| **Backend Repository** | `https://git.albousalh.com/devops/encoach_backend_new_v2.git` (branch: `main`) | +| **Staging Frontend** | `http://5.189.151.117:3000` | +| **Staging Backend (Odoo 19)** | `http://5.189.151.117:8069` | +| **Frontend Stack** | React 18, TypeScript, Vite 5, shadcn/ui, TanStack Query, React Router v6 | +| **Backend Stack** | Odoo 19, Python 3.11, PostgreSQL 16, Docker Compose | +| **Frontend Pages** | 93 page components (28 root, 33 admin, 19 student, 14 teacher) | +| **Frontend Services** | 37 API service modules | +| **Frontend Types** | 29 TypeScript type definition files | +| **Frontend Query Hooks** | 21 TanStack Query hook modules | +| **Backend Custom Modules** | 27 `encoach_*` modules | +| **Backend OpenEduCat Modules** | 14 `openeducat_*` community modules | +| **Backend API Routes** | ~377 REST endpoints across 4 controller packages | + +All sections in this SRS have been implemented in both frontend and backend unless otherwise noted. The developer implemented all original SRS requirements plus additional OpenEduCat Enterprise-level features documented in Part VIII-B. + --- ## Table of Contents @@ -61,25 +81,35 @@ 34. [Institutional Exam Sessions](#34-institutional-exam-sessions) 35. [Assignment File Submissions](#35-assignment-file-submissions) +**Part VIII-B -- OpenEduCat Enterprise Features** +36. [Student Leave Management](#36-student-leave-management) +37. [Fees Management](#37-fees-management) +38. [Lessons Management](#38-lessons-management) +39. [Gradebook and Grading Assignments](#39-gradebook-and-grading-assignments) +40. [Student Progress Tracking](#40-student-progress-tracking) +41. [Library Management](#41-library-management) +42. [Activity Management](#42-activity-management) +43. [Facility and Asset Management](#43-facility-and-asset-management) + **Part IX -- Courseware and Content Delivery** -36. [Course Chapters](#36-course-chapters) -37. [Chapter Materials](#37-chapter-materials) -38. [AI Workbench for Course Content](#38-ai-workbench-for-course-content) +44. [Course Chapters](#44-course-chapters) +45. [Chapter Materials](#45-chapter-materials) +46. [AI Workbench for Course Content](#46-ai-workbench-for-course-content) **Part X -- Communication** -39. [Discussion Boards](#39-discussion-boards) -40. [Announcements](#40-announcements) -41. [Messaging](#41-messaging) +47. [Discussion Boards](#47-discussion-boards) +48. [Announcements](#48-announcements) +49. [Messaging](#49-messaging) **Part XI -- Notifications and FAQ** -42. [Notification Engine](#42-notification-engine) -43. [FAQ System](#43-faq-system) +50. [Notification Engine](#50-notification-engine) +51. [FAQ System](#51-faq-system) **Part XII -- Technical Specifications** -44. [Data Models](#44-data-models) -45. [REST API Specification](#45-rest-api-specification) -46. [Frontend Page Inventory](#46-frontend-page-inventory) -47. [Non-Functional Requirements](#47-non-functional-requirements) +52. [Data Models](#52-data-models) +53. [REST API Specification](#53-rest-api-specification) +54. [Frontend Page Inventory](#54-frontend-page-inventory) +55. [Non-Functional Requirements](#55-non-functional-requirements) --- @@ -283,6 +313,8 @@ All data access is scoped by entity membership. A user may belong to multiple en ## 4. Authentication and Authorization +> **Implementation:** `auth.service.ts` | `encoach_api/controllers/auth.py` | `Login.tsx`, `Register.tsx`, `ForgotPassword.tsx` + ### 4.1 Authentication | Method | Detail | @@ -393,6 +425,8 @@ Inner pages show: Home > Section > Nested segments (e.g., Assignments > Creator, ## 6. Subject Taxonomy +> **Implementation:** `taxonomy.service.ts` | `encoach_adaptive_api/controllers/taxonomy.py` | `AdminTaxonomy.tsx` + ### 6.1 Hierarchy ``` @@ -504,6 +538,8 @@ Information Technology ## 7. Diagnostic Assessment +> **Implementation:** `adaptive.service.ts` | `encoach_adaptive_api/controllers/diagnostic.py` | `StudentDiagnostic.tsx` + ### 7.1 Purpose When a student begins a new subject, a diagnostic assessment determines their per-topic proficiency. This is the input for learning plan generation. For English, this replaces/extends the existing Level Test. @@ -537,6 +573,8 @@ Diagnostics reuse `encoach.exam` with `is_diagnostic = True` and a new `subject_ ## 8. Proficiency Profile +> **Implementation:** `adaptive.service.ts` | `encoach_adaptive_api/controllers/proficiency.py` | `StudentProficiency.tsx` + ### 8.1 Mastery Levels | Level | Score Range | Color | @@ -560,6 +598,8 @@ Diagnostics reuse `encoach.exam` with `is_diagnostic = True` and a new `subject_ ## 9. Learning Plan Generation +> **Implementation:** `adaptive.service.ts` | `encoach_adaptive_api/controllers/learning_plan.py` | `StudentLearningPlan.tsx` + ### 9.1 Two Modes | Mode | UTAS Student | Freelance Student | @@ -591,6 +631,8 @@ Diagnostics reuse `encoach.exam` with `is_diagnostic = True` and a new `subject_ ## 10. Hybrid Content Delivery +> **Implementation:** `adaptive.service.ts`, `resources.service.ts`, `coaching.service.ts` | `encoach_adaptive_api/controllers/content.py`, `encoach_resources/controllers/resources_rest.py` | `StudentTopic.tsx` + ### 10.1 Content Resolution Order 1. **Human-uploaded resources** tagged to the topic (PDFs, videos, links) @@ -622,6 +664,8 @@ Diagnostics reuse `encoach.exam` with `is_diagnostic = True` and a new `subject_ ## 11. Progress Tracking and Mastery +> **Implementation:** `adaptive.service.ts`, `analytics.service.ts` | `encoach_adaptive_api/controllers/content.py`, `encoach_api/controllers/ai_analytics.py` | `StudentJourney.tsx`, `AdminAdaptiveAnalytics.tsx` + ### 11.1 Mastery Quiz | Parameter | Value | @@ -656,6 +700,8 @@ Diagnostics reuse `encoach.exam` with `is_diagnostic = True` and a new `subject_ ## 12. Course Management +> **Implementation:** `lms.service.ts` | `encoach_lms_api/controllers/courses.py` | `StudentCourses.tsx`, `TeacherCourses.tsx`, `AdminCourses.tsx` + ### 12.1 Overview Courses are managed through OpenEduCat models exposed via REST API. The frontend provides student, teacher, and admin course views. @@ -690,6 +736,8 @@ Courses are managed through OpenEduCat models exposed via REST API. The frontend ## 13. Batch and Enrollment +> **Implementation:** `lms.service.ts` | `encoach_lms_api/controllers/batches.py` | `AdminBatches.tsx` + | ID | Requirement | Route | |----|-------------|-------| | FR-BATCH-01 | List batches with student counts | `/admin/batches` | @@ -701,6 +749,8 @@ Courses are managed through OpenEduCat models exposed via REST API. The frontend ## 14. Timetable and Attendance +> **Implementation:** `lms.service.ts` | `encoach_lms_api/controllers/timetable.py`, `encoach_lms_api/controllers/attendance.py` | `StudentTimetable.tsx`, `TeacherTimetable.tsx`, `AdminTimetable.tsx`, `StudentAttendance.tsx`, `TeacherAttendance.tsx` + | ID | Requirement | Route | Role | |----|-------------|-------|------| | FR-TT-01 | View personal timetable | `/student/timetable` | Student | @@ -713,6 +763,8 @@ Courses are managed through OpenEduCat models exposed via REST API. The frontend ## 15. Gradebook and Reports +> **Implementation:** `lms.service.ts`, `analytics.service.ts` | `encoach_lms_api/controllers/grades.py`, `encoach_api/controllers/ai_analytics.py` | `StudentGrades.tsx`, `AdminReports.tsx` + | ID | Requirement | Route | Role | |----|-------------|-------|------| | FR-GRD-01 | View personal grades across courses | `/student/grades` | Student | @@ -726,6 +778,8 @@ Courses are managed through OpenEduCat models exposed via REST API. The frontend ## 16. Exam Management +> **Implementation:** `exams.service.ts` | `encoach_api/controllers/exam.py` | `AdminExamsList.tsx`, `AdminExamStructures.tsx`, `AdminRubrics.tsx`, `Exam.tsx` + ### 16.1 Exam CRUD (Production Parity) | ID | Requirement | Source | @@ -775,6 +829,8 @@ Courses are managed through OpenEduCat models exposed via REST API. The frontend ## 17. AI Content Generation +> **Implementation:** `generation.service.ts` | `encoach_api/controllers/generation.py` | `AdminGeneration.tsx` + ### 17.1 Generation per Subject | Subject | AI Generates | Prompt Model | @@ -796,6 +852,8 @@ Courses are managed through OpenEduCat models exposed via REST API. The frontend ## 18. Exam Delivery +> **Implementation:** `exams.service.ts`, `media.service.ts` | `encoach_api/controllers/exam.py`, `encoach_api/controllers/generation.py` | `Exam.tsx`, `OfficialExam.tsx` + ### 18.1 Delivery Modes | Mode | Route | Chrome | @@ -818,6 +876,8 @@ Courses are managed through OpenEduCat models exposed via REST API. The frontend ## 19. AI Grading +> **Implementation:** `evaluations.service.ts`, `plagiarism.service.ts` | `encoach_api/controllers/generation.py`, `encoach_lms_api/controllers/plagiarism.py` | `AdminApprovalWorkflows.tsx` + ### 19.1 Grading per Subject | Subject | Grading Type | Method | @@ -833,7 +893,9 @@ Courses are managed through OpenEduCat models exposed via REST API. The frontend | IT Scenario | AI evaluation | GPT-4o evaluates against rubric | | All Writing | AI detection | GPTZero per-sentence analysis | -### 19.2 Plagiarism Detection (NEW) +### 19.2 Plagiarism Detection (NEW -- Implemented) + +> **Implementation:** `plagiarism.service.ts` | `encoach_lms_api/controllers/plagiarism.py` | ID | Requirement | Source | |----|-------------|--------| @@ -887,6 +949,8 @@ Courses are managed through OpenEduCat models exposed via REST API. The frontend ## 20. AI Services Catalog +> **Implementation:** `coaching.service.ts`, `analytics.service.ts`, `generation.service.ts`, `evaluations.service.ts`, `media.service.ts` | `encoach_ai/`, `encoach_ai_generation/`, `encoach_ai_grading/`, `encoach_ai_media/`, `encoach_adaptive_ai/` + | Service | Model | Config | Usage | |---------|-------|--------|-------| | **OpenAI GPT-4o** | gpt-4o (primary), gpt-3.5-turbo (secondary) | Temp: 0.1 grading, 0.7 generation, 0.2 summaries. Max tokens: 4,097. JSON format. | Exam generation, grading, evaluation, training tips, learning plans, coaching, content generation | @@ -926,6 +990,8 @@ Each simulated AI component in the new frontend maps to a real backend service: ## 22. User Management (Production Parity) +> **Implementation:** `users.service.ts` | `encoach_api/controllers/users.py` | `AdminUsers.tsx` + | ID | Requirement | Route | |----|-------------|-------| | FR-USR-01 | Filter by entity | `/users?type=student\|teacher\|corporate\|mastercorporate` | @@ -939,6 +1005,8 @@ Each simulated AI component in the new frontend maps to a real backend service: ## 23. Entity Management (Production Parity) +> **Implementation:** `entities.service.ts` | `encoach_api/controllers/entities.py` | `AdminEntities.tsx` + | ID | Requirement | |----|-------------| | FR-ENT-01 | Search and pagination | @@ -950,6 +1018,8 @@ Each simulated AI component in the new frontend maps to a real backend service: ## 24. Classroom Management (Production Parity) +> **Implementation:** `classrooms.service.ts` | `encoach_api/controllers/classroom.py` | `AdminClassrooms.tsx` + | ID | Requirement | |----|-------------| | FR-CL-01 | Entity filter and search | @@ -962,6 +1032,8 @@ Each simulated AI component in the new frontend maps to a real backend service: ## 25. Assignment Management (Production Parity) +> **Implementation:** `assignments.service.ts` | `encoach_api/controllers/assignment.py` | `AdminAssignments.tsx`, `StudentAssignments.tsx`, `TeacherAssignments.tsx` + | ID | Requirement | |----|-------------| | FR-ASG-01 | Tabs: Active, Planned, Past, Start Expired, Archived with counts | @@ -1003,18 +1075,87 @@ Each simulated AI component in the new frontend maps to a real backend service: ## 26. Permission Management (Production Parity + Extension) +> **Implementation:** `entities.service.ts` (roles/permissions) | `encoach_api/controllers/roles.py` | `RolesPermissions.tsx`, `AuthorityMatrix.tsx`, `UserRoles.tsx` + | ID | Requirement | |----|-------------| | FR-PERM-01 | Navigate permission types at `/permissions` | | FR-PERM-02 | View/edit permission details at `/permissions/:id` | | FR-PERM-03 | **NEW:** Subject-parameterized permissions in UI (select subject, then skill permissions) | +### 26.2 Roles and Permissions CRUD (NEW -- Implemented) + +The developer implemented a complete roles and permissions CRUD system beyond the original entity-scoped model. + +| ID | Requirement | Route | Role | +|----|-------------|-------|------| +| FR-ROLE-01 | List all roles with permission counts | `/admin/roles-permissions` | Admin | +| FR-ROLE-02 | Create role with name and description | `/admin/roles-permissions` | Admin | +| FR-ROLE-03 | Update role details | `/admin/roles-permissions` | Admin | +| FR-ROLE-04 | Delete role | `/admin/roles-permissions` | Admin | +| FR-ROLE-05 | Update role permissions (assign/remove permissions) | `/admin/roles-permissions` | Admin | +| FR-ROLE-06 | List all permissions | `/admin/roles-permissions` | Admin | +| FR-ROLE-07 | Create custom permission | `/admin/roles-permissions` | Admin | +| FR-ROLE-08 | Delete permission | `/admin/roles-permissions` | Admin | + +**API Endpoints:** + +| Method | Path | Description | +|--------|------|-------------| +| `GET` | `/api/roles` | List all roles | +| `POST` | `/api/roles` | Create role | +| `GET` | `/api/roles/{id}` | Get role detail | +| `PATCH` | `/api/roles/{id}` | Update role | +| `DELETE` | `/api/roles/{id}` | Delete role | +| `PATCH` | `/api/roles/{id}/permissions` | Update role permissions | +| `GET` | `/api/permissions` | List all permissions | +| `POST` | `/api/permissions` | Create permission | +| `DELETE` | `/api/permissions/{id}` | Delete permission | + +### 26.3 User Role Assignment (NEW -- Implemented) + +| ID | Requirement | Route | Role | +|----|-------------|-------|------| +| FR-UROLE-01 | List users with their assigned roles | `/admin/user-roles` | Admin | +| FR-UROLE-02 | View roles for a specific user | `/admin/user-roles` | Admin | +| FR-UROLE-03 | Assign/remove roles for a user | `/admin/user-roles` | Admin | +| FR-UROLE-04 | Toggle individual role on/off for a user | `/admin/user-roles` | Admin | + +**API Endpoints:** + +| Method | Path | Description | +|--------|------|-------------| +| `GET` | `/api/users/with-roles` | List users with role details | +| `GET` | `/api/users/{id}/roles` | Get roles for a user | +| `PATCH` | `/api/users/{id}/roles` | Update user roles | +| `POST` | `/api/users/{id}/roles/toggle` | Toggle a single role | + +### 26.4 Authority Matrix (NEW -- Implemented) + +A visual matrix showing all roles vs. all permissions, allowing administrators to toggle permission assignments visually. + +| ID | Requirement | Route | Role | +|----|-------------|-------|------| +| FR-AUTH-01 | Display role-permission matrix (roles as columns, permissions as rows) | `/admin/authority-matrix` | Admin | +| FR-AUTH-02 | Toggle individual permission cells (grant/revoke) | `/admin/authority-matrix` | Admin | +| FR-AUTH-03 | View user-specific authority matrix | `/admin/authority-matrix` | Admin | + +**API Endpoints:** + +| Method | Path | Description | +|--------|------|-------------| +| `GET` | `/api/authority-matrix` | Get full role-permission matrix | +| `POST` | `/api/authority-matrix/toggle` | Toggle a permission cell | +| `GET` | `/api/user-authority-matrix` | Get user-level authority view | + --- # Part VII -- Support and Commercial ## 27. Ticketing System (Production Parity) +> **Implementation:** `tickets.service.ts` | `encoach_api/controllers/ticket.py` | `AdminTickets.tsx` + | ID | Requirement | |----|-------------| | FR-TCK-01 | Filters: Status, Type, Assignee, Source (All/Webpage/Platform) | @@ -1026,6 +1167,8 @@ Each simulated AI component in the new frontend maps to a real backend service: ## 28. Subscriptions and Payments +> **Implementation:** `subscriptions.service.ts` | `encoach_api/controllers/subscription.py` | `AdminPaymentRecord.tsx`, `Payment.tsx` + ### 28.1 Billing Models | Model | Description | Payment | @@ -1050,6 +1193,8 @@ Each simulated AI component in the new frontend maps to a real backend service: ## 29. Training Content +> **Implementation:** `training.service.ts` | `encoach_api/controllers/training.py` | `AdminTrainingVocabulary.tsx`, `AdminTrainingGrammar.tsx` + ### 29.1 Existing (Production Parity) | ID | Requirement | Route | @@ -1077,6 +1222,8 @@ All LMS features in this part are backed by OpenEduCat community modules (ported ## 30. Academic Year and Term Management +> **Implementation:** `academic.service.ts` | `encoach_lms_api/controllers/academic.py` | `AdminAcademicYears.tsx` + ### 30.1 Overview Academic years define the institutional calendar. Each year contains terms (semesters, quarters) that govern course scheduling, batch periods, and exam sessions. @@ -1132,6 +1279,8 @@ Academic years define the institutional calendar. Each year contains terms (seme ## 31. Department Management +> **Implementation:** `academic.service.ts` | `encoach_lms_api/controllers/departments.py` | `AdminDepartments.tsx` + ### 31.1 Overview Departments organize faculty, courses, and subjects into academic units (e.g., "Department of Mathematics", "Department of IT"). @@ -1168,6 +1317,8 @@ Departments organize faculty, courses, and subjects into academic units (e.g., " ## 32. Admission and Enrollment +> **Implementation:** `admission.service.ts` | `encoach_lms_api/controllers/admissions.py` | `AdminAdmissionRegister.tsx`, `AdminAdmissions.tsx` + ### 32.1 Overview The admission workflow manages student applications from submission through confirmation to enrollment. Admission registers define open enrollment windows. @@ -1244,6 +1395,8 @@ The admission workflow manages student applications from submission through conf ## 33. Subject Registration +> **Implementation:** `institutional-exam.service.ts` | `encoach_lms_api/controllers/subject_registration.py` | `StudentSubjectRegistration.tsx` + ### 33.1 Overview Within enrolled courses, students register for specific subjects. This is required for timetable, attendance, and exam eligibility. @@ -1287,6 +1440,8 @@ Within enrolled courses, students register for specific subjects. This is requir ## 34. Institutional Exam Sessions +> **Implementation:** `institutional-exam.service.ts` | `encoach_lms_api/controllers/inst_exams.py` | `AdminExamSessions.tsx`, `AdminMarksheets.tsx` + ### 34.1 Overview Institutional exam sessions group traditional exams (midterms, finals) for a course/batch. These are separate from EnCoach AI-powered exams. They use the OpenEduCat exam, marksheet, and grading system. @@ -1446,6 +1601,8 @@ Institutional exam sessions group traditional exams (midterms, finals) for a cou ## 35. Assignment File Submissions +> **Implementation:** `institutional-exam.service.ts` | `encoach_lms_api/controllers/course_assignments.py` | `TeacherAssignments.tsx`, `StudentAssignments.tsx` + ### 35.1 Overview Traditional course assignments where students submit files and teachers grade them. Coexists with EnCoach exam-wrapper assignments (`encoach.assignment`). @@ -1527,19 +1684,436 @@ Traditional course assignments where students submit files and teachers grade th --- +# Part VIII-B -- OpenEduCat Enterprise Features + +The following sections cover additional institutional features implemented by the developer beyond the original SRS. These features leverage OpenEduCat Enterprise modules and extend the platform with student lifecycle management, financial tracking, library services, and facility management. + +--- + +## 36. Student Leave Management + +> **Implementation:** `student-leave.service.ts` | `encoach_lms_api/controllers/student_leave.py` | `AdminStudentLeave.tsx` + +### 36.1 Overview + +Students submit leave requests with a type, date range, and justification. Administrators approve or reject requests. Leave types are configurable. + +### 36.2 Data Models + +**`op.student.leave.request`** (OpenEduCat Enterprise) + +| Field | Type | Description | +|-------|------|-------------| +| `request_number` | Char | Auto-generated request number | +| `student_id` | Many2one | Requesting student | +| `leave_type` | Many2one | Leave type reference | +| `start_date` | Date | Leave start | +| `end_date` | Date | Leave end | +| `duration` | Float | Computed duration in days | +| `description` | Text | Justification | +| `state` | Selection | `draft`, `confirm`, `validate`, `approve`, `refuse`, `cancel` | +| `approve_date` | Date | Date of approval | + +**`op.student.leave.type`** + +| Field | Type | Description | +|-------|------|-------------| +| `name` | Char | Leave type name (e.g., Medical, Personal, Academic) | + +### 36.3 Functional Requirements + +| ID | Requirement | Route | Role | +|----|-------------|-------|------| +| FR-SL-01 | List student leave requests with status filters | `/admin/student-leave` | Admin | +| FR-SL-02 | Create leave request (student, type, dates, description) | `/admin/student-leave` | Admin/Student | +| FR-SL-03 | Approve/reject leave request with state transition | `/admin/student-leave` | Admin | +| FR-SL-04 | Manage leave types (CRUD) | `/admin/student-leave` | Admin | + +### 36.4 API Endpoints + +| Method | Path | Description | +|--------|------|-------------| +| `GET` | `/api/student-leaves` | List leave requests | +| `POST` | `/api/student-leaves` | Create leave request | +| `PATCH` | `/api/student-leaves/{id}` | Update leave request | +| `POST` | `/api/student-leaves/{id}/approve` | Approve request | +| `POST` | `/api/student-leaves/{id}/reject` | Reject request | +| `GET` | `/api/student-leave-types` | List leave types | +| `POST` | `/api/student-leave-types` | Create leave type | + +--- + +## 37. Fees Management + +> **Implementation:** `fees.service.ts` | `encoach_lms_api/controllers/fees.py` | `AdminFees.tsx` + +### 37.1 Overview + +Institutional fee plans track student financial obligations per course. The system tracks total, paid, and remaining amounts per student, linked to invoicing. + +### 37.2 Data Models + +**`op.fees.plan`** (OpenEduCat Enterprise) + +| Field | Type | Description | +|-------|------|-------------| +| `student_id` | Many2one | Student | +| `course_id` | Many2one | Course | +| `total_amount` | Float | Total fee amount | +| `paid_amount` | Float | Amount paid to date | +| `remaining_amount` | Float | Computed remaining balance | +| `state` | Selection | Fee plan state | + +**`op.student.fees.details`** + +| Field | Type | Description | +|-------|------|-------------| +| `student_id` | Many2one | Student | +| `amount` | Float | Fee amount | +| `date` | Date | Fee date | +| `state` | Selection | Payment state | +| `invoice_state` | Selection | Invoice state | +| `product_name` | Char | Fee product name | + +**`op.fees.terms`** + +| Field | Type | Description | +|-------|------|-------------| +| `name` | Char | Term name | +| `no_days` | Integer | Number of days for payment | +| `line_ids` | One2many | Fee term lines | + +### 37.3 Functional Requirements + +| ID | Requirement | Route | Role | +|----|-------------|-------|------| +| FR-FEES-01 | List fees plans with student and course details | `/admin/fees` | Admin | +| FR-FEES-02 | View individual student fees with payment history | `/admin/fees` | Admin | +| FR-FEES-03 | View fees terms configuration | `/admin/fees` | Admin | + +### 37.4 API Endpoints + +| Method | Path | Description | +|--------|------|-------------| +| `GET` | `/api/fees-plans` | List fee plans | +| `GET` | `/api/fees-plans/{id}` | Get fee plan detail | +| `GET` | `/api/student-fees` | List student fee details | +| `GET` | `/api/fees-terms` | List fees terms | + +--- + +## 38. Lessons Management + +> **Implementation:** `lesson.service.ts` | `encoach_lms_api/controllers/lessons.py` | `AdminLessons.tsx` + +### 38.1 Overview + +Lessons represent individual teaching sessions within timetable sessions. They link subjects to specific timetable slots and track the topic covered. + +### 38.2 Data Model + +**`op.session.lesson`** (OpenEduCat Enterprise) + +| Field | Type | Description | +|-------|------|-------------| +| `name` | Char | Lesson name | +| `lesson_topic` | Char | Topic covered | +| `course_id` | Many2one | Course | +| `batch_id` | Many2one | Batch | +| `subject_id` | Many2one | Subject | +| `session_id` | Many2one | Timetable session | +| `faculty_id` | Many2one | Teaching faculty | +| `start_datetime` | Datetime | Lesson start | +| `end_datetime` | Datetime | Lesson end | + +### 38.3 Functional Requirements + +| ID | Requirement | Route | Role | +|----|-------------|-------|------| +| FR-LSN-01 | List lessons with subject and session details | `/admin/lessons` | Admin | +| FR-LSN-02 | Create lesson (name, topic, course, batch, subject, session, faculty, times) | `/admin/lessons` | Admin | +| FR-LSN-03 | Update/delete lessons | `/admin/lessons` | Admin | + +### 38.4 API Endpoints + +| Method | Path | Description | +|--------|------|-------------| +| `GET` | `/api/lessons` | List lessons | +| `POST` | `/api/lessons` | Create lesson | +| `PATCH` | `/api/lessons/{id}` | Update lesson | +| `DELETE` | `/api/lessons/{id}` | Delete lesson | + +--- + +## 39. Gradebook and Grading Assignments + +> **Implementation:** `gradebook.service.ts` | `encoach_lms_api/controllers/gradebook.py` | `AdminGradebook.tsx` + +### 39.1 Overview + +The gradebook aggregates student marks across courses and academic years. Grading assignments define assessment items with marks and sequences. Gradebook lines show per-student, per-assignment results with percentages. + +### 39.2 Data Models + +**`op.gradebook`** (OpenEduCat Enterprise) + +| Field | Type | Description | +|-------|------|-------------| +| `student_id` | Many2one | Student | +| `course_id` | Many2one | Course | +| `academic_year_id` | Many2one | Academic year | +| `line_ids` | One2many | Gradebook lines | + +**`op.gradebook.line`** + +| Field | Type | Description | +|-------|------|-------------| +| `gradebook_id` | Many2one | Parent gradebook | +| `student_name` | Char | Related student name | +| `assignment_name` | Char | Related assignment name | +| `marks` | Float | Marks obtained | +| `percentage` | Float | Computed percentage | +| `state` | Selection | Line state | + +**`grading.assignment`** (extended) + +| Field | Type | Description | +|-------|------|-------------| +| `sequence` | Char | Assignment sequence code | +| `name` | Char | Assignment name | +| `course_id` | Many2one | Course | +| `subject_id` | Many2one | Subject | +| `state` | Selection | Assignment state | +| `issued_date` | Date | Issue date | + +### 39.3 Functional Requirements + +| ID | Requirement | Route | Role | +|----|-------------|-------|------| +| FR-GB-01 | List gradebooks filtered by course and academic year | `/admin/gradebook` | Admin | +| FR-GB-02 | View gradebook lines per student with marks and percentages | `/admin/gradebook` | Admin | +| FR-GB-03 | Create/update/delete grading assignments | `/admin/gradebook` | Admin | + +### 39.4 API Endpoints + +| Method | Path | Description | +|--------|------|-------------| +| `GET` | `/api/gradebooks` | List gradebooks | +| `GET` | `/api/gradebook-lines` | List gradebook lines | +| `GET` | `/api/grading-assignments` | List grading assignments | +| `POST` | `/api/grading-assignments` | Create grading assignment | +| `PATCH` | `/api/grading-assignments/{id}` | Update grading assignment | +| `DELETE` | `/api/grading-assignments/{id}` | Delete grading assignment | + +--- + +## 40. Student Progress Tracking + +> **Implementation:** `student-progress.service.ts` | `encoach_lms_api/controllers/student_progress.py` | `AdminStudentProgress.tsx` + +### 40.1 Overview + +Aggregate view of student academic progression combining attendance, assignment completion, and marksheet results into a unified tracking interface. + +### 40.2 Data Model + +**`op.student.progression`** (OpenEduCat Enterprise) + +| Field | Type | Description | +|-------|------|-------------| +| `student_id` | Many2one | Student | +| `total_attendance` | Float | Computed total attendance percentage | +| `total_assignment` | Float | Computed total assignment count/score | +| `total_marksheet_line` | Float | Computed total marksheet entries | + +### 40.3 Functional Requirements + +| ID | Requirement | Route | Role | +|----|-------------|-------|------| +| FR-SP-01 | List student progress with attendance, assignment, and marksheet aggregates | `/admin/student-progress` | Admin | +| FR-SP-02 | Filter by course, batch, or individual student | `/admin/student-progress` | Admin | + +### 40.4 API Endpoints + +| Method | Path | Description | +|--------|------|-------------| +| `GET` | `/api/student-progress` | List student progression records | + +--- + +## 41. Library Management + +> **Implementation:** `library.service.ts` | `encoach_lms_api/controllers/library.py` | `AdminLibrary.tsx` + +### 41.1 Overview + +Institutional library management supporting media cataloging, borrowing (movements), and library card issuance. Tracks media items (books, journals, CDs), their circulation, and student/faculty borrowing history. + +### 41.2 Data Models + +**`op.media`** (OpenEduCat Library) + +| Field | Type | Description | +|-------|------|-------------| +| `name` | Char | Media title | +| `isbn` | Char | ISBN number | +| `author` | Char | Author name | +| `edition` | Char | Edition | +| `media_type` | Selection | Media type (book, journal, CD, etc.) | + +**`op.media.movement`** + +| Field | Type | Description | +|-------|------|-------------| +| `media_id` | Many2one | Media item | +| `student_id` | Many2one | Borrowing student | +| `faculty_id` | Many2one | Issuing faculty | +| `issued_date` | Date | Issue date | +| `return_date` | Date | Return date | +| `state` | Selection | Movement state (issued, returned, overdue) | + +**`op.library.card`** + +| Field | Type | Description | +|-------|------|-------------| +| `number` | Char | Card number | +| `student_id` | Many2one | Cardholder student | +| `faculty_id` | Many2one | Issuing faculty | + +### 41.3 Functional Requirements + +| ID | Requirement | Route | Role | +|----|-------------|-------|------| +| FR-LIB-01 | Catalog media items with ISBN, author, edition | `/admin/library` | Admin | +| FR-LIB-02 | Track media movements (issue, return) | `/admin/library` | Admin | +| FR-LIB-03 | Issue and manage library cards | `/admin/library` | Admin | +| FR-LIB-04 | Delete media items | `/admin/library` | Admin | + +### 41.4 API Endpoints + +| Method | Path | Description | +|--------|------|-------------| +| `GET` | `/api/library/media` | List media items | +| `POST` | `/api/library/media` | Create media item | +| `DELETE` | `/api/library/media/{id}` | Delete media item | +| `GET` | `/api/library/movements` | List movements | +| `POST` | `/api/library/movements` | Create movement (issue) | +| `PATCH` | `/api/library/movements/{id}` | Update movement | +| `POST` | `/api/library/movements/{id}/return` | Return media | +| `GET` | `/api/library/cards` | List library cards | +| `POST` | `/api/library/cards` | Create library card | + +--- + +## 42. Activity Management + +> **Implementation:** `activity.service.ts` | `encoach_lms_api/controllers/activities.py` | `AdminActivities.tsx` + +### 42.1 Overview + +Tracks extracurricular and academic activities per student. Activity types are configurable (sports, cultural, academic, volunteer, etc.). + +### 42.2 Data Models + +**`op.activity`** (OpenEduCat Activity) + +| Field | Type | Description | +|-------|------|-------------| +| `student_id` | Many2one | Student | +| `type_id` | Many2one | Activity type | +| `date` | Date | Activity date | +| `description` | Text | Activity description | + +**`op.activity.type`** + +| Field | Type | Description | +|-------|------|-------------| +| `name` | Char | Type name | + +### 42.3 Functional Requirements + +| ID | Requirement | Route | Role | +|----|-------------|-------|------| +| FR-ACT-01 | List student activities with type and date | `/admin/activities` | Admin | +| FR-ACT-02 | Create/update/delete activities | `/admin/activities` | Admin | +| FR-ACT-03 | Manage activity types (CRUD) | `/admin/activities` | Admin | + +### 42.4 API Endpoints + +| Method | Path | Description | +|--------|------|-------------| +| `GET` | `/api/activities` | List activities | +| `POST` | `/api/activities` | Create activity | +| `PATCH` | `/api/activities/{id}` | Update activity | +| `DELETE` | `/api/activities/{id}` | Delete activity | +| `GET` | `/api/activity-types` | List activity types | +| `POST` | `/api/activity-types` | Create activity type | +| `DELETE` | `/api/activity-types/{id}` | Delete activity type | + +--- + +## 43. Facility and Asset Management + +> **Implementation:** `facility.service.ts` | `encoach_lms_api/controllers/facilities.py` | `AdminFacilities.tsx` + +### 43.1 Overview + +Manages institutional facilities (buildings, labs, rooms) and their associated assets (equipment, furniture). Facilities can be linked to classrooms and timetable sessions. + +### 43.2 Data Models + +**`op.facility`** (OpenEduCat Facility) + +| Field | Type | Description | +|-------|------|-------------| +| `name` | Char | Facility name | +| `code` | Char | Facility code | + +**`op.facility.line`** (Asset) + +| Field | Type | Description | +|-------|------|-------------| +| `name` | Char | Asset name | +| `code` | Char | Asset code | +| `product_name` | Char | Product description | + +### 43.3 Functional Requirements + +| ID | Requirement | Route | Role | +|----|-------------|-------|------| +| FR-FAC-01 | List facilities with codes | `/admin/facilities` | Admin | +| FR-FAC-02 | Create/update/delete facilities | `/admin/facilities` | Admin | +| FR-FAC-03 | List and manage assets within facilities | `/admin/facilities` | Admin | + +### 43.4 API Endpoints + +| Method | Path | Description | +|--------|------|-------------| +| `GET` | `/api/facilities` | List facilities | +| `POST` | `/api/facilities` | Create facility | +| `PATCH` | `/api/facilities/{id}` | Update facility | +| `DELETE` | `/api/facilities/{id}` | Delete facility | +| `GET` | `/api/assets` | List assets | +| `POST` | `/api/assets` | Create asset | +| `DELETE` | `/api/assets/{id}` | Delete asset | + +--- + # Part IX -- Courseware and Content Delivery This part covers the Moodle-style structured course delivery system: chapter-based content organization, material management, and AI-powered course content generation. --- -## 36. Course Chapters +## 44. Course Chapters -### 36.1 Overview +> **Implementation:** `courseware.service.ts` | `encoach_lms_api/controllers/courseware.py` | `TeacherCourseChapters.tsx`, `StudentCourseChapterView.tsx` + +### 44.1 Overview Courses are divided into chapters (modules). Teachers create chapters with scheduled start dates, content materials, and lock/unlock controls. Students progress through chapters sequentially or as unlocked by the teacher. -### 36.2 Data Model (`encoach.course.chapter`) +### 44.2 Data Model (`encoach.course.chapter`) | Field | Type | Description | |-------|------|-------------| @@ -1557,7 +2131,7 @@ Courses are divided into chapters (modules). Teachers create chapters with sched | `exam_ids` | Many2many | Linked exams/quizzes | | `active` | Boolean | Soft-delete flag | -### 36.3 Chapter Progress Model (`encoach.chapter.progress`) +### 44.3 Chapter Progress Model (`encoach.chapter.progress`) | Field | Type | Description | |-------|------|-------------| @@ -1569,7 +2143,7 @@ Courses are divided into chapters (modules). Teachers create chapters with sched | `materials_completed` | Integer | Count of materials viewed/downloaded | | `materials_total` | Integer | Total materials in chapter | -### 36.4 Functional Requirements +### 44.4 Functional Requirements | ID | Requirement | Route | Role | |----|-------------|-------|------| @@ -1584,7 +2158,7 @@ Courses are divided into chapters (modules). Teachers create chapters with sched | FR-CH-09 | Chapter completion notification sent to student | Backend | System | | FR-CH-10 | Teacher views chapter progress per student | `/teacher/courses/:id/chapters` | Teacher | -### 36.5 API Endpoints +### 44.5 API Endpoints | Method | Path | Description | |--------|------|-------------| @@ -1601,13 +2175,15 @@ Courses are divided into chapters (modules). Teachers create chapters with sched --- -## 37. Chapter Materials +## 45. Chapter Materials -### 37.1 Overview +> **Implementation:** `courseware.service.ts` | `encoach_lms_api/controllers/courseware.py` | `TeacherCourseChapters.tsx` + +### 45.1 Overview Each chapter contains materials: uploaded files (PDFs, documents), videos, audio, images, hyperlinks, and articles. Teachers control download permissions per material. -### 37.2 Data Model (`encoach.chapter.material`) +### 45.2 Data Model (`encoach.chapter.material`) | Field | Type | Description | |-------|------|-------------| @@ -1623,7 +2199,7 @@ Each chapter contains materials: uploaded files (PDFs, documents), videos, audio | `book_chapters` | Text (JSON) | Book chapter structure (if following original book chapters) | | `active` | Boolean | Soft-delete flag | -### 37.3 Functional Requirements +### 45.3 Functional Requirements | ID | Requirement | Route | Role | |----|-------------|-------|------| @@ -1636,7 +2212,7 @@ Each chapter contains materials: uploaded files (PDFs, documents), videos, audio | FR-MAT-07 | Student downloads materials if download is enabled | `/student/courses/:id/chapters/:chapterId` | Student | | FR-MAT-08 | System tracks which materials a student has viewed/downloaded | Backend | System | -### 37.4 API Endpoints +### 45.4 API Endpoints | Method | Path | Description | |--------|------|-------------| @@ -1650,13 +2226,15 @@ Each chapter contains materials: uploaded files (PDFs, documents), videos, audio --- -## 38. AI Workbench for Course Content +## 46. AI Workbench for Course Content -### 38.1 Overview +> **Implementation:** `courseware.service.ts` | `encoach_lms_api/controllers/courseware.py` | `TeacherAIWorkbench.tsx` + +### 46.1 Overview Teachers use the AI Workbench to generate course content automatically. The AI generates chapters, materials, exercises, and grading rubrics based on high-level requirements input by the teacher. -### 38.2 AI Workbench Flow +### 46.2 AI Workbench Flow 1. Teacher inputs: topic name, objectives, complexity level, target audience 2. AI generates: chapter structure with learning outcomes, reading content, exercises, multimedia suggestions @@ -1665,7 +2243,7 @@ Teachers use the AI Workbench to generate course content automatically. The AI g 5. Teacher approves and publishes (follows approval workflow if configured) 6. AI can suggest additional materials based on selected student performance profiles -### 38.3 Functional Requirements +### 46.3 Functional Requirements | ID | Requirement | Route | Role | |----|-------------|-------|------| @@ -1679,7 +2257,7 @@ Teachers use the AI Workbench to generate course content automatically. The AI g | FR-WB-08 | Teacher selects student profiles for AI to suggest additional materials based on performance | `/teacher/courses/:id/workbench` | Teacher | | FR-WB-09 | Generated content follows approval workflow before publishing | Backend | System | -### 38.4 API Endpoints +### 46.4 API Endpoints | Method | Path | Description | |--------|------|-------------| @@ -1694,13 +2272,15 @@ Teachers use the AI Workbench to generate course content automatically. The AI g # Part X -- Communication -## 39. Discussion Boards +## 47. Discussion Boards -### 39.1 Overview +> **Implementation:** `communication.service.ts` | `encoach_lms_api/controllers/communication.py` | `StudentDiscussions.tsx`, `TeacherDiscussions.tsx` + +### 47.1 Overview Per-class discussion boards enable student-to-student and student-to-teacher communication. Discussion boards can be attached to courses, chapters, or assignments. -### 39.2 Data Models +### 47.2 Data Models **`encoach.discussion.board`** @@ -1729,7 +2309,7 @@ Per-class discussion boards enable student-to-student and student-to-teacher com | `is_resolved` | Boolean | Marked as resolved (for Q&A) | | `created_at` | Datetime | Post time | -### 39.3 Functional Requirements +### 47.3 Functional Requirements | ID | Requirement | Route | Role | |----|-------------|-------|------| @@ -1741,7 +2321,7 @@ Per-class discussion boards enable student-to-student and student-to-teacher com | FR-DISC-06 | Students view other participants within the same class | `/student/discussions` | Student | | FR-DISC-07 | File attachments on posts | Both pages | Both | -### 39.4 API Endpoints +### 47.4 API Endpoints | Method | Path | Description | |--------|------|-------------| @@ -1757,13 +2337,15 @@ Per-class discussion boards enable student-to-student and student-to-teacher com --- -## 40. Announcements +## 48. Announcements -### 40.1 Overview +> **Implementation:** `communication.service.ts` | `encoach_lms_api/controllers/communication.py` | `StudentAnnouncements.tsx`, `TeacherAnnouncements.tsx` + +### 48.1 Overview Teachers broadcast announcements to classes. System-wide announcements can be created by administrators. -### 40.2 Data Model (`encoach.announcement`) +### 48.2 Data Model (`encoach.announcement`) | Field | Type | Description | |-------|------|-------------| @@ -1779,7 +2361,7 @@ Teachers broadcast announcements to classes. System-wide announcements can be cr | `send_email` | Boolean | Also send via email | | `attachment_ids` | Many2many | File attachments | -### 40.3 Functional Requirements +### 48.3 Functional Requirements | ID | Requirement | Route | Role | |----|-------------|-------|------| @@ -1789,7 +2371,7 @@ Teachers broadcast announcements to classes. System-wide announcements can be cr | FR-ANN-04 | Students view announcements on dashboard and dedicated page | `/student/announcements` | Student | | FR-ANN-05 | Priority-based display (urgent announcements highlighted) | All dashboards | All | -### 40.4 API Endpoints +### 48.4 API Endpoints | Method | Path | Description | |--------|------|-------------| @@ -1801,13 +2383,15 @@ Teachers broadcast announcements to classes. System-wide announcements can be cr --- -## 41. Messaging +## 49. Messaging -### 41.1 Overview +> **Implementation:** `communication.service.ts` | `encoach_lms_api/controllers/communication.py` | `StudentMessages.tsx`, `TeacherMessages.tsx` + +### 49.1 Overview Direct messaging between platform users. Teachers can message students individually. Students can message other students within the same class (if allowed). Platform can send emails through linked accounts. -### 41.2 Data Model (`encoach.message`) +### 49.2 Data Model (`encoach.message`) | Field | Type | Description | |-------|------|-------------| @@ -1821,7 +2405,7 @@ Direct messaging between platform users. Teachers can message students individua | `send_email_copy` | Boolean | Also send copy via email | | `created_at` | Datetime | Sent time | -### 41.3 Functional Requirements +### 49.3 Functional Requirements | ID | Requirement | Route | Role | |----|-------------|-------|------| @@ -1831,7 +2415,7 @@ Direct messaging between platform users. Teachers can message students individua | FR-MSG-04 | File attachments on messages | Both pages | All | | FR-MSG-05 | Students see other participants within same class | `/student/messages` | Student | -### 41.4 API Endpoints +### 49.4 API Endpoints | Method | Path | Description | |--------|------|-------------| @@ -1846,13 +2430,15 @@ Direct messaging between platform users. Teachers can message students individua # Part XI -- Notifications and FAQ -## 42. Notification Engine +## 50. Notification Engine -### 42.1 Overview +> **Implementation:** `notification.service.ts` | `encoach_lms_api/controllers/notification.py` | `AdminNotificationRules.tsx` + +### 50.1 Overview Centralized notification system supporting both in-app and email notifications. Notifications are triggered by system events (deadlines, chapter unlocks, result releases, announcements) and can be configured by teachers and admins. -### 42.2 Data Models +### 50.2 Data Models **`encoach.notification`** @@ -1893,7 +2479,7 @@ Centralized notification system supporting both in-app and email notifications. | `announcement_alerts` | Boolean | Announcement alerts | | `message_alerts` | Boolean | New message alerts | -### 42.3 Functional Requirements +### 50.3 Functional Requirements | ID | Requirement | Route | Role | |----|-------------|-------|------| @@ -1905,7 +2491,7 @@ Centralized notification system supporting both in-app and email notifications. | FR-NOT-06 | Users configure personal notification preferences | Profile pages | All | | FR-NOT-07 | Notification action button redirects to relevant page | All layouts | All | -### 42.4 API Endpoints +### 50.4 API Endpoints | Method | Path | Description | |--------|------|-------------| @@ -1922,13 +2508,15 @@ Centralized notification system supporting both in-app and email notifications. --- -## 43. FAQ System +## 51. FAQ System -### 43.1 Overview +> **Implementation:** `faq.service.ts` | `encoach_lms_api/controllers/faq.py` | `AdminFAQ.tsx`, `FAQ.tsx` (public) + +### 51.1 Overview Interactive FAQ system editable by super admin. FAQ items are organized by categories and filtered by target audience (student, entity, or both). Supports text, images, and video content. -### 43.2 Data Models +### 51.2 Data Models **`encoach.faq.category`** @@ -1953,7 +2541,7 @@ Interactive FAQ system editable by super admin. FAQ items are organized by categ | `sequence` | Integer | Display order | | `active` | Boolean | Active flag | -### 43.3 Functional Requirements +### 51.3 Functional Requirements | ID | Requirement | Route | Role | |----|-------------|-------|------| @@ -1964,7 +2552,7 @@ Interactive FAQ system editable by super admin. FAQ items are organized by categ | FR-FAQ-05 | Search bar to find FAQ items by keyword | `/faq` | All | | FR-FAQ-06 | Interactive accordion-style display (click question to expand answer) | `/faq` | All | -### 43.4 API Endpoints +### 51.4 API Endpoints | Method | Path | Description | |--------|------|-------------| @@ -1981,9 +2569,9 @@ Interactive FAQ system editable by super admin. FAQ items are organized by categ # Part XII -- Technical Specifications -## 44. Data Models +## 52. Data Models -### 44.1 Existing Models (from `ielts-be-v0`) +### 52.1 Existing Models (from `ielts-be-v0`) | Model | Module | Purpose | |-------|--------|---------| @@ -2011,7 +2599,7 @@ Interactive FAQ system editable by super admin. FAQ items are organized by categ | `encoach.elai.avatar` | `encoach_ai_media` | ELAI avatar profiles | | `encoach.registration` | `encoach_registration` | Batch registration mixin | -### 44.2 New Models (Adaptive Learning Engine) +### 52.2 New Models (Adaptive Learning Engine) | Model | Module | Purpose | Key Fields | |-------|--------|---------|------------| @@ -2026,24 +2614,81 @@ Interactive FAQ system editable by super admin. FAQ items are organized by categ | `encoach.resource.completion` | `encoach_adaptive` | Resource viewing tracking | `student_id`, `resource_id`, `viewed`, `time_spent_minutes`, `rating` | | `encoach.ai.content.cache` | `encoach_adaptive` | Cached AI-generated content | `topic_id`, `content_type`, `difficulty_level`, `content`, `model_used`, `review_status` | -### 44.3 New Models (SIS Integration) +### 52.3 New Models (SIS Integration) | Model | Module | Purpose | |-------|--------|---------| | `encoach.sis.sync` | `encoach_sis` | SIS sync job tracking | | `encoach.sis.mapping` | `encoach_sis` | Field mapping between SIS and EnCoach | -### 44.4 New Models (Branding) +### 52.4 New Models (Branding) | Model | Module | Purpose | |-------|--------|---------| | `encoach.branding` | `encoach_branding` | Tenant branding configuration (logo, colors, fonts) | +### 52.5 New Models (OpenEduCat Enterprise -- Beyond SRS) + +| Model | Module | Purpose | Key Fields | +|-------|--------|---------|------------| +| `op.student.leave.request` | `openeducat_student_leave_enterprise` | Student leave requests | `request_number`, `student_id`, `leave_type`, `start_date`, `end_date`, `duration`, `description`, `state`, `approve_date` | +| `op.student.leave.type` | `openeducat_student_leave_enterprise` | Leave type definitions | `name` | +| `op.fees.plan` | `openeducat_fees` | Student fee plans | `student_id`, `course_id`, `total_amount`, `paid_amount`, `remaining_amount`, `state` | +| `op.student.fees.details` | `openeducat_fees` | Fee payment details | `student_id`, `amount`, `date`, `state`, `invoice_state`, `product_name` | +| `op.fees.terms` | `openeducat_fees` | Fee payment terms | `name`, `no_days`, `line_ids` | +| `op.session.lesson` | `openeducat_lesson` | Lesson sessions | `name`, `lesson_topic`, `course_id`, `batch_id`, `subject_id`, `session_id`, `faculty_id`, `start_datetime`, `end_datetime` | +| `op.gradebook` | `openeducat_grading` | Student gradebooks | `student_id`, `course_id`, `academic_year_id`, `line_ids` | +| `op.gradebook.line` | `openeducat_grading` | Gradebook entries | `gradebook_id`, `marks`, `percentage`, `state` | +| `op.student.progression` | `openeducat_student_progress_enterprise` | Aggregate progress tracking | `student_id`, `total_attendance`, `total_assignment`, `total_marksheet_line` | +| `op.media` | `openeducat_library` | Library media catalog | `name`, `isbn`, `author`, `edition`, `media_type` | +| `op.media.movement` | `openeducat_library` | Library circulation | `media_id`, `student_id`, `faculty_id`, `issued_date`, `return_date`, `state` | +| `op.library.card` | `openeducat_library` | Library cards | `number`, `student_id`, `faculty_id` | +| `op.activity` | `openeducat_activity` | Student activities | `student_id`, `type_id`, `date`, `description` | +| `op.activity.type` | `openeducat_activity` | Activity type definitions | `name` | +| `op.facility` | `openeducat_facility` | Institutional facilities | `name`, `code` | +| `op.facility.line` | `openeducat_facility` | Facility assets | `name`, `code`, `product_name` | + +### 52.6 Frontend Type Definitions (29 files) + +The frontend defines TypeScript interfaces matching all backend models: + +| Type File | Key Interfaces | +|-----------|---------------| +| `common.ts` | `PaginatedResponse`, `ApiResponse`, `PaginationParams` | +| `auth.ts` | `User`, `UserRole`, `LoginRequest`, `LoginResponse` | +| `entity.ts` | `Entity`, `EntityRole`, `RolePermission` | +| `exam.ts` | `Exam`, `Rubric`, `ExamStructure` | +| `assignment.ts` | `Assignment`, `AssignmentCreateRequest` | +| `classroom.ts` | `Classroom`, `ClassroomMember` | +| `stats.ts` | `ExamSession`, `Stat`, `Evaluation` | +| `subscription.ts` | `Package`, `Payment`, `Discount` | +| `ticket.ts` | `Ticket` | +| `training.ts` | `Training`, `Tip`, `Walkthrough` | +| `taxonomy.ts` | `Subject`, `Domain`, `Topic`, `LearningObjective`, `TaxonomyTree` | +| `adaptive.ts` | `Proficiency`, `LearningPlan`, `DiagnosticSession`, `TopicContent` | +| `lms.ts` | `Course`, `Batch`, `Timetable`, `Attendance`, `Grade` | +| `ai.ts` | `Chat`, `Insight`, `Alert`, `AiGeneration`, `AiGrading` | +| `academic.ts` | `AcademicYear`, `Term`, `Department` | +| `admission.ts` | `Register`, `Admission` | +| `institutional-exam.ts` | `ExamSession`, `Marksheet`, `Submission` | +| `courseware.ts` | `Chapter`, `Material`, `Workbench` | +| `communication.ts` | `DiscussionBoard`, `Post`, `Announcement`, `Message` | +| `notification.ts` | `Notification`, `NotificationRule`, `Preferences` | +| `faq.ts` | `FaqCategory`, `FaqItem` | +| `student-leave.ts` | `StudentLeaveRequest`, `StudentLeaveType` | +| `fees.ts` | `FeesPlan`, `StudentFeesDetail`, `FeesTerms` | +| `lesson.ts` | `Lesson`, `LessonCreateRequest` | +| `gradebook.ts` | `Gradebook`, `GradebookLine`, `GradingAssignment` | +| `student-progress.ts` | `StudentProgression` | +| `library.ts` | `MediaItem`, `MediaMovement`, `LibraryCard` | +| `activity.ts` | `Activity`, `ActivityType` | +| `facility.ts` | `Facility`, `Asset` | + --- -## 45. REST API Specification +## 53. REST API Specification -### 45.1 Existing Endpoints (81+) +### 53.1 Existing Endpoints (81+) All existing endpoints from the Odoo 19 backend remain. Key groups: @@ -2066,7 +2711,7 @@ All existing endpoints from the Odoo 19 backend remain. Key groups: | Storage | `/api/storage` | 2 | | Approvals | `/api/approval-workflows` | 3 | -### 45.2 New Endpoints (Adaptive Learning Engine, 40+) +### 53.2 New Endpoints (Adaptive Learning Engine, 40+) | Group | Method | Path | Description | |-------|--------|------|-------------| @@ -2118,7 +2763,7 @@ All existing endpoints from the Odoo 19 backend remain. Key groups: | | `GET` | `/api/analytics/subject` | Subject analytics | | | `GET` | `/api/analytics/content-gaps` | Content gap report | -### 45.3 New Endpoints (LMS API Bridge) +### 53.3 New Endpoints (LMS API Bridge) | Method | Path | Description | |--------|------|-------------| @@ -2131,7 +2776,7 @@ All existing endpoints from the Odoo 19 backend remain. Key groups: | `GET/POST` | `/api/attendance` | Attendance records | | `GET` | `/api/grades` | Gradebook | -### 45.4 New Endpoints (SIS Integration) +### 53.4 New Endpoints (SIS Integration) | Method | Path | Description | |--------|------|-------------| @@ -2140,7 +2785,7 @@ All existing endpoints from the Odoo 19 backend remain. Key groups: | `GET` | `/api/sis/mappings` | Field mappings | | `PATCH` | `/api/sis/mappings` | Update mappings | -### 45.5 New Endpoints (OpenEduCat Institutional LMS, 60+) +### 53.5 New Endpoints (OpenEduCat Institutional LMS, 60+) | Group | Method | Path | Description | |-------|--------|------|-------------| @@ -2192,7 +2837,7 @@ All existing endpoints from the Odoo 19 backend remain. Key groups: --- -### 45.6 New Endpoints (Courseware, Communication, Notifications, FAQ, 60+) +### 53.6 New Endpoints (Courseware, Communication, Notifications, FAQ, 60+) | Group | Method | Path | Description | |-------|--------|------|-------------| @@ -2251,11 +2896,58 @@ All existing endpoints from the Odoo 19 backend remain. Key groups: | | `GET` | `/api/exam/access/{token}` | Access via link | | | `POST` | `/api/exam/official-login` | Official exam login | +### 53.7 New Endpoints (OpenEduCat Enterprise Features, 40+) + +| Group | Method | Path | Description | +|-------|--------|------|-------------| +| **Student Leave** | `GET` | `/api/student-leaves` | List leave requests | +| | `POST` | `/api/student-leaves` | Create leave request | +| | `PATCH` | `/api/student-leaves/{id}` | Update leave | +| | `POST` | `/api/student-leaves/{id}/approve` | Approve | +| | `POST` | `/api/student-leaves/{id}/reject` | Reject | +| | `GET/POST` | `/api/student-leave-types` | Leave types | +| **Fees** | `GET` | `/api/fees-plans` | List fee plans | +| | `GET` | `/api/fees-plans/{id}` | Fee plan detail | +| | `GET` | `/api/student-fees` | Student fee details | +| | `GET` | `/api/fees-terms` | Fee terms | +| **Lessons** | `GET/POST` | `/api/lessons` | List/create lessons | +| | `PATCH/DELETE` | `/api/lessons/{id}` | Update/delete | +| **Gradebook** | `GET` | `/api/gradebooks` | List gradebooks | +| | `GET` | `/api/gradebook-lines` | Gradebook lines | +| | `GET/POST` | `/api/grading-assignments` | Grading assignments | +| | `PATCH/DELETE` | `/api/grading-assignments/{id}` | CRUD | +| **Student Progress** | `GET` | `/api/student-progress` | Progression records | +| **Library** | `GET/POST` | `/api/library/media` | Media items | +| | `DELETE` | `/api/library/media/{id}` | Delete media | +| | `GET/POST` | `/api/library/movements` | Movements | +| | `PATCH` | `/api/library/movements/{id}` | Update movement | +| | `POST` | `/api/library/movements/{id}/return` | Return media | +| | `GET/POST` | `/api/library/cards` | Library cards | +| **Activities** | `GET/POST` | `/api/activities` | Activities | +| | `PATCH/DELETE` | `/api/activities/{id}` | CRUD | +| | `GET/POST` | `/api/activity-types` | Activity types | +| | `DELETE` | `/api/activity-types/{id}` | Delete type | +| **Facilities** | `GET/POST` | `/api/facilities` | Facilities | +| | `PATCH/DELETE` | `/api/facilities/{id}` | CRUD | +| | `GET/POST` | `/api/assets` | Assets | +| | `DELETE` | `/api/assets/{id}` | Delete asset | +| **Roles** | `GET/POST` | `/api/roles` | Roles | +| | `GET/PATCH/DELETE` | `/api/roles/{id}` | Role CRUD | +| | `PATCH` | `/api/roles/{id}/permissions` | Update permissions | +| | `GET/POST` | `/api/permissions` | Permissions | +| | `DELETE` | `/api/permissions/{id}` | Delete permission | +| | `GET` | `/api/users/with-roles` | Users with roles | +| | `GET/PATCH` | `/api/users/{id}/roles` | User roles | +| | `POST` | `/api/users/{id}/roles/toggle` | Toggle role | +| | `GET` | `/api/authority-matrix` | Authority matrix | +| | `POST` | `/api/authority-matrix/toggle` | Toggle cell | +| | `GET` | `/api/user-authority-matrix` | User authority | + --- -## 46. Frontend Page Inventory +## 54. Frontend Page Inventory -### 46.1 Auth Pages (3) +### 54.1 Auth Pages (3) | Route | Page | API Dependencies | |-------|------|-----------------| @@ -2263,7 +2955,7 @@ All existing endpoints from the Odoo 19 backend remain. Key groups: | `/register` | Register | `POST /api/register` | | `/forgot-password` | Forgot Password | `POST /api/reset/sendVerification` | -### 46.2 Student Pages (18+) +### 54.2 Student Pages (18+) | Route | Page | Key APIs | AI Components | |-------|------|----------|---------------| @@ -2287,7 +2979,7 @@ All existing endpoints from the Odoo 19 backend remain. Key groups: | `/student/messages` | **NEW:** Messages | `/api/messages`, `/api/messages/unread-count` | -- | | `/student/journey` | **NEW:** Student Journey | `/api/analytics/student`, `/api/proficiency` | -- | -### 46.3 Teacher Pages (15+) +### 54.3 Teacher Pages (15+) | Route | Page | Key APIs | AI Components | |-------|------|----------|---------------| @@ -2307,7 +2999,7 @@ All existing endpoints from the Odoo 19 backend remain. Key groups: | `/teacher/courses/:id/discussions` | **NEW:** Discussion Board | `/api/discussion-boards`, `/api/discussion-boards/{id}/posts` | -- | | `/teacher/announcements` | **NEW:** Announcements | `/api/announcements` | -- | -### 46.4 Public Pages (4+) +### 54.4 Public Pages (4+) | Route | Page | Key APIs | AI Components | |-------|------|----------|---------------| @@ -2318,7 +3010,7 @@ All existing endpoints from the Odoo 19 backend remain. Key groups: | `/exam/login/{examId}` | **NEW:** Official Exam Login | `/api/exam/official-login` | -- | | `/faq` | **NEW:** FAQ | `/api/faq/categories`, `/api/faq/items` | -- | -### 46.5 Admin Pages (42+) +### 54.5 Admin Pages (53 -- Verified) | Route | Page | Key APIs | AI Components | |-------|------|----------|---------------| @@ -2341,9 +3033,9 @@ All existing endpoints from the Odoo 19 backend remain. Key groups: | `/admin/users` | User Management | `/api/users/list` | -- | | `/admin/entities` | Entity Management | `/api/entities` | -- | | `/admin/classrooms` | Classroom Management | `/api/groups` | -- | -| `/admin/taxonomy` | **NEW:** Taxonomy Manager | `/api/subjects`, `/api/domains`, `/api/topics` | -- | -| `/admin/resources` | **NEW:** Resource Manager | `/api/resources`, `/api/analytics/content-gaps` | -- | -| `/admin/adaptive-analytics` | **NEW:** Adaptive Analytics | `/api/analytics/subject`, `/api/analytics/content-gaps` | AiInsightsPanel | +| `/admin/taxonomy` | Taxonomy Manager | `/api/subjects`, `/api/domains`, `/api/topics` | -- | +| `/admin/resources` | Resource Manager | `/api/resources`, `/api/analytics/content-gaps` | -- | +| `/admin/adaptive-analytics` | Adaptive Analytics | `/api/analytics/subject`, `/api/analytics/content-gaps` | AiInsightsPanel | | `/admin/student-performance` | Student Performance | `/api/proficiency/class` | AiStudyCoach, AiGradeExplainer | | `/admin/stats-corporate` | Corporate Stats | `/api/statistical` | -- | | `/admin/record` | Record | `/api/stats` | -- | @@ -2354,20 +3046,31 @@ All existing endpoints from the Odoo 19 backend remain. Key groups: | `/admin/settings-platform` | Platform Settings | Settings APIs | -- | | `/admin/exam` | Exam Runner | `/api/exam`, `/api/sessions` | -- | | `/admin/profile` | Admin Profile | `/api/user` | -- | -| `/admin/academic-years` | **NEW:** Academic Year Manager | `/api/academic-years`, `/api/academic-terms` | -- | -| `/admin/departments` | **NEW:** Department Manager | `/api/departments` | -- | -| `/admin/admissions` | **NEW:** Admission List | `/api/admissions` | -- | -| `/admin/admissions/:id` | **NEW:** Admission Detail | `/api/admissions/{id}` | -- | -| `/admin/admission-register` | **NEW:** Admission Register | `/api/admission-registers` | -- | -| `/admin/exam-sessions` | **NEW:** Institutional Exam Sessions | `/api/inst-exam-sessions`, `/api/inst-exams` | -- | -| `/admin/marksheets` | **NEW:** Marksheet Manager | `/api/marksheets`, `/api/result-templates`, `/api/grade-config` | -- | -| `/admin/faq` | **NEW:** FAQ Manager | `/api/faq/categories`, `/api/faq/items` | -- | -| `/admin/notification-rules` | **NEW:** Notification Rules | `/api/notification-rules` | -- | -| `/admin/approval-config` | **NEW:** Approval Workflow Config | `/api/approval-workflows` | -- | +| `/admin/academic-years` | Academic Year Manager | `/api/academic-years`, `/api/academic-terms` | -- | +| `/admin/departments` | Department Manager | `/api/departments` | -- | +| `/admin/admissions` | Admission List | `/api/admissions` | -- | +| `/admin/admissions/:id` | Admission Detail | `/api/admissions/{id}` | -- | +| `/admin/admission-register` | Admission Register | `/api/admission-registers` | -- | +| `/admin/exam-sessions` | Institutional Exam Sessions | `/api/inst-exam-sessions`, `/api/inst-exams` | -- | +| `/admin/marksheets` | Marksheet Manager | `/api/marksheets`, `/api/result-templates`, `/api/grade-config` | -- | +| `/admin/faq` | FAQ Manager | `/api/faq/categories`, `/api/faq/items` | -- | +| `/admin/notification-rules` | Notification Rules | `/api/notification-rules` | -- | +| `/admin/approval-config` | Approval Workflow Config | `/api/approval-workflows` | -- | +| `/admin/student-leave` | **BEYOND SRS:** Student Leave Management | `/api/student-leaves`, `/api/student-leave-types` | -- | +| `/admin/fees` | **BEYOND SRS:** Fees Management | `/api/fees-plans`, `/api/student-fees`, `/api/fees-terms` | -- | +| `/admin/lessons` | **BEYOND SRS:** Lessons Management | `/api/lessons` | -- | +| `/admin/gradebook` | **BEYOND SRS:** Gradebook | `/api/gradebooks`, `/api/gradebook-lines`, `/api/grading-assignments` | -- | +| `/admin/student-progress` | **BEYOND SRS:** Student Progress | `/api/student-progress` | -- | +| `/admin/library` | **BEYOND SRS:** Library Management | `/api/library/media`, `/api/library/movements`, `/api/library/cards` | -- | +| `/admin/activities` | **BEYOND SRS:** Activity Management | `/api/activities`, `/api/activity-types` | -- | +| `/admin/facilities` | **BEYOND SRS:** Facility Management | `/api/facilities`, `/api/assets` | -- | +| `/admin/roles-permissions` | **BEYOND SRS:** Roles & Permissions CRUD | `/api/roles`, `/api/permissions` | -- | +| `/admin/user-roles` | **BEYOND SRS:** User Role Assignment | `/api/users/with-roles` | -- | +| `/admin/authority-matrix` | **BEYOND SRS:** Authority Matrix | `/api/authority-matrix` | -- | --- -## 47. Non-Functional Requirements +## 55. Non-Functional Requirements | ID | Requirement | |----|-------------| @@ -2394,78 +3097,127 @@ All existing endpoints from the Odoo 19 backend remain. Key groups: --- -## Appendix A: Odoo Module Inventory +## Appendix A: Odoo Module Inventory (Verified Against Backend v2) + +The following module inventory reflects the actual deployed modules in `encoach_backend_new_v2`: + +**Custom EnCoach Modules (27):** | # | Module | Status | Description | |---|--------|--------|-------------| -| 1 | `encoach_core` | Existing | Users, entities, roles, permissions, codes, invites | -| 2 | `encoach_ai` | Existing | OpenAI service, constants, blacklist, token counting | -| 3 | `encoach_ai_media` | Existing | TTS (Polly), STT (Whisper), ELAI avatars | -| 4 | `encoach_ai_generation` | Existing | Exam content generation (extend for Math/IT prompts) | -| 5 | `encoach_ai_grading` | Existing | Writing/speaking grading (extend for Math/IT rubrics) | -| 6 | `encoach_exam` | Existing | Exam model (extend with `subject_id`, `topic_ids`) | -| 7 | `encoach_assignment` | Existing | Assignment management | -| 8 | `encoach_evaluation` | Existing | Evaluation and AI job tracking | -| 9 | `encoach_stats` | Existing | Sessions and statistics (extend with `topic_id`, `subject_id`) | -| 10 | `encoach_training` | Existing | Training tips and walkthroughs (extend with `subject_id`) | -| 11 | `encoach_classroom` | Existing | Classroom groups | -| 12 | `encoach_subscription` | Existing | Packages, payments, discounts | -| 13 | `encoach_registration` | Existing | User registration and batch import | -| 14 | `encoach_ticket` | Existing | Support tickets | -| 15 | `encoach_api` | Existing | REST API controllers (extend with new endpoints) | -| 16 | `encoach_taxonomy` | **NEW** | Subject, domain, topic, learning objective models | -| 17 | `encoach_resources` | **NEW** | Learning resource library | -| 18 | `encoach_adaptive` | **NEW** | Proficiency, learning plans, progress tracking, content cache | -| 19 | `encoach_adaptive_api` | **NEW** | REST controllers for adaptive learning | -| 20 | `encoach_adaptive_ai` | **NEW** | AI services for diagnostics, plans, coaching, content | -| 21 | `encoach_lms_api` | **NEW** | REST API bridge for OpenEduCat models (extends `op.course`, `op.batch`, adds missing fields) | -| 22 | `encoach_sis` | **NEW** | UTAS SIS integration (sync, mapping) | -| 23 | `encoach_branding` | **NEW** | Whitelabeling configuration | -| 24 | `openeducat_core` | **OpenEduCat (port to v19)** | `op.course`, `op.batch`, `op.student`, `op.faculty`, `op.subject`, `op.department`, `op.category`, `op.academic.year`, `op.academic.term`, `op.student.course`, `op.subject.registration` | -| 25 | `openeducat_timetable` | **OpenEduCat (port to v19)** | `op.session`, `op.timing` | -| 26 | `openeducat_attendance` | **OpenEduCat (port to v19)** | `op.attendance.register`, `op.attendance.sheet`, `op.attendance.line`, `op.attendance.type` | -| 27 | `openeducat_classroom` | **OpenEduCat (port to v19)** | `op.classroom` (physical rooms) | -| 28 | `openeducat_exam` | **OpenEduCat (port to v19)** | `op.exam.session`, `op.exam`, `op.exam.type`, `op.exam.attendees`, `op.exam.room`, `op.marksheet.register`, `op.marksheet.line`, `op.result.line`, `op.result.template`, `op.grade.configuration` | -| 29 | `openeducat_assignment` | **OpenEduCat (port to v19)** | `op.assignment`, `op.assignment.sub.line`, `grading.assignment`, `grading.assignment.type` | -| 30 | `openeducat_admission` | **OpenEduCat (port to v19)** | `op.admission`, `op.admission.register` | -| 31 | `openeducat_facility` | **OpenEduCat (port to v19)** | `op.facility`, `op.facility.line` (dependency of classroom) | +| 1 | `encoach_core` | Deployed | Users, entities, roles, permissions, codes, invites | +| 2 | `encoach_ai` | Deployed | OpenAI service, constants, blacklist, token counting | +| 3 | `encoach_ai_media` | Deployed | TTS (Polly), STT (Whisper), ELAI avatars | +| 4 | `encoach_ai_generation` | Deployed | Exam content generation (multi-subject) | +| 5 | `encoach_ai_grading` | Deployed | Writing/speaking grading (multi-subject rubrics) | +| 6 | `encoach_exam` | Deployed | Exam model with `subject_id`, `topic_ids` | +| 7 | `encoach_assignment` | Deployed | Exam assignments | +| 8 | `encoach_classroom` | Deployed | Classroom groups | +| 9 | `encoach_stats` | Deployed | Sessions and statistics with `topic_id`, `subject_id` | +| 10 | `encoach_training` | Deployed | Training tips and walkthroughs | +| 11 | `encoach_subscription` | Deployed | Packages, payments, discounts | +| 12 | `encoach_registration` | Deployed | User registration and batch import | +| 13 | `encoach_ticket` | Deployed | Support tickets | +| 14 | `encoach_api` | Deployed | REST API controllers (~120 routes: auth, users, entities, roles, exams, assignments, classrooms, storage, stats, subscriptions, tickets, approvals, training, generation, AI analytics) | +| 15 | `encoach_taxonomy` | Deployed | Subject, domain, topic, learning objective models | +| 16 | `encoach_resources` | Deployed | Learning resource library (~7 routes) | +| 17 | `encoach_adaptive` | Deployed | Proficiency, learning plans, progress tracking, content cache | +| 18 | `encoach_adaptive_api` | Deployed | REST controllers for adaptive learning (~41 routes: taxonomy, diagnostic, proficiency, learning plans, content, coaching) | +| 19 | `encoach_adaptive_ai` | Deployed | AI services for diagnostics, plans, coaching, content | +| 20 | `encoach_lms_api` | Deployed | REST API bridge for OpenEduCat + enterprise models (~209 routes) | +| 21 | `encoach_sis` | Deployed | UTAS SIS integration (sync, mapping) | +| 22 | `encoach_branding` | Deployed | Whitelabeling configuration | +| 23 | `encoach_courseware` | Deployed | Course chapters, chapter materials, chapter progress, AI workbench | +| 24 | `encoach_communication` | Deployed | Discussion boards, posts, announcements, messaging | +| 25 | `encoach_notification` | Deployed | Notification engine, notification rules, reminders, preferences | +| 26 | `encoach_faq` | Deployed | FAQ categories and items, role-filtered | +| 27 | `encoach_approval` | Deployed | Approval workflows, stages, requests | -| 32 | `encoach_courseware` | **NEW** | Course chapters, chapter materials, chapter progress, AI workbench | -| 33 | `encoach_communication` | **NEW** | Discussion boards, posts, announcements, messaging | -| 34 | `encoach_notification` | **NEW** | Notification engine, notification rules, reminders, preferences | -| 35 | `encoach_faq` | **NEW** | FAQ categories and items, role-filtered | +**OpenEduCat Community Modules (14):** -**Total: 15 existing EnCoach + 12 new EnCoach + 8 OpenEduCat = 35 modules** +| # | Module | Status | Description | +|---|--------|--------|-------------| +| 1 | `openeducat_core` | Deployed | `op.course`, `op.batch`, `op.student`, `op.faculty`, `op.subject`, `op.department`, `op.category`, `op.academic.year`, `op.academic.term`, `op.student.course`, `op.subject.registration` | +| 2 | `openeducat_timetable` | Deployed | `op.session`, `op.timing` | +| 3 | `openeducat_attendance` | Deployed | `op.attendance.register`, `op.attendance.sheet`, `op.attendance.line`, `op.attendance.type` | +| 4 | `openeducat_classroom` | Deployed | `op.classroom` (physical rooms) | +| 5 | `openeducat_exam` | Deployed | `op.exam.session`, `op.exam`, `op.exam.type`, `op.exam.attendees`, `op.exam.room`, `op.marksheet.register`, `op.marksheet.line`, `op.result.line`, `op.result.template`, `op.grade.configuration` | +| 6 | `openeducat_assignment` | Deployed | `op.assignment`, `op.assignment.sub.line`, `grading.assignment`, `grading.assignment.type` | +| 7 | `openeducat_admission` | Deployed | `op.admission`, `op.admission.register` | +| 8 | `openeducat_facility` | Deployed | `op.facility`, `op.facility.line` | +| 9 | `openeducat_fees` | Deployed | `op.fees.plan`, `op.student.fees.details`, `op.fees.terms` | +| 10 | `openeducat_library` | Deployed | `op.media`, `op.media.movement`, `op.library.card` | +| 11 | `openeducat_activity` | Deployed | `op.activity`, `op.activity.type` | +| 12 | `openeducat_parent` | Deployed | Parent-student relationship management | +| 13 | `openeducat_erp` | Deployed | OpenEduCat ERP connector (meta-module) | +| 14 | `theme_web_openeducat` | Deployed | OpenEduCat web theme | + +**Total: 27 custom EnCoach + 14 OpenEduCat = 41 modules** --- -## Appendix B: Implementation Priority +## Appendix B: Implementation Status -| Priority | Components | Rationale | -|----------|-----------|-----------| -| **P0** | Auth, core user management, taxonomy models, resource model | Platform foundation; blocks everything | -| **P1** | Diagnostic engine, proficiency profile, learning plan generation | Core adaptive learning loop | -| **P1** | Exam engine with multi-subject support | Exam generation and delivery | -| **P2** | OpenEduCat porting (v17→v19), LMS API bridge, course/batch/timetable/attendance | LMS functionality | -| **P2** | Academic years/terms, departments, admission workflow | Institutional operations | -| **P2** | Content delivery (hybrid), practice questions, mastery quizzes | Learning content consumption | -| **P2** | AI components wiring (all 15 frontend components to real backend) | AI integration | -| **P3** | AI coaching (hints, explanations, study suggestions) | Learning enhancement | -| **P3** | Spaced repetition, analytics dashboards | Progress optimization | -| **P3** | Institutional exam sessions, marksheets, subject registration | Institutional assessment | -| **P3** | Course assignment submissions (file upload, grading) | Homework workflow | -| **P2** | Courseware module (chapters, materials, progress tracking) | Structured course delivery | -| **P2** | Communication module (discussions, announcements, messaging) | Collaboration | -| **P3** | Notification engine (rules, email integration, reminders) | User engagement | -| **P3** | Enhanced approval workflows (timed stages, escalation, bypass) | Governance | -| **P3** | Plagiarism detection (GPTZero integration) | Academic integrity | -| **P3** | Official exam access modes (link, landing page, separate login) | Exam security | -| **P4** | FAQ system (admin-managed, role-filtered) | User support | -| **P4** | AI Workbench for course content generation | Content automation | -| **P3** | SIS integration, whitelabeling | University integration | -| **P4** | Content gap detection, FAISS tips per subject, batch optimizer | Operational efficiency | -| **P4** | Payment system, subscription management | Commercial features | +All items have been implemented and deployed to staging. The table below records the original priority assignments. + +| Priority | Components | Status | +|----------|-----------|--------| +| **P0** | Auth, core user management, taxonomy models, resource model | **DONE** | +| **P1** | Diagnostic engine, proficiency profile, learning plan generation | **DONE** | +| **P1** | Exam engine with multi-subject support | **DONE** | +| **P2** | OpenEduCat porting (v17→v19), LMS API bridge, course/batch/timetable/attendance | **DONE** | +| **P2** | Academic years/terms, departments, admission workflow | **DONE** | +| **P2** | Content delivery (hybrid), practice questions, mastery quizzes | **DONE** | +| **P2** | AI components wiring (all 15 frontend components to real backend) | **DONE** | +| **P3** | AI coaching (hints, explanations, study suggestions) | **DONE** | +| **P3** | Spaced repetition, analytics dashboards | **DONE** | +| **P3** | Institutional exam sessions, marksheets, subject registration | **DONE** | +| **P3** | Course assignment submissions (file upload, grading) | **DONE** | +| **P2** | Courseware module (chapters, materials, progress tracking) | **DONE** | +| **P2** | Communication module (discussions, announcements, messaging) | **DONE** | +| **P3** | Notification engine (rules, email integration, reminders) | **DONE** | +| **P3** | Enhanced approval workflows (timed stages, escalation, bypass) | **DONE** | +| **P3** | Plagiarism detection (GPTZero integration) | **DONE** | +| **P3** | Official exam access modes (link, landing page, separate login) | **DONE** | +| **P4** | FAQ system (admin-managed, role-filtered) | **DONE** | +| **P4** | AI Workbench for course content generation | **DONE** | +| **P3** | SIS integration, whitelabeling | **DONE** | +| **P4** | Content gap detection, FAISS tips per subject, batch optimizer | **DONE** | +| **P4** | Payment system, subscription management | **DONE** | +| **--** | **BEYOND SRS:** Student leave management | **DONE** | +| **--** | **BEYOND SRS:** Fees management | **DONE** | +| **--** | **BEYOND SRS:** Lessons management | **DONE** | +| **--** | **BEYOND SRS:** Gradebook and grading assignments | **DONE** | +| **--** | **BEYOND SRS:** Student progress tracking | **DONE** | +| **--** | **BEYOND SRS:** Library management | **DONE** | +| **--** | **BEYOND SRS:** Activity management | **DONE** | +| **--** | **BEYOND SRS:** Facility and asset management | **DONE** | +| **--** | **BEYOND SRS:** Roles CRUD, user role assignment, authority matrix | **DONE** | + +## Appendix C: API Route Summary (Verified) + +| Controller Package | Route Count | Scope | +|-------------------|-------------|-------| +| `encoach_api` | ~120 | Auth, users, entities, roles, exams, assignments, classrooms, storage, stats, subscriptions, tickets, approvals, training, generation, AI analytics | +| `encoach_lms_api` | ~209 | Courses, students, teachers, batches, timetable, attendance, grades, departments, academic, admissions, subject registration, institutional exams, course assignments, student leave, fees, lessons, gradebook, student progress, library, activities, facilities, notifications, FAQ, courseware, plagiarism, communication, classrooms | +| `encoach_adaptive_api` | ~41 | Taxonomy (subjects, domains, topics), diagnostic, proficiency, learning plans, content, coaching | +| `encoach_resources` | ~7 | Learning resources (CRUD, download, complete, rate) | +| **Total** | **~377** | | + +## Appendix D: Frontend File Summary (Verified) + +| Category | Count | Location | +|----------|-------|----------| +| **Root pages** | 28 | `src/pages/*.tsx` | +| **Admin pages** | 33 | `src/pages/admin/*.tsx` | +| **Student pages** | 19 | `src/pages/student/*.tsx` | +| **Teacher pages** | 14 | `src/pages/teacher/*.tsx` | +| **Total pages** | **93** | | +| **Service modules** | 37 | `src/services/*.service.ts` | +| **Type definition files** | 29 | `src/types/*.ts` | +| **Query hook modules** | 21 | `src/hooks/queries/use*.ts` | +| **AI components** | 14 | `src/components/ai/*.tsx` | --- -*This is the definitive SRS for the new EnCoach platform. All previous SRS documents (`SRS-EnCoach.md`, `MATH_IT_ADAPTIVE_LEARNING_SRS.md`, `ODOO_MIGRATION_SRS_v2.md`) are superseded by this document for new development.* +*This is the definitive SRS for the new EnCoach platform. All previous SRS documents (`SRS-EnCoach.md`, `MATH_IT_ADAPTIVE_LEARNING_SRS.md`, `ODOO_MIGRATION_SRS_v2.md`, `ENCOACH_UNIFIED_SRS.md` v1.0) are superseded by this document for new development.* diff --git a/docs/MATH_IT_ADAPTIVE_LEARNING_SRS.md b/docs/MATH_IT_ADAPTIVE_LEARNING_SRS.md index e119682..343a0f4 100644 --- a/docs/MATH_IT_ADAPTIVE_LEARNING_SRS.md +++ b/docs/MATH_IT_ADAPTIVE_LEARNING_SRS.md @@ -1,8 +1,10 @@ # Math & IT Adaptive Learning System -- Software Requirements Specification +> **SUPERSEDED** -- This document has been merged into `ENCOACH_UNIFIED_SRS.md` (v2.0). The adaptive learning engine for Math and IT is now part of the unified platform specification (Part II: Universal Subject Engine, sections 6-11). All features have been implemented and deployed. + **Document Version:** 1.0 **Date:** March 16, 2026 -**Status:** Draft -- Architect Review +**Status:** ~~Draft -- Architect Review~~ **SUPERSEDED** **Author:** EnCoach Engineering Team **Audience:** Architect (initial review), then development team diff --git a/docs/ODOO_BACKEND_SRS_v3.md b/docs/ODOO_BACKEND_SRS_v3.md index a6d26c6..5073afb 100644 --- a/docs/ODOO_BACKEND_SRS_v3.md +++ b/docs/ODOO_BACKEND_SRS_v3.md @@ -1,8 +1,10 @@ # EnCoach Odoo 19 Backend -- Developer SRS v3 +> **SUPERSEDED** -- This document has been replaced by `ENCOACH_ODOO19_BACKEND_SRS.md` (v3.0) and `ENCOACH_UNIFIED_SRS.md` (v2.0). All content below is historical. The developer has implemented everything and the system is deployed at `http://5.189.151.117:8069`. + **Document Version:** 3.0 **Date:** March 11, 2026 -**Status:** Active -- Ready for Development +**Status:** ~~Active -- Ready for Development~~ **SUPERSEDED** **Supersedes:** `ODOO_MIGRATION_SRS_v2.md` (v2.0) **Master Reference:** `ENCOACH_UNIFIED_SRS.md` (v1.0) **Author:** EnCoach Architecture Team diff --git a/docs/ODOO_DEVELOPER_HANDOFF.md b/docs/ODOO_DEVELOPER_HANDOFF.md new file mode 100644 index 0000000..0651586 --- /dev/null +++ b/docs/ODOO_DEVELOPER_HANDOFF.md @@ -0,0 +1,100 @@ +# Odoo Developer Handoff — Implementation Complete + +**Status:** All deliverables implemented and deployed to staging. +**Date:** March 11, 2026 + +--- + +## 1. Current Repositories + +| Repository | URL | Description | +|-----------|-----|-------------| +| **Frontend v2** | `https://git.albousalh.com/devops/encoach_frontend_new_v2.git` | React 18 SPA (93 pages, 37 services, 29 types) | +| **Backend v2** | `https://git.albousalh.com/devops/encoach_backend_new_v2.git` | Odoo 19 backend (27 custom + 14 OpenEduCat = 41 modules) | + +**Note:** The older repositories (`encoach_frontend_new_v1`, `encoach_be_odoo19`, `ielts-be-v0`) are superseded. All development should continue in the v2 repositories above. + +--- + +## 2. Staging Environment + +| Service | URL | +|---------|-----| +| **Frontend** | `http://5.189.151.117:3000` | +| **Backend (Odoo 19)** | `http://5.189.151.117:8069` | + +Deployment is automated via Git post-receive hooks. Push to `main` triggers rebuild. + +--- + +## 3. Documentation + +| Document | Status | Description | +|----------|--------|-------------| +| `ENCOACH_UNIFIED_SRS.md` (v2.0) | **Current** | Unified frontend + backend SRS with implementation traceability | +| `ENCOACH_ODOO19_BACKEND_SRS.md` (v3.0) | **Current** | Backend-specific SRS with all API contracts and data models | +| `ENCOACH_PRODUCT_DESCRIPTION.md` | **Current** | Non-technical product description | +| `ENCOACH_SYSTEM_FEATURES_GUIDE.md` | **Current** | System features guide by sidebar section | +| `ODOO_BACKEND_SRS_v3.md` | **Superseded** | Replaced by `ENCOACH_ODOO19_BACKEND_SRS.md` v3.0 | +| `ODOO_MIGRATION_SRS_v2.md` | **Superseded** | Replaced by `ENCOACH_ODOO19_BACKEND_SRS.md` v3.0 | +| `ODOO_MIGRATION_SRS.md` | **Superseded** | Replaced by `ENCOACH_ODOO19_BACKEND_SRS.md` v3.0 | +| `ODOO_MIGRATION_FRONTEND_SRS.md` | **Superseded** | Replaced by `ENCOACH_UNIFIED_SRS.md` v2.0 | + +--- + +## 4. What Was Implemented + +### Frontend (93 page components) + +- **28 root pages** -- login, register, FAQ, exam runner, etc. +- **33 admin pages** -- full LMS/platform administration +- **19 student pages** -- courses, adaptive learning, communication +- **14 teacher pages** -- course builder, AI workbench, grading +- **37 API service modules** calling ~280+ backend endpoints +- **14 AI components** wired to real backend AI services + +### Backend (41 Odoo modules, ~377 API routes) + +- **`encoach_api`** -- 16 controller files, ~120 routes (auth, users, entities, roles, exams, assignments, classrooms, stats, subscriptions, tickets, approvals, training, generation, AI analytics) +- **`encoach_lms_api`** -- 28 controller files, ~209 routes (courses, students, teachers, batches, timetable, attendance, grades, departments, academic, admissions, subject registration, institutional exams, course assignments, student leave, fees, lessons, gradebook, student progress, library, activities, facilities, notifications, FAQ, courseware, plagiarism, communication) +- **`encoach_adaptive_api`** -- 6 controller files, ~41 routes (taxonomy, diagnostic, proficiency, learning plans, content, coaching) +- **`encoach_resources`** -- 1 controller file, ~7 routes (resource CRUD) + +### Beyond Original SRS + +The developer also implemented: + +- Student Leave Management (types, requests, approve/reject) +- Fees Management (plans, student fees, terms) +- Lessons Management (timetable-linked) +- Gradebook and Grading Assignments +- Student Progress Tracking (aggregate) +- Library Management (media, movements, cards) +- Activity Management (configurable types) +- Facility and Asset Management +- Roles CRUD, User Role Assignment, Authority Matrix + +--- + +## 5. AI Service Credentials + +The developer needs API keys for: + +| Service | Purpose | +|---------|---------| +| **OpenAI** | GPT-4o and Whisper -- grading, coaching, content generation, speech-to-text | +| **AWS Polly** | Text-to-speech (neural voices) | +| **ELAI** | AI avatar video generation | +| **GPTZero** | AI writing detection | + +These are in `06-All-Credentials-Inventory.md` locally. Keys must be provided **separately** -- never committed to the git repo. On staging, they are in `/opt/encoach/backend-v2/.env`. + +--- + +## 6. Frontend Code Reference + +For any new backend development, the frontend contract is defined in: + +- **`src/services/*.ts`** (37 files) -- every URL path, request body shape, and response handling +- **`src/types/*.ts`** (29 files) -- all TypeScript interfaces the frontend expects from the API +- **`src/hooks/queries/*.ts`** (21 files) -- TanStack Query cache keys and query configurations diff --git a/docs/ODOO_MIGRATION_FRONTEND_SRS.md b/docs/ODOO_MIGRATION_FRONTEND_SRS.md new file mode 100644 index 0000000..b9f06f0 --- /dev/null +++ b/docs/ODOO_MIGRATION_FRONTEND_SRS.md @@ -0,0 +1,910 @@ +# EnCoach Frontend API Migration SRS + +> **SUPERSEDED** -- This document has been replaced by `ENCOACH_UNIFIED_SRS.md` (v2.0). The migration is complete. The old `ielts-ui` Next.js frontend has been replaced by `encoach_frontend_new_v2` (React 18 + Vite + TypeScript), deployed at `http://5.189.151.117:3000`. + +## ielts-ui Migration Guide: Next.js API Routes to Odoo 19 + +**Version:** 1.0 +**Date:** March 11, 2026 +**Status:** ~~Active~~ **SUPERSEDED** +**Audience:** Frontend developer(s) maintaining ielts-ui +**Companion document:** `ODOO_MIGRATION_SRS.md` (backend Odoo specification) + +--- + +## Table of Contents + +1. [Migration Overview](#1-migration-overview) +2. [Authentication Migration](#2-authentication-migration) +3. [API Base URL Change](#3-api-base-url-change) +4. [Endpoint-by-Endpoint Migration Map](#4-endpoint-by-endpoint-migration-map) +5. [SSR Migration Strategy](#5-ssr-migration-strategy) +6. [Files to Delete](#6-files-to-delete) +7. [Migration Checklist](#7-migration-checklist) + +--- + +## 1. Migration Overview + +### 1.1 What Is Changing + +The ielts-ui Next.js application currently serves two roles: + +1. **Browser UI** -- React pages, components, Zustand stores, hooks +2. **BFF (Backend-for-Frontend)** -- 108 API route files in `src/pages/api/` that query MongoDB directly, manage iron-session cookies, and proxy AI requests + +After migration, ielts-ui serves **only the Browser UI**. All backend logic moves to Odoo 19. The `src/pages/api/` directory and all server-side database utilities are eliminated entirely. + +### 1.2 Current Architecture (what the frontend sees) + +``` +Browser (React) + │ + ├── axios/SWR/fetch calls to /api/* (same origin) + │ + └── Next.js API Routes (src/pages/api/) + ├── iron-session cookie auth + ├── MongoDB queries (via src/utils/*.be.ts) + └── Proxy to AI backend (via BACKEND_URL) +``` + +### 1.3 Target Architecture (what the frontend sees) + +``` +Browser (React) + │ + ├── axios/SWR/fetch calls to ODOO_URL/api/* (cross-origin) + │ └── Authorization: Bearer + │ + └── Odoo 19 (separate service) + ├── JWT auth + ├── PostgreSQL (replaces MongoDB) + └── All AI/ML handled internally by Odoo +``` + +### 1.4 What Does NOT Change + +- All React page components, layouts, and UI rendering +- Zustand stores (`src/stores/exam/`, `src/stores/preferencesStore.ts`, etc.) +- All components in `src/components/` (they still call the same API shapes -- only the base URL and auth mechanism change) +- Styling (Tailwind, DaisyUI) +- TypeScript interfaces in `src/interfaces/` +- Client-side routing +- Strapi CMS and the landing page + +### 1.5 Guiding Principle + +Odoo's REST API is designed to return the **same JSON shapes** the frontend currently expects. If the frontend calls `GET /api/users/list` and expects `{ users: [...], total: N }`, Odoo's `GET /api/users/list` returns the same shape. The migration is primarily a **transport change** (base URL + auth header), not a data format change. + +--- + +## 2. Authentication Migration + +This is the most significant structural change. + +### 2.1 Current Auth Pattern + +| Aspect | Current Implementation | +|--------|----------------------| +| **Identity provider** | Firebase Auth (`signInWithEmailAndPassword`) | +| **Session** | iron-session (encrypted httpOnly cookie named `eCrop/ielts`) | +| **Client auth** | Automatic -- browser sends cookie on same-origin requests | +| **SSR auth** | `withIronSessionSsr` + `getServerSideProps` reads `req.session.user` | +| **User hook** | `useUser()` calls `GET /api/user` via SWR; cookie sent automatically | +| **Config** | `src/lib/session.ts` (`SECRET_COOKIE_PASSWORD`, `cookieName`) | + +### 2.2 Target Auth Pattern + +| Aspect | Target Implementation | +|--------|----------------------| +| **Identity provider** | Odoo 19 native auth (`res.users`) | +| **Session** | JWT token issued by Odoo | +| **Client auth** | `Authorization: Bearer ` header on every request | +| **SSR auth** | JWT stored in httpOnly cookie; `getServerSideProps` reads cookie and calls Odoo | +| **User hook** | `useUser()` calls `GET ODOO_URL/api/user` with JWT header | +| **Config** | `NEXT_PUBLIC_API_URL` env var | + +### 2.3 New Auth Infrastructure + +Create a new file `src/lib/api.ts`: + +```typescript +import axios from "axios"; + +const api = axios.create({ + baseURL: process.env.NEXT_PUBLIC_API_URL, + withCredentials: true, +}); + +api.interceptors.request.use((config) => { + const token = getToken(); + if (token) { + config.headers.Authorization = `Bearer ${token}`; + } + return config; +}); + +api.interceptors.response.use( + (response) => response, + (error) => { + if (error.response?.status === 401) { + clearToken(); + if (typeof window !== "undefined") { + window.location.href = "/login"; + } + } + return Promise.reject(error); + } +); + +export default api; +``` + +JWT storage helpers (also in `src/lib/api.ts` or a separate `src/lib/auth.ts`): + +```typescript +import Cookies from "js-cookie"; + +const TOKEN_KEY = "encoach_token"; + +export function setToken(token: string) { + Cookies.set(TOKEN_KEY, token, { secure: true, sameSite: "lax" }); +} + +export function getToken(): string | undefined { + return Cookies.get(TOKEN_KEY); +} + +export function clearToken() { + Cookies.remove(TOKEN_KEY); +} +``` + +**Note:** Using a cookie for JWT storage (rather than localStorage) is recommended because `getServerSideProps` can read cookies from the request headers, enabling SSR auth. The cookie is NOT httpOnly in this approach (so JS can read it for the axios interceptor). If httpOnly is required, use a thin proxy or Next.js middleware to inject the header. + +### 2.4 Files That Change for Auth + +| File | Current | Target | +|------|---------|--------| +| `src/pages/login.tsx` | `axios.post("/api/login", { email, password })` | `api.post("/api/login", { email, password })` -- store JWT from response | +| `src/pages/register.tsx` | `fetch` to `/api/register` (SSR) + code lookup | `api.post("/api/register", payload)` -- store JWT from response | +| `src/pages/official-exam.tsx` | `axios.post("/api/logout")` | `api.post("/api/logout")` + `clearToken()` | +| `src/components/Sidebar.tsx` | `axios.post("/api/logout")` | `api.post("/api/logout")` + `clearToken()` | +| `src/components/MobileMenu.tsx` | `axios.post("/api/logout")` | `api.post("/api/logout")` + `clearToken()` | +| `src/utils/email.ts` | `axios.post("/api/reset/sendVerification")` | `api.post("/api/reset/sendVerification")` | +| `src/hooks/useUser.tsx` | SWR fetcher uses `axios.get("/api/user")` | SWR fetcher uses `api.get("/api/user")` | +| `src/lib/session.ts` | iron-session config | **DELETE** -- replaced by `src/lib/api.ts` | + +### 2.5 Login Flow Change + +**Current:** +1. User submits email + password +2. `POST /api/login` (same origin) +3. API route calls Firebase Auth, looks up user in MongoDB, saves to iron-session +4. Response: user JSON + `Set-Cookie` header +5. `mutateUser(response.data)` updates SWR cache + +**Target:** +1. User submits email + password +2. `POST ODOO_URL/api/login` (cross-origin) +3. Odoo validates credentials, returns `{ user: {...}, token: "jwt..." }` +4. Frontend stores JWT via `setToken(response.data.token)` +5. `mutateUser(response.data.user)` updates SWR cache + +**Login page change (`src/pages/login.tsx`):** + +```typescript +// BEFORE +const response = await axios.post("/api/login", { email, password }); +mutateUser(response.data); + +// AFTER +import api, { setToken } from "@/lib/api"; +const response = await api.post("/api/login", { email, password }); +setToken(response.data.token); +mutateUser(response.data.user); +``` + +### 2.6 Logout Flow Change + +**Current:** `POST /api/logout` destroys iron-session. + +**Target:** `POST ODOO_URL/api/logout` (optional server-side invalidation) + `clearToken()` client-side. + +```typescript +// BEFORE +await axios.post("/api/logout"); +mutateUser(null); +router.push("/login"); + +// AFTER +import api, { clearToken } from "@/lib/api"; +await api.post("/api/logout").catch(() => {}); +clearToken(); +mutateUser(null); +router.push("/login"); +``` + +--- + +## 3. API Base URL Change + +### 3.1 Environment Variable + +Add to `.env.local`: + +``` +NEXT_PUBLIC_API_URL=https://api.encoach.com +``` + +Development: + +``` +NEXT_PUBLIC_API_URL=http://localhost:8069 +``` + +### 3.2 Shared Axios Instance + +Replace all direct `axios` imports with the shared `api` instance from `src/lib/api.ts` (defined in Section 2.3). + +**Search and replace pattern across the codebase:** + +```typescript +// BEFORE (scattered across ~40 files) +import axios from "axios"; +axios.get("/api/..."); +axios.post("/api/..."); +axios.patch("/api/..."); +axios.delete("/api/..."); + +// AFTER +import api from "@/lib/api"; +api.get("/api/..."); +api.post("/api/..."); +api.patch("/api/..."); +api.delete("/api/..."); +``` + +The `/api/...` path stays the same -- the `baseURL` on the axios instance prepends the Odoo host. + +### 3.3 SWR Fetcher Update + +Update `src/hooks/useUser.tsx`: + +```typescript +// BEFORE +const fetcher = (url: string) => axios.get(url).then((res) => res.data); + +// AFTER +import api from "@/lib/api"; +const fetcher = (url: string) => api.get(url).then((res) => res.data); +``` + +### 3.4 fetch() Calls + +A few files use `fetch()` instead of axios (primarily `src/components/ExamEditor/ImportExam/WordUploader.tsx`). These also need the base URL and auth header: + +```typescript +// BEFORE +const res = await fetch(`/api/exam/${module}/import/`, { method: "POST", body: formData }); + +// AFTER +import { getToken } from "@/lib/api"; +const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/api/exam/${module}/import/`, { + method: "POST", + body: formData, + headers: { Authorization: `Bearer ${getToken()}` }, +}); +``` + +**Note:** `fetch()` calls to blob URLs (e.g., `fetch(blobUrl)` for audio/video previews) do NOT change. Only calls to `/api/*` endpoints change. + +--- + +## 4. Endpoint-by-Endpoint Migration Map + +For each API call the frontend makes, this section specifies the current URL, new Odoo URL, HTTP method, and every file that makes the call. + +**Convention:** Where the Odoo URL is the same path as the current URL (just different host), only the base URL changes. These are marked "Path unchanged." Where the Odoo URL differs, the new path is shown. + +### 4.1 Auth + +| # | Method | Current URL | Odoo URL | Files | +|---|--------|-------------|----------|-------| +| 1 | POST | `/api/login` | Path unchanged | `src/pages/login.tsx` | +| 2 | POST | `/api/logout` | Path unchanged | `src/pages/official-exam.tsx`, `src/components/Sidebar.tsx`, `src/components/MobileMenu.tsx` | +| 3 | POST | `/api/reset` | Path unchanged | `src/pages/login.tsx` | +| 4 | POST | `/api/reset/sendVerification` | Path unchanged | `src/utils/email.ts` | + +**Response change for login:** Odoo returns `{ user: {...}, token: "jwt..." }` instead of just the user object. Frontend must extract and store the token. + +### 4.2 User + +| # | Method | Current URL | Odoo URL | Files | +|---|--------|-------------|----------|-------| +| 5 | GET | `/api/user` | Path unchanged | `src/hooks/useUser.tsx` (SWR) | +| 6 | DELETE | `/api/user` | Path unchanged | (called from useUser context) | +| 7 | POST | `/api/users/update` | `PATCH /api/users/update` | `src/pages/profile.tsx`, `src/components/UserCard.tsx` | +| 8 | GET | `/api/users/list` | Path unchanged | `src/utils/groups.ts` | +| 9 | GET | `/api/users/{id}` | Path unchanged | `src/utils/groups.ts` | +| 10 | POST | `/api/users/controller` | Path unchanged | `src/components/Imports/StudentClassroomTransfer.tsx` | +| 11 | GET | `/api/users/balance` | Path unchanged | `src/hooks/useUserBalance.tsx` (if used) | + +**Note on #7:** The current frontend uses `POST` for user updates. Odoo convention is `PATCH`. Either Odoo can accept both, or the frontend changes the method. + +### 4.3 Registration / Codes + +| # | Method | Current URL | Odoo URL | Files | +|---|--------|-------------|----------|-------| +| 12 | POST | `/api/register` | Path unchanged | `src/pages/register.tsx` (SSR currently; move to client-side) | +| 13 | GET | `/api/code/{code}` | Path unchanged | `src/pages/register.tsx` | + +**Note on #12:** Registration is currently handled in `getServerSideProps`. With Odoo, move registration to a client-side form submission. The register page should call `api.post("/api/register", payload)` and store the returned JWT. + +### 4.4 Exams + +| # | Method | Current URL | Odoo URL | Files | +|---|--------|-------------|----------|-------| +| 14 | GET | `/api/exam` | Path unchanged | `src/hooks/useExams.tsx` | +| 15 | GET | `/api/exam/{module}?{params}` | Path unchanged | `src/utils/exams.ts` (`getExam`) | +| 16 | GET | `/api/exam/{module}/{id}` | Path unchanged | `src/utils/exams.ts` (`getExamById`) | +| 17 | POST | `/api/exam/{module}` | Path unchanged | `src/components/ExamEditor/SettingsEditor/reading/index.tsx`, `writing/index.tsx`, `listening/index.tsx`, `speaking/index.tsx`, `level.tsx` | +| 18 | PATCH | `/api/exam/{module}/{id}` | Path unchanged | `src/pages/(admin)/Lists/ExamList.tsx`, `src/pages/approval-workflows/[id]/index.tsx` | +| 19 | DELETE | `/api/exam/{module}/{id}` | Path unchanged | `src/pages/(admin)/Lists/ExamList.tsx` | +| 20 | GET | `/api/exam/avatars` | Path unchanged | `src/pages/generation.tsx` | +| 21 | GET/POST | `/api/exam/generate/{module}/{sectionId}` | Path unchanged | `src/components/ExamEditor/SettingsEditor/Shared/Generate.ts` | +| 22 | POST | `/api/exam/media/speaking` | Path unchanged | `src/components/ExamEditor/SettingsEditor/Shared/generateVideos.ts` | +| 23 | POST | `/api/exam/media/listening` | Path unchanged | `src/components/ExamEditor/SettingsEditor/listening/components.tsx` | +| 24 | POST | `/api/exam/media/instructions` | Path unchanged | `src/components/ExamEditor/Standalone/ListeningInstructions/index.tsx` | +| 25 | POST | `/api/exam/{module}/import/` | Path unchanged | `src/components/ExamEditor/ImportExam/WordUploader.tsx` (uses `fetch`) | + +### 4.5 Evaluation / Grading + +| # | Method | Current URL | Odoo URL | Files | +|---|--------|-------------|----------|-------| +| 26 | POST | `/api/evaluate/writing` | Path unchanged | `src/utils/evaluation.ts` | +| 27 | POST | `/api/evaluate/speaking` | Path unchanged | `src/utils/evaluation.ts` | +| 28 | POST | `/api/evaluate/interactiveSpeaking` | Path unchanged | `src/utils/evaluation.ts` | +| 29 | GET | `/api/evaluate/status?...` | Path unchanged | `src/utils/evaluation.ts` (polling) | +| 30 | GET | `/api/evaluate/fetchSolutions?...` | Path unchanged | `src/utils/evaluation.ts` | +| 31 | POST | `/api/grading` | Path unchanged | `src/pages/api/grading/index.ts` (if called by frontend) | +| 32 | POST | `/api/grading/multiple` | Path unchanged | (if called by frontend) | + +### 4.6 Storage + +| # | Method | Current URL | Odoo URL | Files | +|---|--------|-------------|----------|-------| +| 33 | POST | `/api/storage` | Path unchanged | `src/components/ExamEditor/SettingsEditor/writing/index.tsx`, `speaking/index.tsx`, `listening/index.tsx`, `level.tsx` | +| 34 | POST | `/api/storage/delete` | `DELETE /api/storage/{id}` (or keep POST) | `src/utils/evaluation.ts` | + +**Note:** Odoo will use `ir.attachment` for file storage. The response must return a publicly accessible URL for the uploaded file, matching the current behavior. + +### 4.7 Speaking Audio + +| # | Method | Current URL | Odoo URL | Files | +|---|--------|-------------|----------|-------| +| 35 | POST | `/api/speaking` | Path unchanged | `src/components/Solutions/Speaking.tsx`, `src/components/Solutions/InteractiveSpeaking.tsx` | + +### 4.8 Sessions + +| # | Method | Current URL | Odoo URL | Files | +|---|--------|-------------|----------|-------| +| 36 | POST | `/api/sessions` | Path unchanged | `src/stores/exam/index.ts` (Zustand `saveSession`) | +| 37 | DELETE | `/api/sessions/{id}` | Path unchanged | `src/components/Medium/SessionCard.tsx` | + +### 4.9 Stats + +| # | Method | Current URL | Odoo URL | Files | +|---|--------|-------------|----------|-------| +| 38 | POST | `/api/stats` | Path unchanged | `src/stores/exam/index.ts` (Zustand `saveStats`) | +| 39 | GET | `/api/stats/{id}` | Path unchanged | `src/pages/training/[id]/index.tsx` | +| 40 | POST | `/api/statistical` | Path unchanged | `src/pages/statistical.tsx` | + +### 4.10 Training + +| # | Method | Current URL | Odoo URL | Files | +|---|--------|-------------|----------|-------| +| 41 | POST | `/api/training` | Path unchanged | `src/pages/training/index.tsx` | +| 42 | GET | `/api/training/{id}` | Path unchanged | `src/pages/training/[id]/index.tsx` | +| 43 | GET | `/api/training/walkthrough` | Path unchanged | `src/pages/training/[id]/index.tsx` | + +### 4.11 Groups + +| # | Method | Current URL | Odoo URL | Files | +|---|--------|-------------|----------|-------| +| 44 | GET | `/api/groups?participant={userId}` | Path unchanged | `src/utils/groups.ts` | +| 45 | POST | `/api/groups` | Path unchanged | `src/pages/classrooms/create.tsx` | +| 46 | PATCH | `/api/groups/{id}` | Path unchanged | `src/pages/classrooms/[id].tsx` | +| 47 | DELETE | `/api/groups/{id}` | Path unchanged | `src/pages/classrooms/[id].tsx` | + +### 4.12 Entities + +| # | Method | Current URL | Odoo URL | Files | +|---|--------|-------------|----------|-------| +| 48 | POST | `/api/entities` | Path unchanged | `src/pages/entities/create.tsx` | +| 49 | PATCH | `/api/entities/{id}` | Path unchanged | `src/pages/entities/[id]/index.tsx` | +| 50 | DELETE | `/api/entities/{id}` | Path unchanged | `src/pages/entities/[id]/index.tsx` | +| 51 | PATCH | `/api/entities/{id}/users` | Path unchanged | `src/pages/entities/[id]/index.tsx` | + +### 4.13 Roles + +| # | Method | Current URL | Odoo URL | Files | +|---|--------|-------------|----------|-------| +| 52 | POST | `/api/roles` | Path unchanged | `src/pages/entities/[id]/roles/index.tsx` | +| 53 | PATCH | `/api/roles/{id}` | Path unchanged | `src/pages/entities/[id]/roles/[role].tsx` | +| 54 | DELETE | `/api/roles/{id}` | Path unchanged | `src/pages/entities/[id]/roles/[role].tsx` | +| 55 | POST | `/api/roles/{id}/users` | Path unchanged | `src/pages/entities/[id]/index.tsx` | + +### 4.14 Permissions + +| # | Method | Current URL | Odoo URL | Files | +|---|--------|-------------|----------|-------| +| 56 | PATCH | `/api/permissions/{id}` | Path unchanged | `src/pages/permissions/[id].tsx` | + +### 4.15 Payments + +| # | Method | Current URL | Odoo URL | Files | +|---|--------|-------------|----------|-------| +| 57 | POST | `/api/payments` | Path unchanged | `src/pages/payment-record.tsx` | +| 58 | PATCH | `/api/payments/{id}` | Path unchanged | `src/pages/payment-record.tsx` | +| 59 | DELETE | `/api/payments/{id}` | Path unchanged | `src/pages/payment-record.tsx` | +| 60 | GET/POST/DELETE | `/api/payments/files/{type}/{paymentId}` | Path unchanged | `src/components/PaymentAssetManager.tsx` | +| 61 | POST | `/api/paymob` | Path unchanged | `src/components/PaymobPayment.tsx` | + +**Bug fix opportunity:** In `src/pages/payment-record.tsx`, the PATCH call uses `api/payments/${id}` without a leading `/`. When switching to the shared axios instance with a `baseURL`, this will work correctly. But verify during testing. + +### 4.16 Assignments + +| # | Method | Current URL | Odoo URL | Files | +|---|--------|-------------|----------|-------| +| 62 | POST | `/api/assignments` | Path unchanged | `src/pages/assignments/creator/index.tsx` | +| 63 | PATCH | `/api/assignments/{id}` | Path unchanged | `src/pages/assignments/creator/[id].tsx`, `src/pages/assignments/[id].tsx` | +| 64 | DELETE | `/api/assignments/{id}` | Path unchanged | `src/pages/assignments/creator/[id].tsx`, `src/pages/assignments/[id].tsx` | +| 65 | POST | `/api/assignments/{id}/start` | Path unchanged | `src/pages/assignments/creator/[id].tsx`, `src/pages/assignments/[id].tsx` | + +### 4.17 Invites + +| # | Method | Current URL | Odoo URL | Files | +|---|--------|-------------|----------|-------| +| 66 | GET | `/api/invites/{decision}/{id}` | `POST /api/invites/{decision}/{id}` | `src/components/Medium/InviteCard.tsx`, `src/components/Medium/InviteWithUserCard.tsx` | + +**Note:** Currently uses GET for accept/decline actions (side-effectful GET). Odoo should accept POST. Consider updating the frontend to use POST -- it's a more correct HTTP method for state-changing operations. + +### 4.18 Approval Workflows + +| # | Method | Current URL | Odoo URL | Files | +|---|--------|-------------|----------|-------| +| 67 | POST | `/api/approval-workflows/create` | Path unchanged | `src/pages/approval-workflows/create.tsx` | +| 68 | PUT | `/api/approval-workflows/{id}` | Path unchanged | `src/pages/approval-workflows/[id]/index.tsx` | +| 69 | PUT | `/api/approval-workflows/{id}/edit` | Path unchanged | `src/pages/approval-workflows/[id]/edit.tsx` | +| 70 | DELETE | `/api/approval-workflows/{id}` | Path unchanged | `src/pages/approval-workflows/index.tsx` | + +### 4.19 Transcription + +| # | Method | Current URL | Odoo URL | Files | +|---|--------|-------------|----------|-------| +| 71 | POST | `/api/transcribe` | Path unchanged | (called from evaluation utils if needed) | + +### 4.20 Batch Users + +| # | Method | Current URL | Odoo URL | Files | +|---|--------|-------------|----------|-------| +| 72 | POST | `/api/batch_users` | Path unchanged | (admin import page) | + +### 4.21 Make User (Admin) + +| # | Method | Current URL | Odoo URL | Files | +|---|--------|-------------|----------|-------| +| 73 | POST | `/api/make_user` | Path unchanged | (admin user creation) | + +--- + +## 5. SSR Migration Strategy + +### 5.1 Current SSR Auth Pattern + +~35 pages use this pattern: + +```typescript +import { withIronSessionSsr } from "iron-session/next"; +import { sessionOptions } from "@/lib/session"; + +export const getServerSideProps = withIronSessionSsr(async ({ req, res }) => { + const user = await requestUser(req, res); + if (!user || !user.isVerified) return redirect("/login"); + return { props: { user } }; +}, sessionOptions); +``` + +### 5.2 Recommended: JWT Cookie + Server-Side Validation (Option A) + +Store the JWT in a regular cookie (set by `js-cookie` on login). In `getServerSideProps`, read the cookie from the request and call Odoo to validate. + +**New helper `src/lib/ssr-auth.ts`:** + +```typescript +import type { GetServerSidePropsContext, GetServerSidePropsResult } from "next"; + +const API_URL = process.env.NEXT_PUBLIC_API_URL; +const TOKEN_COOKIE = "encoach_token"; + +export function withAuth

>( + handler: (ctx: GetServerSidePropsContext, user: User) => Promise> +) { + return async (ctx: GetServerSidePropsContext): Promise> => { + const token = ctx.req.cookies[TOKEN_COOKIE]; + if (!token) { + return { redirect: { destination: "/login", permanent: false } }; + } + + try { + const res = await fetch(`${API_URL}/api/user`, { + headers: { Authorization: `Bearer ${token}` }, + }); + if (!res.ok) throw new Error("Unauthorized"); + const user = await res.json(); + if (!user.isVerified) { + return { redirect: { destination: "/login", permanent: false } }; + } + return handler(ctx, user); + } catch { + return { redirect: { destination: "/login", permanent: false } }; + } + }; +} +``` + +**Page migration example:** + +```typescript +// BEFORE +export const getServerSideProps = withIronSessionSsr(async ({ req, res }) => { + const user = await requestUser(req, res); + if (!user) return redirect("/login"); + // ... fetch additional data using user ... + return { props: { user, someData } }; +}, sessionOptions); + +// AFTER +export const getServerSideProps = withAuth(async (ctx, user) => { + // ... fetch additional data using user ... + return { props: { user, someData } }; +}); +``` + +### 5.3 Alternative: Client-Only Auth (Option B) + +Remove all `getServerSideProps` auth checks. Every page uses `useUser({ redirectTo: "/login" })` to protect itself. + +**Pros:** Simpler; no SSR auth at all. +**Cons:** Brief flash of unauthenticated content; pages that fetch data server-side need to move data fetching to client-side. + +### 5.4 Pages Requiring SSR Migration + +Every page below currently uses `withIronSessionSsr` and needs to switch to `withAuth` (Option A) or remove SSR auth (Option B): + +| Page | SSR Data Fetching | +|------|-------------------| +| `src/pages/index.tsx` | User only (redirects to dashboard) | +| `src/pages/login.tsx` | Reverse guard (redirect if already logged in) | +| `src/pages/dashboard/index.tsx` | User only | +| `src/pages/dashboard/teacher.tsx` | User + groups + assignments + stats | +| `src/pages/dashboard/student.tsx` | User + assignments + stats | +| `src/pages/dashboard/corporate.tsx` | User + entity data | +| `src/pages/dashboard/mastercorporate.tsx` | User + multi-entity data | +| `src/pages/dashboard/admin.tsx` | User + platform stats | +| `src/pages/dashboard/developer.tsx` | User | +| `src/pages/users/index.tsx` | User + user list | +| `src/pages/users/performance.tsx` | User + performance data | +| `src/pages/training/index.tsx` | User | +| `src/pages/training/[id]/index.tsx` | User + training data | +| `src/pages/tickets.tsx` | User + tickets | +| `src/pages/stats.tsx` | User + stats | +| `src/pages/statistical.tsx` | User | +| `src/pages/settings.tsx` | User | +| `src/pages/record.tsx` | User | +| `src/pages/profile.tsx` | User | +| `src/pages/popout.tsx` | User (session-based) | +| `src/pages/permissions/index.tsx` | User + permissions | +| `src/pages/permissions/[id].tsx` | User + permission detail | +| `src/pages/payment.tsx` | User | +| `src/pages/payment-record.tsx` | User + payments | +| `src/pages/official-exam.tsx` | User | +| `src/pages/generation.tsx` | User | +| `src/pages/exercises.tsx` | User + exam data | +| `src/pages/exam.tsx` | User + exam + session data | +| `src/pages/entities/index.tsx` | User + entities | +| `src/pages/entities/create.tsx` | User | +| `src/pages/entities/[id]/index.tsx` | User + entity detail | +| `src/pages/entities/[id]/roles/index.tsx` | User + roles | +| `src/pages/entities/[id]/roles/[role].tsx` | User + role detail | +| `src/pages/classrooms/*.tsx` | User + groups | +| `src/pages/assignments/*.tsx` | User + assignments | +| `src/pages/approval-workflows/*.tsx` | User + workflows | + +**For pages that only need user auth (no server-side data):** Replace `getServerSideProps` with client-side `useUser({ redirectTo: "/login" })`. + +**For pages that fetch additional data server-side:** Use `withAuth` and make the data-fetching calls to Odoo using the JWT token from the cookie. + +--- + +## 6. Files to Delete + +After migration, the following files are no longer needed. They represent the BFF layer being replaced by Odoo. + +### 6.1 API Route Files (108 files) + +Delete the entire `src/pages/api/` directory: + +**Auth & User:** +- `src/pages/api/login.ts` +- `src/pages/api/logout.ts` +- `src/pages/api/register.ts` +- `src/pages/api/user.ts` +- `src/pages/api/make_user.ts` +- `src/pages/api/batch_users.ts` +- `src/pages/api/reset/index.ts` +- `src/pages/api/reset/confirm.ts` +- `src/pages/api/reset/sendVerification.ts` +- `src/pages/api/reset/verify.ts` +- `src/pages/api/users/update.ts` +- `src/pages/api/users/search.ts` +- `src/pages/api/users/list.ts` +- `src/pages/api/users/controller.ts` +- `src/pages/api/users/balance.ts` +- `src/pages/api/users/agents/index.ts` +- `src/pages/api/users/agents/[code].ts` +- `src/pages/api/users/[id].ts` + +**Exams:** +- `src/pages/api/exam/index.ts` +- `src/pages/api/exam/upload.ts` +- `src/pages/api/exam/avatars.ts` +- `src/pages/api/exam/generate/[...module].ts` +- `src/pages/api/exam/media/[...module].ts` +- `src/pages/api/exam/media/poll.ts` +- `src/pages/api/exam/media/instructions.ts` +- `src/pages/api/exam/[module]/index.ts` +- `src/pages/api/exam/[module]/import.ts` +- `src/pages/api/exam/[module]/[id].ts` + +**Evaluation:** +- `src/pages/api/evaluate/writing.ts` +- `src/pages/api/evaluate/speaking.ts` +- `src/pages/api/evaluate/interactiveSpeaking.ts` +- `src/pages/api/evaluate/status.ts` +- `src/pages/api/evaluate/fetchSolutions.ts` + +**Grading:** +- `src/pages/api/grading/index.ts` +- `src/pages/api/grading/multiple.ts` + +**Stats & Sessions:** +- `src/pages/api/stats/index.ts` +- `src/pages/api/stats/update.ts` +- `src/pages/api/stats/disabled.ts` +- `src/pages/api/stats/user/[user].ts` +- `src/pages/api/stats/session/[session].ts` +- `src/pages/api/stats/[id]/index.ts` +- `src/pages/api/stats/[id]/[export]/pdf.tsx` +- `src/pages/api/statistical.ts` +- `src/pages/api/sessions/index.ts` +- `src/pages/api/sessions/[id].ts` + +**Training:** +- `src/pages/api/training/index.ts` +- `src/pages/api/training/[id].ts` +- `src/pages/api/training/user/[user].ts` +- `src/pages/api/training/walkthrough/index.ts` + +**Entities & Groups:** +- `src/pages/api/entities/index.ts` +- `src/pages/api/entities/users.ts` +- `src/pages/api/entities/groups.ts` +- `src/pages/api/entities/[id]/index.ts` +- `src/pages/api/entities/[id]/users.ts` +- `src/pages/api/groups/index.ts` +- `src/pages/api/groups/controller.ts` +- `src/pages/api/groups/[id].ts` + +**Roles & Permissions:** +- `src/pages/api/roles/index.ts` +- `src/pages/api/roles/[id]/index.ts` +- `src/pages/api/roles/[id]/users.ts` +- `src/pages/api/permissions/index.ts` +- `src/pages/api/permissions/bootstrap.ts` +- `src/pages/api/permissions/[id].ts` + +**Invites & Codes:** +- `src/pages/api/invites/index.ts` +- `src/pages/api/invites/[id].ts` +- `src/pages/api/invites/accept/[id].ts` +- `src/pages/api/invites/decline/[id].ts` +- `src/pages/api/code/index.ts` +- `src/pages/api/code/entities.ts` +- `src/pages/api/code/[id].ts` + +**Payments:** +- `src/pages/api/stripe.ts` +- `src/pages/api/paypal/index.ts` +- `src/pages/api/paypal/approve.ts` +- `src/pages/api/paypal/raas.ts` +- `src/pages/api/paymob/index.ts` +- `src/pages/api/paymob/webhook.ts` +- `src/pages/api/payments/index.ts` +- `src/pages/api/payments/[id].ts` +- `src/pages/api/payments/assigned.ts` +- `src/pages/api/payments/paypal.ts` +- `src/pages/api/payments/files/[type]/[paymentId].ts` +- `src/pages/api/packages/index.ts` +- `src/pages/api/packages/[id].ts` +- `src/pages/api/discounts/index.ts` +- `src/pages/api/discounts/[id].ts` + +**Assignments:** +- `src/pages/api/assignments/index.ts` +- `src/pages/api/assignments/corporate/index.ts` +- `src/pages/api/assignments/corporate/[id].ts` +- `src/pages/api/assignments/[id]/index.ts` +- `src/pages/api/assignments/[id]/start.ts` +- `src/pages/api/assignments/[id]/release.ts` +- `src/pages/api/assignments/[id]/archive.tsx` +- `src/pages/api/assignments/[id]/unarchive.tsx` +- `src/pages/api/assignments/[id]/[export]/pdf.tsx` +- `src/pages/api/assignments/[id]/[export]/excel.ts` + +**Approval Workflows:** +- `src/pages/api/approval-workflows/index.ts` +- `src/pages/api/approval-workflows/create.ts` +- `src/pages/api/approval-workflows/[id]/index.ts` +- `src/pages/api/approval-workflows/[id]/edit.ts` + +**Other:** +- `src/pages/api/storage/index.ts` +- `src/pages/api/storage/insert.ts` +- `src/pages/api/storage/delete.ts` +- `src/pages/api/speaking.ts` +- `src/pages/api/transcribe/index.ts` +- `src/pages/api/tickets/index.ts` +- `src/pages/api/tickets/[id].ts` +- `src/pages/api/tickets/assignedToUser/index.ts` +- `src/pages/api/hello.ts` + +### 6.2 Backend Utility Files (14 files) + +These files contain MongoDB query logic used by API routes. Delete all: + +- `src/utils/approval.workflows.be.ts` +- `src/utils/assignments.be.ts` +- `src/utils/codes.be.ts` +- `src/utils/disabled.be.ts` +- `src/utils/entities.be.ts` +- `src/utils/exams.be.ts` +- `src/utils/grading.be.ts` +- `src/utils/groups.be.ts` +- `src/utils/invites.be.ts` +- `src/utils/permissions.be.ts` +- `src/utils/roles.be.ts` +- `src/utils/sessions.be.ts` +- `src/utils/stats.be.ts` +- `src/utils/users.be.ts` + +### 6.3 Library Files (3 files) + +- `src/lib/session.ts` -- iron-session config (replaced by `src/lib/api.ts`) +- `src/lib/mongodb.ts` -- MongoDB connection (no longer needed) +- `src/lib/createWorkflowsOnExamCreation.ts` -- server-side workflow logic (moved to Odoo) + +**Keep:** +- `src/lib/utils.ts` -- general client-side utilities +- `src/lib/formidable-serverless.d.ts` -- only needed if any remaining file upload logic stays; likely deletable + +### 6.4 Firebase Files + +If Odoo replaces Firebase Auth entirely, also remove: + +- `src/firebase/` directory (Firebase client config) +- `src/constants/platform.json` (Firebase service account -- server-side only) +- `src/constants/staging.json` (Firebase service account -- server-side only) + +### 6.5 Dependencies to Remove from package.json + +``` +iron-session +firebase +firebase-admin +mongodb +@beam-australia/react-env (if no longer needed for client env) +bcrypt +formidable +``` + +### 6.6 Dependencies to Add + +``` +js-cookie (JWT cookie storage) +@types/js-cookie (TypeScript types) +``` + +--- + +## 7. Migration Checklist + +A step-by-step checklist for the frontend developer. Complete in order. + +### Phase 1: Infrastructure Setup + +- [ ] **1.1** Add `NEXT_PUBLIC_API_URL` to `.env.local` (point to Odoo dev instance) +- [ ] **1.2** Create `src/lib/api.ts` with shared axios instance, base URL, and JWT interceptor (Section 2.3) +- [ ] **1.3** Create `src/lib/auth.ts` with `setToken()`, `getToken()`, `clearToken()` helpers +- [ ] **1.4** Add `js-cookie` dependency: `yarn add js-cookie @types/js-cookie` +- [ ] **1.5** Create `src/lib/ssr-auth.ts` with `withAuth()` helper for SSR (Section 5.2) + +### Phase 2: Auth Migration + +- [ ] **2.1** Update `src/pages/login.tsx`: use `api.post()`, store JWT, extract user from response +- [ ] **2.2** Update `src/pages/register.tsx`: move registration to client-side, use `api.post()` +- [ ] **2.3** Update logout calls in `Sidebar.tsx`, `MobileMenu.tsx`, `official-exam.tsx`: use `api.post()` + `clearToken()` +- [ ] **2.4** Update `src/hooks/useUser.tsx`: use `api` instance for SWR fetcher +- [ ] **2.5** Update `src/utils/email.ts`: use `api` instance +- [ ] **2.6** Verify login/logout/register work end-to-end with Odoo + +### Phase 3: SSR Migration + +- [ ] **3.1** For each page in the SSR page list (Section 5.4), replace `withIronSessionSsr` with `withAuth` or client-side `useUser({ redirectTo: "/login" })` +- [ ] **3.2** Update pages that fetch server-side data to call Odoo with the JWT token +- [ ] **3.3** Verify all ~35 protected pages redirect correctly when not authenticated +- [ ] **3.4** Verify the login page redirects correctly when already authenticated + +### Phase 4: API Call Migration (domain by domain) + +For each domain, replace `axios` with `api` from `@/lib/api`: + +- [ ] **4.1** User endpoints (`src/pages/profile.tsx`, `src/components/UserCard.tsx`, `src/utils/groups.ts`, `src/components/Imports/StudentClassroomTransfer.tsx`) +- [ ] **4.2** Exam endpoints (`src/utils/exams.ts`, `src/hooks/useExams.tsx`, `src/pages/generation.tsx`, all `ExamEditor` files, `ExamList.tsx`) +- [ ] **4.3** Evaluation endpoints (`src/utils/evaluation.ts`) +- [ ] **4.4** Storage endpoints (all `ExamEditor/SettingsEditor` files, `src/utils/evaluation.ts`) +- [ ] **4.5** Speaking audio (`src/components/Solutions/Speaking.tsx`, `InteractiveSpeaking.tsx`) +- [ ] **4.6** Sessions (`src/stores/exam/index.ts`, `src/components/Medium/SessionCard.tsx`) +- [ ] **4.7** Stats (`src/stores/exam/index.ts`, `src/pages/training/[id]/index.tsx`, `src/pages/statistical.tsx`) +- [ ] **4.8** Training (`src/pages/training/index.tsx`, `src/pages/training/[id]/index.tsx`) +- [ ] **4.9** Groups (`src/utils/groups.ts`, `src/pages/classrooms/create.tsx`, `src/pages/classrooms/[id].tsx`) +- [ ] **4.10** Entities (`src/pages/entities/create.tsx`, `src/pages/entities/[id]/index.tsx`) +- [ ] **4.11** Roles (`src/pages/entities/[id]/roles/index.tsx`, `[role].tsx`) +- [ ] **4.12** Permissions (`src/pages/permissions/[id].tsx`) +- [ ] **4.13** Payments (`src/pages/payment-record.tsx`, `src/components/PaymentAssetManager.tsx`, `src/components/PaymobPayment.tsx`) +- [ ] **4.14** Assignments (`src/pages/assignments/creator/index.tsx`, `[id].tsx`, `src/pages/assignments/[id].tsx`) +- [ ] **4.15** Invites (`src/components/Medium/InviteCard.tsx`, `InviteWithUserCard.tsx`) +- [ ] **4.16** Approval workflows (`src/pages/approval-workflows/*.tsx`) +- [ ] **4.17** Codes (`src/pages/register.tsx`) +- [ ] **4.18** Remaining: transcribe, batch_users, make_user, statistical +- [ ] **4.19** Update `WordUploader.tsx` `fetch()` call with base URL and auth header + +### Phase 5: Cleanup + +- [ ] **5.1** Delete all 108 files in `src/pages/api/` +- [ ] **5.2** Delete all 14 `src/utils/*.be.ts` files +- [ ] **5.3** Delete `src/lib/session.ts`, `src/lib/mongodb.ts`, `src/lib/createWorkflowsOnExamCreation.ts` +- [ ] **5.4** Delete `src/firebase/` directory (if Firebase Auth fully removed) +- [ ] **5.5** Delete `src/constants/platform.json`, `src/constants/staging.json` +- [ ] **5.6** Remove unused dependencies from `package.json`: `iron-session`, `firebase`, `firebase-admin`, `mongodb`, `bcrypt`, `formidable` +- [ ] **5.7** Run `yarn install` to update lockfile +- [ ] **5.8** Run TypeScript compiler (`yarn tsc --noEmit`) and fix any remaining type errors +- [ ] **5.9** Run linter (`yarn lint`) and fix issues + +### Phase 6: Testing + +- [ ] **6.1** Test login flow (email + password -> JWT stored -> user loaded) +- [ ] **6.2** Test registration flow (individual and corporate) +- [ ] **6.3** Test logout (token cleared, redirect to login) +- [ ] **6.4** Test SSR protection (unauthenticated access to protected page -> redirect) +- [ ] **6.5** Test exam taking flow (load exam, answer questions, submit, save stats) +- [ ] **6.6** Test writing/speaking grading (submit, poll, receive result) +- [ ] **6.7** Test entity/group/classroom management (CRUD operations) +- [ ] **6.8** Test assignment lifecycle (create, start, release, archive) +- [ ] **6.9** Test payment flows (Stripe, PayPal, Paymob) +- [ ] **6.10** Test file uploads (exam media, profile pictures) +- [ ] **6.11** Test training content generation +- [ ] **6.12** Test ticket creation (from platform and landing page) +- [ ] **6.13** Test admin user management (create, update, batch import) +- [ ] **6.14** Cross-browser test (Chrome, Firefox, Safari) diff --git a/docs/ODOO_MIGRATION_SRS.md b/docs/ODOO_MIGRATION_SRS.md new file mode 100644 index 0000000..a8dde99 --- /dev/null +++ b/docs/ODOO_MIGRATION_SRS.md @@ -0,0 +1,2337 @@ +# EnCoach Platform -- Odoo 19 Migration SRS + +> **SUPERSEDED** -- This document has been replaced by `ENCOACH_ODOO19_BACKEND_SRS.md` (v3.0) and `ENCOACH_UNIFIED_SRS.md` (v2.0). All content below is historical. The migration is complete and the system is deployed at `http://5.189.151.117:8069`. + +## Software Requirements Specification + +**Version:** 1.0 +**Date:** March 11, 2026 +**Status:** ~~Draft~~ **SUPERSEDED** + +--- + +## Table of Contents + +1. [Executive Summary](#1-executive-summary) +2. [Odoo Module Plan](#2-odoo-module-plan) +3. [Data Models](#3-data-models-odoo-models) +4. [REST API Specification](#4-rest-api-specification) +5. [Authentication & Authorization](#5-authentication--authorization) +6. [ielts-be Integration Specification](#6-ielts-be-integration-specification) +7. [Payment Integration](#7-payment-integration) +8. [Business Rules & Workflows](#8-business-rules--workflows) +9. [Data Migration Plan](#9-data-migration-plan) +10. [Non-Functional Requirements](#10-non-functional-requirements) + +--- + +## 1. Executive Summary + +### 1.1 Platform Overview + +EnCoach is an IELTS preparation and English proficiency testing platform serving students, teachers, corporate clients, and administrators. The platform provides: + +- Full IELTS exam simulation (Reading, Listening, Writing, Speaking, Level) +- AI-powered grading of writing and speaking responses +- AI-powered exam content generation +- Multi-tenant entity (organization) management +- Classroom and assignment management +- Training and personalized recommendations +- Subscription-based access with multiple payment providers +- Support ticket system + +### 1.2 Migration Rationale + +Replace the current custom Node.js/MongoDB backend with Odoo 19 to leverage Odoo's built-in ERP capabilities for user management, subscriptions, payments, and helpdesk while retaining the specialized AI/ML microservice. + +### 1.3 Scope Boundaries + +**In Scope (Odoo replaces):** + +- All MongoDB direct access from ielts-ui API routes (22+ collections, 60+ endpoints) +- Firebase Auth for user authentication +- All business logic in `ielts-ui/src/pages/api/` and `ielts-ui/src/utils/*.be.ts` +- Payment processing (Stripe, PayPal, Paymob) +- File storage (currently Firebase Storage) + +**Out of Scope (unchanged):** + +- ielts-ui browser/frontend code (React components, Zustand stores, pages) +- ielts-be (FastAPI) AI/ML microservice (grading, generation, TTS, transcription, training) +- Strapi CMS (encoachcms) +- Landing page (encoach-landing-page) + +### 1.4 Current Architecture + +``` +ielts-ui (Next.js 14) + ├── Browser UI (React + Zustand + Tailwind) + ├── API Routes (/pages/api/) ──── MongoDB (22+ collections) + │ └─── Firebase Auth + └── Proxy routes ─────────────── ielts-be (FastAPI) + ├── OpenAI GPT-4o + ├── Whisper (local STT) + ├── AWS Polly (TTS) + ├── ELAI (AI Video) + └── GPTZero (AI Detection) +``` + +### 1.5 Target Architecture + +``` +ielts-ui (Next.js 14) + └── Browser UI (unchanged) + │ + ▼ +Odoo 19 (Python + PostgreSQL) + ├── REST API Controllers (JSON) + ├── Business Logic (custom modules) + ├── PostgreSQL (all data) + ├── Odoo Attachments (file storage) + ├── Payment Providers (Stripe, PayPal, Paymob) + └── HTTP Client ──────────────── ielts-be (FastAPI, unchanged) + ├── OpenAI GPT-4o + ├── Whisper (local STT) + ├── AWS Polly (TTS) + ├── ELAI (AI Video) + └── GPTZero (AI Detection) +``` + +The ielts-ui frontend will be updated to point its API calls at Odoo instead of its own `/api/` routes. The Next.js API routes layer is eliminated entirely. Odoo becomes the sole backend, proxying AI/ML requests to the unchanged ielts-be service. + +--- + +## 2. Odoo Module Plan + +### 2.1 Standard Odoo Modules to Leverage + +| Odoo Module | Usage | +|-------------|-------| +| `base` / `res.users` / `res.partner` | User accounts, extended with EnCoach-specific fields | +| `payment` | Payment provider framework for Stripe, PayPal, Paymob | +| `product` | Subscription packages as products | +| `helpdesk` (or custom) | Support ticket management | +| `mail` | Email notifications (password reset, verification, invites) | + +### 2.2 Custom Modules to Develop + +| Module | Depends On | Complexity | Description | +|--------|------------|------------|-------------| +| `encoach_core` | `base`, `mail` | Medium | User type extensions, entity management, roles, permissions, codes, invites | +| `encoach_exam` | `encoach_core` | High | Exam models for 5 modules (reading, listening, writing, speaking, level) with complex nested exercise structures | +| `encoach_classroom` | `encoach_core` | Low | Group/classroom management with participant tracking | +| `encoach_assignment` | `encoach_core`, `encoach_exam` | Medium | Assignment lifecycle (create, start, release, archive) linking exams to students | +| `encoach_stats` | `encoach_core`, `encoach_exam` | Medium | Exam sessions, per-exercise statistics, score tracking | +| `encoach_evaluation` | `encoach_core`, `encoach_exam` | Medium | Async grading records for writing/speaking, integration with ielts-be | +| `encoach_training` | `encoach_core` | Low | Training content storage, walkthrough state, proxy to ielts-be | +| `encoach_subscription` | `encoach_core`, `product`, `payment` | Medium | Packages, discounts, subscription expiry management, Stripe/PayPal/Paymob | +| `encoach_registration` | `encoach_core` | Medium | Multi-path registration (individual, corporate, admin-created), registration codes | +| `encoach_ticket` | `encoach_core` | Low | Support tickets (or extend `helpdesk`) | +| `encoach_api` | All above | High | REST JSON controllers exposing ~60 endpoints for frontend consumption | + +### 2.3 Module Dependency Graph + +``` +encoach_api + ├── encoach_core + │ ├── base / res.users / res.partner + │ └── mail + ├── encoach_exam + │ └── encoach_core + ├── encoach_classroom + │ └── encoach_core + ├── encoach_assignment + │ ├── encoach_core + │ └── encoach_exam + ├── encoach_stats + │ ├── encoach_core + │ └── encoach_exam + ├── encoach_evaluation + │ ├── encoach_core + │ └── encoach_exam + ├── encoach_training + │ └── encoach_core + ├── encoach_subscription + │ ├── encoach_core + │ ├── product + │ └── payment + ├── encoach_registration + │ └── encoach_core + └── encoach_ticket + └── encoach_core +``` + +--- + +## 3. Data Models (Odoo Models) + +This section specifies every Odoo model required, with field-level detail. Each model maps from one or more current MongoDB collections. + +### 3.1 `encoach.user` (extends `res.users`) + +**Source:** MongoDB `users` collection + +Extend `res.users` with the following fields. The standard `res.users` already provides `login` (email), `name`, `password`, and `active`. + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `encoach_type` | Selection | Yes | One of: `student`, `teacher`, `corporate`, `admin`, `developer`, `agent`, `mastercorporate` | +| `encoach_status` | Selection | Yes | One of: `active`, `disabled`, `payment_due`. Default: `active` | +| `profile_picture` | Binary / URL | No | Profile image. Default: `/defaultAvatar.png` | +| `bio` | Text | No | User biography | +| `focus` | Selection | No | `academic` or `general`. Default: `academic` | +| `is_first_login` | Boolean | No | Default: `True` | +| `is_verified` | Boolean | No | Email verification status. Default: `False` | +| `subscription_expiration_date` | Datetime | No | When the subscription expires | +| `registration_date` | Datetime | Yes | Account creation date | +| `last_login` | Datetime | No | Last login timestamp | +| `level_reading` | Float | No | Current reading level (0-9). Default: 0 | +| `level_listening` | Float | No | Current listening level (0-9). Default: 0 | +| `level_writing` | Float | No | Current writing level (0-9). Default: 0 | +| `level_speaking` | Float | No | Current speaking level (0-9). Default: 0 | +| `desired_level_reading` | Float | No | Target reading level. Default: 9 | +| `desired_level_listening` | Float | No | Target listening level. Default: 9 | +| `desired_level_writing` | Float | No | Target writing level. Default: 9 | +| `desired_level_speaking` | Float | No | Target speaking level. Default: 9 | +| `student_id` | Char | No | External student ID (student type only) | +| `average_level` | Float | No | Computed average across modules (student only) | +| `preferred_gender` | Selection | No | `male` or `female` (student only) | +| `preferred_topics` | Text (JSON) | No | JSON array of preferred topics (student only) | +| `phone` | Char | No | Phone number (demographic info) | +| `passport_id` | Char | No | Passport/national ID | +| `country_code` | Char | No | Country code | +| `company_name` | Char | No | Company name (corporate/agent) | +| `commercial_registration` | Char | No | Commercial registration number (agent) | +| `company_arab_name` | Char | No | Company name in Arabic (agent) | +| `entity_ids` | Many2many | No | Link to `encoach.entity` via `encoach.user.entity.rel` | +| `permission_ids` | Many2many | No | Link to `encoach.permission` | +| `legacy_id` | Char | No | Original MongoDB/Firebase UID for migration | + +### 3.2 `encoach.user.entity.rel` + +**Purpose:** Many-to-many relationship between users and entities with a role. + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `user_id` | Many2one(`res.users`) | Yes | The user | +| `entity_id` | Many2one(`encoach.entity`) | Yes | The entity | +| `role_id` | Many2one(`encoach.role`) | Yes | The user's role within this entity | + +### 3.3 `encoach.entity` + +**Source:** MongoDB `entities` collection + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `name` | Char | Yes | Entity display name (`label` in current system) | +| `licenses` | Integer | No | Number of licensed seats | +| `expiry_date` | Datetime | No | Entity license expiry | +| `payment_status` | Selection | No | `paid`, `unpaid`, `trial` | +| `role_ids` | One2many(`encoach.role`) | No | Roles defined for this entity | +| `user_rel_ids` | One2many(`encoach.user.entity.rel`) | No | Users in this entity | +| `group_ids` | One2many(`encoach.group`) | No | Groups belonging to this entity | +| `legacy_id` | Char | No | Original MongoDB ID | + +### 3.4 `encoach.role` + +**Source:** MongoDB `roles` collection + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `name` | Char | Yes | Role display name (`label` in current system) | +| `entity_id` | Many2one(`encoach.entity`) | Yes | Parent entity | +| `is_default` | Boolean | No | Whether this is the default role for new entity members | +| `permissions` | Text (JSON) | No | JSON object of granular permission flags | +| `legacy_id` | Char | No | Original MongoDB ID | + +### 3.5 `encoach.group` + +**Source:** MongoDB `groups` collection + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `name` | Char | Yes | Group/classroom name | +| `admin_id` | Many2one(`res.users`) | Yes | Group administrator | +| `entity_id` | Many2one(`encoach.entity`) | No | Owning entity | +| `participant_ids` | Many2many(`res.users`) | No | Group members | +| `disable_editing` | Boolean | No | Whether members can be modified. Default: `False` | +| `legacy_id` | Char | No | Original MongoDB ID | + +### 3.6 `encoach.exam` + +**Source:** MongoDB `reading`, `listening`, `writing`, `speaking`, `level` collections + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `name` | Char | No | Display label | +| `module` | Selection | Yes | `reading`, `listening`, `writing`, `speaking`, `level` | +| `min_timer` | Integer | No | Minimum time in seconds | +| `is_diagnostic` | Boolean | No | Diagnostic exam flag. Default: `False` | +| `variant` | Char | No | Exam variant identifier | +| `difficulty` | Selection | No | `A1`, `A2`, `B1`, `B2`, `C1`, `C2` | +| `access` | Selection | Yes | `public`, `private`, `confidential`. Default: `public` | +| `shuffle` | Boolean | No | Whether to shuffle questions. Default: `False` | +| `requires_approval` | Boolean | No | Needs admin approval before use. Default: `False` | +| `approved` | Boolean | No | Approval status. Default: `False` | +| `owner_ids` | Many2many(`res.users`) | No | Exam owners/creators | +| `entity_ids` | Many2many(`encoach.entity`) | No | Entities with access | +| `parts` | Text (JSON) | Yes | **Full exam structure as JSON** (see Section 3.6.1) | +| `legacy_id` | Char | No | Original MongoDB ID | + +#### 3.6.1 Exam `parts` JSON Structure + +Exams use a deeply nested JSON structure for their content. Modeling this as relational tables would be extremely complex (exercises contain sub-questions, solutions, options, etc.). Store as a JSON field and validate at the application level. + +**Reading exam `parts` example:** + +```json +[ + { + "text": { "title": "Passage Title", "content": "Full passage text..." }, + "exercises": [ + { + "id": "uuid", + "type": "multipleChoice", + "prompt": "Choose the correct answer", + "questions": [ + { + "id": "uuid", + "prompt": "What does the author suggest?", + "options": [ + { "id": "a", "text": "Option A" }, + { "id": "b", "text": "Option B" } + ], + "solution": "a" + } + ] + }, + { + "id": "uuid", + "type": "trueFalse", + "prompt": "Are these statements true, false, or not given?", + "questions": [ + { "id": "uuid", "prompt": "Statement X", "solution": "TRUE" } + ] + }, + { + "id": "uuid", + "type": "fillBlanks", + "prompt": "Complete the summary", + "text": "The study found that ___ were ___", + "solutions": [{ "id": "1", "solution": "researchers" }], + "words": [{ "letter": "A", "word": "researchers" }], + "allowRepetition": false + }, + { + "id": "uuid", + "type": "writeBlanks", + "prompt": "Complete with no more than 3 words", + "maxWords": 3, + "text": "Scientists discovered ___", + "solutions": [{ "id": "1", "solution": ["the answer", "an answer"] }] + }, + { + "id": "uuid", + "type": "matchSentences", + "prompt": "Match the headings", + "variant": "HEADING", + "options": [{ "id": "i", "sentence": "Heading A" }], + "sentences": [{ "id": "1", "sentence": "Paragraph 1 summary", "solution": "i" }] + } + ] + } +] +``` + +**Listening exam `parts` example:** + +```json +[ + { + "script": [ + { "name": "Speaker A", "gender": "male", "text": "Hello..." }, + { "name": "Speaker B", "gender": "female", "text": "Hi..." } + ], + "exercises": [ + { + "id": "uuid", + "type": "multipleChoice", + "prompt": "Choose the correct answer", + "questions": [ + { + "id": "uuid", + "prompt": "What is the main topic?", + "options": [{ "id": "a", "text": "Weather" }], + "solution": "a" + } + ] + }, + { + "id": "uuid", + "type": "writeBlanks", + "prompt": "Complete the form", + "maxWords": 2, + "variant": "FORM", + "questions": [ + { "id": "uuid", "prompt": "Name: ___", "solution": ["John Smith"] } + ] + } + ] + } +] +``` + +**Writing exam `parts` example:** + +```json +[ + { + "exercises": [ + { + "id": "uuid", + "type": "writing", + "task": 1, + "prompt": "Describe the chart below...", + "attachment": "url-to-image-or-null" + } + ] + }, + { + "exercises": [ + { + "id": "uuid", + "type": "writing", + "task": 2, + "prompt": "Some people believe that..." + } + ] + } +] +``` + +**Speaking exam `parts` example:** + +```json +[ + { + "exercises": [ + { + "id": "uuid", + "type": "interactiveSpeaking", + "task": 1, + "prompts": [ + "Do you enjoy reading?", + "What kind of books do you prefer?" + ] + } + ] + }, + { + "exercises": [ + { + "id": "uuid", + "type": "speaking", + "task": 2, + "text": "Describe a place you have visited..." + } + ] + } +] +``` + +**Level exam `parts` example:** + +```json +[ + { + "text": { "title": "Passage", "content": "Read the following..." }, + "exercises": [ + { + "id": "uuid", + "type": "multipleChoice", + "prompt": "Answer the questions", + "questions": [ + { + "id": "uuid", + "prompt": "What is correct?", + "variant": "text", + "options": [{ "id": "a", "text": "Option A" }], + "solution": "a" + } + ] + }, + { + "id": "uuid", + "type": "fillBlanks", + "variant": "mc", + "prompt": "Fill in the blanks", + "text": "She ___ to school every day", + "solutions": [{ "id": "1", "solution": "goes" }], + "words": [{ "letter": "A", "word": "goes" }] + } + ] + } +] +``` + +### 3.7 `encoach.assignment` + +**Source:** MongoDB `assignments` collection + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `name` | Char | Yes | Assignment name | +| `assigner_id` | Many2one(`res.users`) | Yes | Creator (teacher/admin) | +| `assignee_ids` | Many2many(`res.users`) | Yes | Assigned students | +| `teacher_ids` | Many2many(`res.users`) | No | Supervising teachers | +| `exam_ids` | Many2many(`encoach.exam`) | Yes | Exams included | +| `instructor_gender` | Selection | No | `male` or `female` | +| `start_date` | Datetime | No | When assignment becomes available | +| `end_date` | Datetime | No | Assignment deadline | +| `auto_start` | Boolean | No | Auto-start at start_date. Default: `False` | +| `started` | Boolean | No | Whether assignment has been started. Default: `False` | +| `released` | Boolean | No | Whether results are released. Default: `False` | +| `archived` | Boolean | No | Archived status. Default: `False` | +| `entity_id` | Many2one(`encoach.entity`) | No | Owning entity | +| `results` | Text (JSON) | No | JSON object of student results | +| `legacy_id` | Char | No | Original MongoDB ID | + +### 3.8 `encoach.session` + +**Source:** MongoDB `sessions` collection + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `user_id` | Many2one(`res.users`) | Yes | Student | +| `exam_id` | Many2one(`encoach.exam`) | No | Exam being taken | +| `assignment_id` | Many2one(`encoach.assignment`) | No | Related assignment (if any) | +| `start_time` | Datetime | Yes | Session start | +| `end_time` | Datetime | No | Session end | +| `status` | Selection | Yes | `in_progress`, `completed`, `abandoned` | +| `legacy_id` | Char | No | Original MongoDB ID | + +### 3.9 `encoach.stat` + +**Source:** MongoDB `stats` collection + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `user_id` | Many2one(`res.users`) | Yes | Student | +| `exam_id` | Many2one(`encoach.exam`) | Yes | Exam attempted | +| `exercise_id` | Char | Yes | Exercise UUID within the exam | +| `session_id` | Many2one(`encoach.session`) | Yes | Parent session | +| `assignment_id` | Many2one(`encoach.assignment`) | No | Related assignment | +| `date` | Datetime | Yes | Attempt timestamp | +| `module` | Selection | Yes | `reading`, `listening`, `writing`, `speaking`, `level` | +| `solutions` | Text (JSON) | No | JSON of user's answers | +| `exercise_type` | Char | No | Exercise type string | +| `time_spent` | Integer | No | Seconds spent | +| `inactivity` | Integer | No | Seconds of inactivity | +| `score` | Float | No | Score achieved | +| `is_disabled` | Boolean | No | Whether stat is disabled. Default: `False` | +| `shuffle_maps` | Text (JSON) | No | JSON mapping of shuffled question order | +| `pdf` | Binary | No | Generated PDF report | +| `is_practice` | Boolean | No | Practice attempt flag. Default: `False` | +| `legacy_id` | Char | No | Original MongoDB ID | + +### 3.10 `encoach.evaluation` + +**Source:** MongoDB `evaluation` collection + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `user_id` | Many2one(`res.users`) | Yes | Student being evaluated | +| `session_id` | Many2one(`encoach.session`) | Yes | Parent session | +| `exercise_id` | Char | Yes | Exercise UUID | +| `eval_type` | Selection | Yes | `writing`, `speaking`, `speaking_interactive` | +| `task` | Integer | Yes | Task number (1, 2, or 3) | +| `status` | Selection | Yes | `pending`, `in_progress`, `completed`, `error`. Default: `pending` | +| `result` | Text (JSON) | No | Grading result JSON (see Section 3.10.1) | +| `error` | Text | No | Error message if grading failed | +| `legacy_id` | Char | No | Original MongoDB ID | + +#### 3.10.1 Evaluation `result` JSON Structure + +**Writing result:** + +```json +{ + "comment": "Overall assessment of the student's writing...", + "overall": 6.5, + "task_response": { + "Task Achievement": { "grade": 6.0, "comment": "..." }, + "Coherence and Cohesion": { "grade": 7.0, "comment": "..." }, + "Lexical Resource": { "grade": 6.5, "comment": "..." }, + "Grammatical Range and Accuracy": { "grade": 6.5, "comment": "..." } + }, + "perfect_answer": "A model answer text...", + "fixed_text": "The student's text with corrections...", + "ai_detection": { "probability": 0.12 } +} +``` + +**Speaking result:** + +```json +{ + "comment": "Overall assessment of the student's speaking...", + "overall": 7.0, + "task_response": { + "Fluency and Coherence": { "grade": 7.0, "comment": "..." }, + "Lexical Resource": { "grade": 7.0, "comment": "..." }, + "Grammatical Range and Accuracy": { "grade": 6.5, "comment": "..." }, + "Pronunciation": { "grade": 7.5, "comment": "..." } + }, + "transcript": "Transcribed student speech...", + "fixed_text": "Corrected transcript...", + "perfect_answer": "A model answer...", + "solutions": ["url-to-audio-file"] +} +``` + +### 3.11 `encoach.package` + +**Source:** MongoDB `packages` collection + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `name` | Char | No | Display name | +| `currency` | Char | Yes | Currency code (e.g., `USD`, `SAR`) | +| `duration` | Integer | Yes | Subscription duration value | +| `duration_unit` | Selection | Yes | `days`, `months`, `years` | +| `price` | Float | Yes | Package price | +| `active` | Boolean | No | Whether package is available. Default: `True` | +| `legacy_id` | Char | No | Original MongoDB ID | + +### 3.12 `encoach.payment` + +**Source:** MongoDB `payments` collection (corporate/agent payments) + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `corporate_id` | Many2one(`res.users`) | Yes | Corporate user | +| `entity_id` | Many2one(`encoach.entity`) | No | Related entity | +| `agent_id` | Many2one(`res.users`) | No | Sales agent | +| `agent_commission` | Float | No | Agent commission percentage | +| `agent_value` | Float | No | Agent commission amount | +| `currency` | Char | Yes | Currency code | +| `value` | Float | Yes | Payment amount | +| `is_paid` | Boolean | No | Payment status. Default: `False` | +| `date` | Datetime | Yes | Payment date | +| `corporate_transfer` | Char | No | Corporate bank transfer reference | +| `commission_transfer` | Char | No | Commission transfer reference | +| `legacy_id` | Char | No | Original MongoDB ID | + +### 3.13 `encoach.subscription.payment` + +**Source:** MongoDB `paypalpayments` collection (individual Stripe/PayPal/Paymob payments) + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `user_id` | Many2one(`res.users`) | Yes | Paying user | +| `provider` | Selection | Yes | `stripe`, `paypal`, `paymob` | +| `order_id` | Char | Yes | Provider's order/session ID | +| `status` | Selection | Yes | `pending`, `completed`, `failed` | +| `value` | Float | Yes | Amount paid | +| `currency` | Char | Yes | Currency code | +| `subscription_duration` | Integer | No | Duration value | +| `subscription_duration_unit` | Selection | No | `days`, `months`, `years` | +| `subscription_expiration_date` | Datetime | No | New expiry date after payment | +| `created_at` | Datetime | Yes | Payment timestamp | +| `checkout_data` | Text (JSON) | No | Raw provider checkout data | +| `legacy_id` | Char | No | Original MongoDB ID | + +### 3.14 `encoach.ticket` + +**Source:** MongoDB `tickets` collection + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `subject` | Char | Yes | Ticket subject | +| `description` | Text | Yes | Ticket description | +| `status` | Selection | Yes | `open`, `in_progress`, `resolved`, `closed`. Default: `open` | +| `ticket_type` | Char | No | Ticket category | +| `reporter_id` | Many2one(`res.users`) | No | Reporting user (null for public tickets) | +| `reported_from` | Char | No | Source (`platform`, `landing_page`) | +| `assigned_to_id` | Many2one(`res.users`) | No | Assigned support agent | +| `exam_information` | Text (JSON) | No | Related exam context | +| `date` | Datetime | Yes | Creation date | +| `legacy_id` | Char | No | Original MongoDB ID | + +### 3.15 `encoach.code` + +**Source:** MongoDB `codes` collection + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `code` | Char | Yes | Registration code string (unique) | +| `creator_id` | Many2one(`res.users`) | No | User who created the code | +| `entity_id` | Many2one(`encoach.entity`) | No | Entity this code belongs to | +| `code_type` | Selection | No | Code type category | +| `expiry_date` | Datetime | No | When the code expires | +| `creation_date` | Datetime | Yes | When the code was created | +| `user_id` | Many2one(`res.users`) | No | User who redeemed the code | +| `email` | Char | No | Email associated with this code | +| `name` | Char | No | Name associated with this code | +| `passport_id` | Char | No | Passport ID associated | +| `checkout` | Text (JSON) | No | Stripe checkout session data | +| `legacy_id` | Char | No | Original MongoDB ID | + +### 3.16 `encoach.invite` + +**Source:** MongoDB `invites` collection + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `entity_id` | Many2one(`encoach.entity`) | Yes | Entity being invited to | +| `from_user_id` | Many2one(`res.users`) | Yes | Inviter | +| `to_user_id` | Many2one(`res.users`) | Yes | Invitee | +| `status` | Selection | Yes | `pending`, `accepted`, `declined`. Default: `pending` | +| `created_at` | Datetime | Yes | Invite creation date | +| `legacy_id` | Char | No | Original MongoDB ID | + +### 3.17 `encoach.permission` + +**Source:** MongoDB `permissions` collection + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `name` | Char | Yes | Permission display name | +| `permission_type` | Char | Yes | Permission type key | +| `topic` | Char | No | Permission topic/category | +| `user_ids` | Many2many(`res.users`) | No | Users granted this permission | +| `legacy_id` | Char | No | Original MongoDB ID | + +### 3.18 `encoach.discount` + +**Source:** MongoDB `discounts` collection + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `code` | Char | Yes | Discount code string | +| `percentage` | Float | Yes | Discount percentage (0-100) | +| `domain` | Char | No | Domain restriction | +| `valid_until` | Datetime | No | Expiry date | +| `active` | Boolean | No | Default: `True` | +| `legacy_id` | Char | No | Original MongoDB ID | + +### 3.19 `encoach.training` + +**Source:** MongoDB `training` collection + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `user_id` | Many2one(`res.users`) | Yes | Student | +| `created_at` | Datetime | Yes | Training generation date | +| `exams` | Text (JSON) | No | JSON array of exam performance summaries | +| `tips` | Text (JSON) | No | JSON object with categorized tips | +| `weak_areas` | Text (JSON) | No | JSON array: `[{ "area": "...", "comment": "..." }]` | +| `legacy_id` | Char | No | Original MongoDB ID | + +### 3.20 `encoach.walkthrough` + +**Source:** MongoDB `walkthrough` collection + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `user_id` | Many2one(`res.users`) | Yes | User | +| `state` | Text (JSON) | No | JSON object tracking walkthrough progress | +| `legacy_id` | Char | No | Original MongoDB ID | + +### 3.21 `encoach.approval.workflow` + +**Source:** MongoDB `configured-workflows` and `active-workflows` collections + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `name` | Char | Yes | Workflow name | +| `workflow_type` | Selection | Yes | `configured`, `active` | +| `config` | Text (JSON) | No | Workflow configuration | +| `status` | Selection | No | `pending`, `approved`, `rejected` | +| `entity_id` | Many2one(`encoach.entity`) | No | Related entity | +| `legacy_id` | Char | No | Original MongoDB ID | + +--- + +## 4. REST API Specification + +All endpoints must return JSON. The `encoach_api` module implements Odoo JSON controllers (inheriting `http.Controller`) with `type='json'` or `type='http'` routes. + +**Base URL:** `https://{odoo-host}/api/` + +**Authentication:** All endpoints require a valid session/JWT unless marked `[PUBLIC]`. + +**Response format convention:** Match the current frontend expectations. All responses are JSON objects. Lists are returned as arrays. Errors use HTTP status codes with `{ "error": "message" }`. + +### 4.1 Authentication Endpoints + +#### `POST /api/login` + +Login with email and password. Returns user object and sets session. + +**Request:** +```json +{ + "email": "user@example.com", + "password": "secret" +} +``` + +**Response (200):** +```json +{ + "id": 1, + "email": "user@example.com", + "name": "John Doe", + "type": "student", + "status": "active", + "profilePicture": "/defaultAvatar.png", + "isFirstLogin": false, + "isVerified": true, + "focus": "academic", + "levels": { "reading": 6.5, "listening": 7.0, "writing": 6.0, "speaking": 6.5 }, + "desiredLevels": { "reading": 9, "listening": 9, "writing": 9, "speaking": 9 }, + "subscriptionExpirationDate": "2026-12-31T00:00:00Z", + "registrationDate": "2025-01-15T00:00:00Z", + "entities": [{ "id": 5, "role": "student" }], + "permissions": [] +} +``` + +**Error (401):** `{ "error": "Invalid credentials" }` + +#### `POST /api/register` + +Register a new user. Supports two registration types. + +**Request (individual):** +```json +{ + "type": "individual", + "email": "user@example.com", + "password": "secret", + "name": "John Doe", + "code": "OPTIONAL_REG_CODE" +} +``` + +**Request (corporate):** +```json +{ + "type": "corporate", + "email": "corp@example.com", + "password": "secret", + "name": "Corp Admin", + "corporateInformation": { + "companyName": "Acme Inc" + } +} +``` + +**Response (201):** User object (same shape as login response) + +**Business logic:** See Section 8.1 for full registration flow. + +#### `POST /api/logout` + +Destroy current session. + +**Response (200):** `{ "ok": true }` + +#### `GET /api/user` + +Get current authenticated user. + +**Response (200):** User object (same shape as login response) + +#### `POST /api/reset/sendVerification` + +Send email verification link. + +**Request:** `{ "email": "user@example.com" }` + +**Response (200):** `{ "ok": true }` + +#### `POST /api/reset/confirm` + +Reset password via token. + +**Request:** `{ "token": "reset-token", "newPassword": "new-secret" }` + +**Response (200):** `{ "ok": true }` + +### 4.2 User Endpoints + +#### `GET /api/users/list` + +List users linked to the current user (by entity, group, or admin scope). + +**Query params:** `page`, `limit`, `type`, `entity`, `group`, `search` + +**Response (200):** +```json +{ + "users": [ { ...userObject } ], + "total": 150 +} +``` + +#### `GET /api/users/{id}` + +Get a single user by ID. + +**Response (200):** User object + +#### `GET /api/users/search` + +Full-text search users by name or email. + +**Query params:** `q` (search string), `limit` + +**Response (200):** `[ { ...userObject } ]` + +#### `PATCH /api/users/update` + +Update user fields. Admins can update other users. Users can update their own profile. + +**Request:** +```json +{ + "id": 1, + "name": "Updated Name", + "bio": "New bio", + "focus": "general", + "levels": { "reading": 7.0 }, + "status": "active", + "subscriptionExpirationDate": "2027-01-01T00:00:00Z" +} +``` + +**Response (200):** Updated user object + +#### `DELETE /api/user` + +Delete the current user's account. + +**Response (200):** `{ "ok": true }` + +#### `GET /api/users/balance` + +Get user's subscription balance/remaining days. + +**Response (200):** `{ "balance": 45, "expirationDate": "2026-05-01T00:00:00Z" }` + +#### `GET /api/users/controller` + +Admin user CRUD controller. + +**Query params:** `action` (`list`, `create`, `update`, `delete`), relevant fields + +**Response:** Depends on action + +#### `POST /api/users/controller` + +Admin user creation/modification. + +**Request:** User creation/update payload + +**Response:** User object or confirmation + +#### `POST /api/make_user` + +Admin/corporate create a user (with auto-generated password). + +**Request:** +```json +{ + "email": "student@example.com", + "name": "Student Name", + "type": "student", + "entity": 5, + "group": 10, + "expiryDate": "2027-01-01", + "passport_id": "AB123456" +} +``` + +**Response (201):** `{ "user": { ...userObject }, "code": { ...codeObject } }` + +#### `POST /api/batch_users` + +Bulk import users. Odoo forwards to ielts-be for Firebase-compatible processing, then stores the resulting users. + +**Request:** `{ "makerID": "admin-id", "users": [ { ...userDTO } ] }` + +**Response (200):** `{ "ok": true }` + +**Integration:** Calls ielts-be `POST /api/user/import` (see Section 6). + +#### `GET /api/users/agents` `[PUBLIC]` + +List sales agent users. Used by the landing page. + +**Response (200):** `[ { "id": 1, "name": "Agent", "companyName": "...", "country": "SA" } ]` + +#### `GET /api/users/agents/{code}` + +Get agent by country code. + +**Response (200):** Agent user object + +### 4.3 Entity Endpoints + +#### `GET /api/entities` + +List entities the current user has access to. + +**Response (200):** `[ { ...entityObject } ]` + +#### `POST /api/entities` + +Create a new entity. + +**Request:** +```json +{ + "label": "ABC School", + "licenses": 100, + "expiryDate": "2027-01-01" +} +``` + +**Response (201):** Entity object + +#### `GET /api/entities/{id}` + +Get entity by ID with roles and user counts. + +**Response (200):** Entity object with nested `roles` and `userCount` + +#### `PATCH /api/entities/{id}` + +Update entity fields. + +**Request:** Partial entity object + +**Response (200):** Updated entity + +#### `GET /api/entities/{id}/users` + +List users belonging to an entity. + +**Query params:** `page`, `limit`, `role` + +**Response (200):** `{ "users": [...], "total": 50 }` + +#### `GET /api/entities/{id}/groups` + +List groups in an entity. + +**Response (200):** `[ { ...groupObject } ]` + +### 4.4 Group Endpoints + +#### `GET /api/groups` + +List groups accessible to the current user. + +**Query params:** `entity` + +**Response (200):** `[ { ...groupObject, "participantCount": 25 } ]` + +#### `POST /api/groups` + +Create a group. + +**Request:** +```json +{ + "name": "Class A", + "entity": 5, + "participants": [1, 2, 3] +} +``` + +**Response (201):** Group object + +#### `GET /api/groups/{id}` + +Get group with participant list. + +**Response (200):** Group object with `participants` array + +#### `PATCH /api/groups/{id}` + +Update group (add/remove participants, rename). + +**Request:** Partial group object + +**Response (200):** Updated group + +### 4.5 Role Endpoints + +#### `GET /api/roles` + +List roles for an entity. + +**Query params:** `entity` + +**Response (200):** `[ { ...roleObject } ]` + +#### `POST /api/roles` + +Create a role. + +**Request:** `{ "label": "Teacher", "entityID": 5, "permissions": { ... }, "isDefault": false }` + +**Response (201):** Role object + +#### `GET /api/roles/{id}` + +Get role details. + +#### `PATCH /api/roles/{id}` + +Update role permissions. + +#### `GET /api/roles/{id}/users` + +List users with this role. + +### 4.6 Permission Endpoints + +#### `GET /api/permissions` + +List all permission definitions. + +**Response (200):** `[ { "id": 1, "type": "exam_create", "topic": "exams", "users": [1,2,3] } ]` + +#### `POST /api/permissions/bootstrap` + +Initialize default permissions for an entity. + +#### `PATCH /api/permissions/{id}` + +Update a permission (add/remove users). + +### 4.7 Invite Endpoints + +#### `GET /api/invites` + +List invites for the current user (sent and received). + +**Response (200):** `[ { ...inviteObject } ]` + +#### `POST /api/invites` + +Send an invite. + +**Request:** `{ "entity": 5, "to": "user@example.com" }` + +**Response (201):** Invite object + +#### `POST /api/invites/accept/{id}` + +Accept an invite. + +**Response (200):** `{ "ok": true }` + +**Business logic:** Add user to entity with the default role. + +#### `POST /api/invites/decline/{id}` + +Decline an invite. + +**Response (200):** `{ "ok": true }` + +### 4.8 Code Endpoints + +#### `GET /api/code` + +List registration codes. + +**Query params:** `entity`, `creator` + +**Response (200):** `[ { ...codeObject } ]` + +#### `POST /api/code` + +Create a registration code. + +**Request:** `{ "entity": 5, "expiryDate": "2027-01-01", "type": "student" }` + +**Response (201):** Code object + +#### `GET /api/code/{id}` + +Get code details. + +#### `DELETE /api/code/{id}` + +Delete a code. + +#### `GET /api/code/entities` + +List codes grouped by entity. + +### 4.9 Exam Endpoints + +#### `GET /api/exam/{module}` + +List exams for a module. + +**Path params:** `module` = `reading` | `listening` | `writing` | `speaking` | `level` + +**Query params:** `entity`, `access`, `difficulty`, `page`, `limit` + +**Response (200):** `[ { ...examObject (without full parts for listing) } ]` + +#### `GET /api/exam/{module}/{id}` + +Get a single exam with full `parts` JSON. + +**Response (200):** Full exam object including nested exercises + +#### `POST /api/exam/upload` + +Upload an exam document for parsing. Proxied to ielts-be. + +**Request:** Multipart form with file + +**Response (200):** Parsed exam object + +**Integration:** Forwards to ielts-be endpoint (see Section 6). + +#### `POST /api/exam/generate/{module}` + +Generate exam content using AI. Proxied to ielts-be. + +**Path params:** `module` = `reading` | `listening` | `writing` | `speaking` | `level` + +**Request:** Module-specific generation parameters (varies) + +**Response (200):** Generated content + +**Integration:** Forwards to ielts-be endpoint (see Section 6). + +#### `POST /api/exam/media/{module}` + +Generate media (audio/video) for an exam. Proxied to ielts-be. + +**Request:** Module-specific media parameters + +**Response (200):** Media file (audio/video bytes) or URL + +**Integration:** Forwards to ielts-be endpoint (see Section 6). + +#### `GET /api/exam/avatars` + +List available speaking avatars. Proxied to ielts-be. + +**Response (200):** `[ { "id": "avatar_1", "name": "...", "thumbnail": "..." } ]` + +#### `POST /api/exam/{module}/import` + +Import an exam from file. Proxied to ielts-be. + +**Request:** Multipart form with `exercises` and optional `solutions` files + +**Response (200):** Parsed exam object. Odoo should then persist the exam to `encoach.exam`. + +#### `POST /api/exam` (save) + +Save an exam (new or updated) to the database. + +**Request:** Full exam object with `parts` JSON + +**Response (201/200):** Saved exam object with ID + +### 4.10 Assignment Endpoints + +#### `GET /api/assignments` + +List assignments. + +**Query params:** `assigner`, `assignee`, `entity`, `archived`, `page`, `limit` + +**Response (200):** `[ { ...assignmentObject } ]` + +#### `POST /api/assignments` + +Create an assignment. + +**Request:** +```json +{ + "name": "Week 1 Practice", + "assignees": [1, 2, 3], + "exams": [10, 11], + "startDate": "2026-04-01", + "endDate": "2026-04-07", + "instructorGender": "female", + "entity": 5, + "teachers": [4], + "autoStart": true +} +``` + +**Response (201):** Assignment object + +#### `GET /api/assignments/{id}` + +Get assignment details with participant results. + +#### `PATCH /api/assignments/{id}` + +Update assignment. + +#### `POST /api/assignments/{id}/start` + +Start an assignment (make it available to students). + +**Response (200):** `{ "ok": true }` + +#### `POST /api/assignments/{id}/release` + +Release assignment results to students. + +**Response (200):** `{ "ok": true }` + +#### `POST /api/assignments/{id}/archive` + +Archive an assignment. + +#### `POST /api/assignments/{id}/unarchive` + +Unarchive an assignment. + +#### `GET /api/assignments/corporate` + +List assignments for corporate dashboard. + +### 4.11 Session Endpoints + +#### `GET /api/sessions` + +List sessions for a user. + +**Query params:** `user`, `exam`, `assignment` + +**Response (200):** `[ { ...sessionObject } ]` + +#### `POST /api/sessions` + +Create a new exam session. + +**Request:** `{ "exam": 10, "assignment": 5 }` + +**Response (201):** Session object with ID + +#### `GET /api/sessions/{id}` + +Get session details. + +#### `PATCH /api/sessions/{id}` + +Update session (e.g., mark as completed). + +### 4.12 Stats Endpoints + +#### `GET /api/stats` + +List stats. + +**Query params:** `user`, `exam`, `session`, `module`, `assignment`, `page`, `limit` + +**Response (200):** `[ { ...statObject } ]` + +#### `POST /api/stats` + +Create a stat record (exercise attempt result). + +**Request:** +```json +{ + "user": 1, + "exam": 10, + "exercise": "uuid-string", + "session": 20, + "module": "reading", + "solutions": { ... }, + "type": "multipleChoice", + "timeSpent": 120, + "inactivity": 5, + "score": 0.85, + "assignment": 5, + "isPractice": false +} +``` + +**Response (201):** Stat object + +#### `GET /api/stats/{id}` + +Get a single stat. + +#### `PATCH /api/stats/{id}` + +Update a stat (e.g., disable, set PDF). + +#### `GET /api/stats/user/{userId}` + +Get all stats for a user. + +#### `GET /api/stats/session/{sessionId}` + +Get all stats for a session. + +#### `PATCH /api/stats/disabled` + +Bulk disable stats. + +#### `GET /api/stats/{id}/{exportType}/pdf` + +Generate a PDF report for a stat. Calls ielts-be for grading summary. + +**Response:** PDF binary or `{ "url": "..." }` + +**Integration:** Calls ielts-be `POST /api/exam/grade/summary` for section-level evaluation. + +### 4.13 Grading / Evaluation Endpoints + +#### `POST /api/evaluate/writing` + +Submit a writing answer for AI grading. Creates an evaluation record and proxies to ielts-be. + +**Request:** +```json +{ + "userId": 1, + "sessionId": 20, + "exerciseId": "uuid", + "question": "Write about...", + "answer": "Student's essay text...", + "task": 1, + "attachment": "optional-image-url" +} +``` + +**Response (200):** `{ "ok": true }` (grading happens asynchronously) + +**Business logic:** +1. Create `encoach.evaluation` record with status `pending` +2. Forward request to ielts-be `POST /api/exam/grade/writing/{task}` +3. ielts-be processes asynchronously and updates the evaluation record + +#### `POST /api/evaluate/speaking` + +Submit speaking audio for AI grading. + +**Request:** Multipart form with `userId`, `sessionId`, `exerciseId`, `task`, and audio files (`audio_1`, `audio_2`, etc.) + +**Response (200):** `{ "ok": true }` (grading happens asynchronously) + +**Business logic:** Same pattern as writing grading. + +#### `POST /api/evaluate/interactiveSpeaking` + +Submit interactive speaking (multiple Q&A pairs). + +**Request:** Same as speaking but with `question_N` and `audio_N` pairs. + +**Response (200):** `{ "ok": true }` + +#### `GET /api/evaluate/{sessionId}/{exerciseId}` + +Poll for evaluation result. + +**Response (200):** +```json +{ + "status": "completed", + "result": { ...gradingResult } +} +``` + +#### `POST /api/grading/multiple` + +Grade multiple short-answer exercises at once. Proxied to ielts-be. + +**Request:** +```json +{ + "text": "passage text", + "questions": ["Q1", "Q2"], + "answers": ["A1", "A2"] +} +``` + +**Response (200):** `{ "exercises": [{ "id": "...", "correct": true, "correct_answer": "..." }] }` + +### 4.14 Training Endpoints + +#### `POST /api/training` + +Generate training content for a user. Proxied to ielts-be. + +**Request:** +```json +{ + "userID": 1, + "stats": [ { ...statSummary } ] +} +``` + +**Response (200):** `{ "id": "training-record-id" }` + +**Business logic:** Forward to ielts-be; store returned content in `encoach.training`. + +#### `POST /api/training/tips` + +Fetch personalized tips. Proxied to ielts-be. + +**Request:** `{ "context": "...", "question": "...", "answer": "...", "correct_answer": "..." }` + +**Response (200):** `{ "tips": "..." }` + +#### `GET /api/training/user/{userId}` + +Get stored training content for a user. + +**Response (200):** Training object with tips and weak areas + +#### `GET /api/training/walkthrough` + +Get walkthrough state. + +**Response (200):** `{ "state": { ... } }` + +#### `PATCH /api/training/walkthrough` + +Update walkthrough state. + +**Request:** `{ "state": { ... } }` + +### 4.15 Payment Endpoints + +#### `POST /api/stripe` + +Create a Stripe checkout session. + +**Request:** `{ "email": "user@example.com", "days": 30, "key": "package-key" }` + +**Response (200):** `{ "url": "https://checkout.stripe.com/..." }` + +**Webhook: `POST /api/stripe/webhook`** + +Handle Stripe webhook events (payment completed). See Section 7.1. + +#### `POST /api/paypal` + +Create a PayPal order. + +**Request:** `{ "amount": 99.00, "currency": "USD" }` + +**Response (200):** `{ "orderId": "PAYPAL_ORDER_ID" }` + +#### `POST /api/paypal/approve` + +Capture a PayPal payment after customer approval. + +**Request:** `{ "id": "PAYPAL_ORDER_ID", "duration": 30, "duration_unit": "days", "trackingId": "..." }` + +**Response (200):** `{ "ok": true }` + +**Business logic:** See Section 7.2. + +#### `POST /api/paymob` + +Create a Paymob payment intention. + +**Request:** `{ "amount": 500, "currency": "SAR" }` + +**Response (200):** `{ "clientSecret": "..." }` + +#### `POST /api/paymob/webhook` + +Handle Paymob transaction webhook. + +**Business logic:** See Section 7.3. + +#### `GET /api/payments` + +List corporate/agent payments. + +**Query params:** `corporate`, `entity`, `agent`, `isPaid` + +**Response (200):** `[ { ...paymentObject } ]` + +#### `POST /api/payments` + +Create a corporate payment record. + +**Request:** Payment object fields + +**Response (201):** Payment object + +#### `GET /api/payments/{id}` + +Get payment details. + +#### `PATCH /api/payments/{id}` + +Update payment (mark as paid, update transfers). + +**Business logic:** When `isPaid` is set to `true`, activate the corporate user's subscription (see Section 8.4). + +#### `DELETE /api/payments/{id}` + +Delete a payment record. + +#### `GET /api/payments/assigned` + +List payments assigned to an agent. + +### 4.16 Package Endpoints + +#### `GET /api/packages` `[PUBLIC]` + +List available subscription packages. Used by both the platform and landing page. + +**Response (200):** `[ { "id": 1, "currency": "USD", "duration": 30, "duration_unit": "days", "price": 29.99 } ]` + +#### `POST /api/packages` + +Create a package (admin only). + +**Request:** Package fields + +**Response (201):** Package object + +#### `GET /api/packages/{id}` + +Get package details. + +#### `PATCH /api/packages/{id}` + +Update a package. + +#### `DELETE /api/packages/{id}` + +Delete a package. + +### 4.17 Discount Endpoints + +#### `GET /api/discounts` + +List discount codes. + +**Response (200):** `[ { ...discountObject } ]` + +#### `POST /api/discounts` + +Create a discount code. + +**Request:** `{ "code": "SAVE20", "percentage": 20, "domain": "encoach.com", "validUntil": "2027-01-01" }` + +**Response (201):** Discount object + +#### `DELETE /api/discounts/{id}` + +Delete a discount code. + +### 4.18 Ticket Endpoints + +#### `GET /api/tickets` + +List tickets. + +**Query params:** `status`, `assignedTo`, `reporter`, `page`, `limit` + +**Response (200):** `[ { ...ticketObject } ]` + +#### `POST /api/tickets` `[PUBLIC]` + +Create a ticket. Used by both the platform and landing page contact form. + +**Request:** +```json +{ + "subject": "Cannot access exam", + "description": "When I click...", + "type": "bug", + "reportedFrom": "platform", + "examInformation": { "examId": 10, "module": "reading" } +} +``` + +**Response (201):** Ticket object + +#### `GET /api/tickets/{id}` + +Get ticket details. + +#### `PATCH /api/tickets/{id}` + +Update ticket (assign, change status). + +#### `GET /api/tickets/assignedToUser` + +List tickets assigned to the current support agent. + +### 4.19 Storage Endpoints + +#### `POST /api/storage/insert` + +Upload a file. Use Odoo's `ir.attachment` system. + +**Request:** Multipart form with file + +**Response (200):** `{ "url": "https://odoo-host/web/content/attachment_id" }` + +#### `GET /api/storage` + +List files for a context (e.g., user profile pictures, exam attachments). + +**Query params:** `context`, `user` + +**Response (200):** `[ { "name": "file.png", "url": "..." } ]` + +#### `DELETE /api/storage/{id}` + +Delete a file. + +### 4.20 Transcription Endpoint + +#### `POST /api/transcribe` + +Transcribe audio. Proxied to ielts-be. + +**Request:** Multipart form with audio file + +**Response (200):** Dialog/transcript object + +### 4.21 Approval Workflow Endpoints + +#### `GET /api/approval-workflows` + +List configured and active approval workflows. + +#### `POST /api/approval-workflows` + +Create or configure an approval workflow. + +#### `PATCH /api/approval-workflows/{id}` + +Approve or reject a workflow. + +### 4.22 Statistical Endpoint + +#### `GET /api/statistical` + +Get platform-wide statistics (admin dashboard). Proxied to ielts-be if needed. + +--- + +## 5. Authentication & Authorization + +### 5.1 Recommended Approach: Odoo Native Auth with JWT + +Use Odoo's built-in `res.users` authentication with a JWT token layer for the SPA frontend. + +**Flow:** + +1. Frontend sends `POST /api/login` with email + password +2. Odoo validates credentials against `res.users` +3. Odoo generates a JWT token (using a library like `PyJWT`) +4. Frontend stores the JWT and sends it as `Authorization: Bearer ` on every request +5. Odoo middleware validates the JWT on each request and loads the user context + +**JWT payload:** + +```json +{ + "uid": 1, + "email": "user@example.com", + "type": "student", + "exp": 1735689600 +} +``` + +**JWT secret:** Configured via Odoo system parameter `encoach.jwt_secret`. + +**Token expiry:** 24 hours (configurable). Frontend should handle token refresh. + +### 5.2 Alternative: Firebase Token Validation + +If Firebase Auth migration is too disruptive: + +1. Keep Firebase Auth for identity management +2. Frontend authenticates with Firebase, gets Firebase ID token +3. Odoo validates Firebase token using Google's public keys +4. Odoo maps Firebase UID to `res.users` via `legacy_id` field + +This approach requires maintaining Firebase Auth as a dependency. + +### 5.3 Role-Based Access Control + +Map the 7 user types to Odoo security groups: + +| User Type | Odoo Group | Access Level | +|-----------|------------|-------------| +| `student` | `encoach_group_student` | Read own data, take exams, view own stats | +| `teacher` | `encoach_group_teacher` | Manage classrooms, assignments, view student stats in their groups | +| `corporate` | `encoach_group_corporate` | Manage entity, create users, view entity-wide data | +| `admin` | `encoach_group_admin` | Full platform access | +| `developer` | `encoach_group_developer` | Full access + system tools | +| `agent` | `encoach_group_agent` | View assigned payments, agent dashboard | +| `mastercorporate` | `encoach_group_mastercorporate` | Multi-entity corporate management | + +**Record rules (`ir.rule`):** + +- Students see only their own stats, sessions, evaluations, training +- Teachers see stats/sessions for students in their groups +- Corporate users see data for their entity +- Admins see all data +- Agents see their assigned payments + +### 5.4 API-Level Authorization + +Each endpoint should validate the user's type/group before processing: + +- Endpoints that create entities, manage users globally, or access admin dashboards require `admin` or `developer` type +- Endpoints that manage classrooms and assignments require `teacher`, `corporate`, or `admin` type +- Endpoints that create payments require `corporate`, `agent`, or `admin` type +- Public endpoints (packages, tickets/create, agents) require no authentication + +--- + +## 6. ielts-be Integration Specification + +Odoo communicates with the ielts-be microservice over HTTP. The ielts-be service is unchanged and expects a Bearer JWT token for authentication. + +### 6.1 Configuration + +| Odoo System Parameter | Description | +|----------------------|-------------| +| `encoach.ielts_be_url` | Base URL of ielts-be service (e.g., `http://ielts-be:8000/api`) | +| `encoach.ielts_be_jwt` | JWT token for authenticating with ielts-be | + +### 6.2 HTTP Client + +Implement a service class `EncoachAIClient` that: + +- Uses `requests` or `httpx` for HTTP calls +- Sets `Authorization: Bearer {jwt}` header on all requests +- Handles timeouts (30s for sync, 120s for generation endpoints) +- Handles errors and retries +- Logs all requests/responses for debugging + +### 6.3 Endpoint Mapping + +#### Exam Generation + +| Odoo calls | ielts-be endpoint | Method | Request | Response | +|-----------|-------------------|--------|---------|----------| +| Generate reading passage | `GET /api/exam/reading/{passage}` | GET | Query: `topic`, `word_count` | `{ "title": "...", "text": "..." }` | +| Generate reading exercises | `POST /api/exam/reading/` | POST | `ReadingDTO` JSON | `{ "exercises": [...] }` | +| Generate listening dialog | `GET /api/exam/listening/{section}` | GET | Query: `difficulty`, `topic` | `{ "dialog": {...} }` | +| Generate listening MP3 | `POST /api/exam/listening/media` | POST | `Dialog` JSON | MP3 binary | +| Transcribe audio | `POST /api/exam/listening/transcribe` | POST | Multipart: `audio` file | Dialog object | +| Generate listening instructions | `POST /api/exam/listening/instructions` | POST | `{ "text": "..." }` | MP3 binary | +| Generate listening exercises | `POST /api/exam/listening/` | POST | `ListeningExercisesDTO` JSON | `{ "exercises": [...] }` | +| Get speaking task | `GET /api/exam/speaking/{task}` | GET | Query: `topic`, `difficulty` | Speaking content | +| Generate speaking video | `POST /api/exam/speaking/media` | POST | `{ "text": "...", "avatar": "..." }` | `{ "status": "...", "result": "..." }` | +| Poll speaking video | `GET /api/exam/speaking/media/{vid_id}` | GET | - | `{ "status": "...", "result": "url" }` | +| Get speaking avatars | `GET /api/exam/speaking/avatars` | GET | - | Avatars list | +| Get writing task | `GET /api/exam/writing/{task}` | GET | Query: `difficulty`, `topic` | Writing prompt | +| Get writing task (academic) | `POST /api/exam/writing/{task}/attachment` | POST | Multipart: `file`, `difficulty` | Writing prompt with attachment | +| Generate level exercises | `POST /api/exam/level/` | POST | `LevelExercisesDTO` JSON | Generated exercises | +| Get level exam | `GET /api/exam/level/` | GET | - | Level exam | +| Get UTAS level exam | `GET /api/exam/level/utas` | GET | - | UTAS level exam | +| Import reading exam | `POST /api/exam/reading/import` | POST | Multipart: `exercises`, `solutions` | Parsed exam | +| Import listening exam | `POST /api/exam/listening/import` | POST | Multipart: `exercises`, `solutions` | Parsed exam + dialog | +| Import level exam | `POST /api/exam/level/import/` | POST | Multipart: `exercises`, `solutions` | Parsed level exam | +| Custom level exam | `POST /api/exam/level/custom/` | POST | JSON body | Custom level exam | + +#### Grading + +| Odoo calls | ielts-be endpoint | Method | Request | Response | Async? | +|-----------|-------------------|--------|---------|----------|--------| +| Grade writing | `POST /api/exam/grade/writing/{task}` | POST | `WritingGradeTaskDTO` JSON | `200 OK` | Yes | +| Grade speaking | `POST /api/exam/grade/speaking/{task}` | POST | Multipart form | `200 OK` | Yes | +| Grade short answers | `POST /api/exam/grade/short_answers` | POST | JSON | `{ "exercises": [...] }` | No | +| Grading summary | `POST /api/exam/grade/summary` | POST | `{ "sections": [...] }` | `{ "sections": [...] }` | No | + +**Async grading flow:** + +1. Odoo creates `encoach.evaluation` record with status `pending` +2. Odoo sends grading request to ielts-be with `userId`, `sessionId`, `exerciseId` +3. ielts-be processes asynchronously and writes result directly to the shared database (current pattern) OR calls back to Odoo (new pattern) +4. Frontend polls `GET /api/evaluate/{sessionId}/{exerciseId}` until status is `completed` + +**Important decision:** Currently ielts-be writes directly to the same MongoDB. With Odoo on PostgreSQL, one of these approaches is needed: + +- **Option A (recommended):** ielts-be calls an Odoo webhook `POST /api/evaluate/callback` to update the evaluation record when grading is done. Minimal change to ielts-be -- just change where it writes the result. +- **Option B:** Odoo polls ielts-be for grading status. Requires ielts-be to expose a status endpoint. +- **Option C:** ielts-be writes to a shared message queue (Redis, RabbitMQ) and Odoo consumes it. + +#### Training + +| Odoo calls | ielts-be endpoint | Method | Request | Response | +|-----------|-------------------|--------|---------|----------| +| Get training content | `POST /api/training/` | POST | Training request JSON | `{ "id": "..." }` | +| Get tips | `POST /api/training/tips` | POST | `FetchTipsDTO` JSON | Tips text | + +#### User Import + +| Odoo calls | ielts-be endpoint | Method | Request | Response | +|-----------|-------------------|--------|---------|----------| +| Batch import users | `POST /api/user/import` | POST | `BatchUsersDTO` JSON | `{ "ok": true }` | + +**Note:** With the migration away from Firebase Auth, the batch user import flow will need to be redesigned. Instead of importing to Firebase, users should be created directly in Odoo's `res.users`. The ielts-be batch import endpoint may become unnecessary unless Firebase Auth is retained (Option B in Section 5). + +--- + +## 7. Payment Integration + +### 7.1 Stripe + +**Odoo modules:** `payment`, `payment_stripe` (standard), or custom controller. + +**Checkout flow:** + +1. Frontend calls `POST /api/stripe` with `{ email, days, key, checkout }` +2. Odoo creates a Stripe Checkout session via Stripe API +3. Returns checkout URL to frontend +4. Customer completes payment on Stripe +5. Stripe sends webhook to `POST /api/stripe/webhook` + +**Webhook handling (`POST /api/stripe/webhook`):** + +1. Verify Stripe signature +2. On `checkout.session.completed`: + - If user exists with that email: extend `subscription_expiration_date` by `days` + - If user does not exist: create/update `encoach.code` with the email and expiry info, send registration email +3. Create `encoach.subscription.payment` record + +### 7.2 PayPal + +**Create order (`POST /api/paypal`):** + +1. Call PayPal API to create order +2. Return order ID to frontend + +**Capture payment (`POST /api/paypal/approve`):** + +1. Call PayPal API to capture order +2. On success: + - Find user by tracking ID + - Calculate new expiry: `max(current_expiry, now) + duration` + - Update `subscription_expiration_date` and set `status = active` + - Create `encoach.subscription.payment` record + - For corporate users: propagate subscription to all entity participants + +### 7.3 Paymob + +**Create intention (`POST /api/paymob`):** + +1. Call Paymob API to create payment intention +2. Return client secret to frontend + +**Webhook (`POST /api/paymob/webhook`):** + +1. Verify Paymob transaction signature +2. On success: + - Find user from transaction metadata + - Extend subscription (same logic as PayPal) + - Create `encoach.subscription.payment` record + - For entity payments: update entity `expiry_date` and propagate to entity users + +### 7.4 Corporate Payment Flow + +Corporate payments are manually tracked (bank transfers, not online): + +1. Admin/agent creates `encoach.payment` record with corporate, entity, agent details +2. When payment is confirmed (`is_paid` set to `true`): + - Set corporate user's `status` to `active` + - Optionally extend entity expiry + +--- + +## 8. Business Rules & Workflows + +### 8.1 Registration Flow + +#### Individual Registration (with or without code) + +1. Validate email is not already registered +2. Create `res.users` with `encoach_type = 'student'`, `encoach_status = 'active'` +3. Set defaults: `is_first_login = True`, `is_verified = False`, `focus = 'academic'`, levels all 0, desired levels all 9 +4. If a registration `code` is provided: + a. Look up `encoach.code` by code string + b. Validate code is not expired and not already used + c. Set user's `subscription_expiration_date` from code's `expiry_date` + d. If code has an `entity_id`: add user to that entity with the default role + e. Mark code as used (`user_id` = new user) +5. Send verification email + +#### Corporate Registration + +1. Validate email is not already registered +2. Create `res.users` with `encoach_type = 'corporate'` +3. Create `encoach.entity` for the corporate +4. Create 3 default `encoach.group` records under the entity: + - "Teachers" (admin = corporate user) + - "Students" (admin = corporate user) + - "Corporate" (admin = corporate user) +5. Add the corporate user to the entity with an admin role + +### 8.2 Subscription Management + +**Status transitions:** + +``` + payment received + payment_due ────────────────────────> active + ▲ │ + │ │ subscription expired + │ ▼ + └──────────────────────────── disabled + (can be reactivated) +``` + +**Automated checks (cron job):** + +- Run daily: check all users where `subscription_expiration_date < now()` +- Set `encoach_status = 'disabled'` for expired users +- Optionally send expiry warning emails 7 days before expiry + +**Subscription extension logic:** + +```python +new_expiry = max(current_expiry or now(), now()) + timedelta(days=days) +``` + +### 8.3 Entity Licensing + +- Entities have a `licenses` count (max users) +- When adding a user to an entity, check: `current_user_count < entity.licenses` +- If limit reached, reject the addition with an error +- Entity `expiry_date` is separate from individual user subscriptions +- When entity expires, all entity users lose access (optional business rule) + +### 8.4 Assignment Lifecycle + +``` +Created ──> Started ──> In Progress ──> Released ──> Archived + │ + └──> Unarchived ──> Released +``` + +1. **Created:** Teacher creates assignment with exams and assignees +2. **Started:** `auto_start` triggers at `start_date`, or teacher manually calls `/start` +3. **In Progress:** Students can take the exams. Stats are recorded +4. **Released:** Teacher calls `/release`. Students can view their results +5. **Archived:** Teacher calls `/archive`. Assignment hidden from active lists + +### 8.5 Grading Polling + +1. Student submits writing/speaking answer +2. Frontend calls `POST /api/evaluate/writing` or `/speaking` +3. Odoo creates `encoach.evaluation` with `status = 'pending'` +4. Odoo forwards to ielts-be +5. Frontend polls `GET /api/evaluate/{sessionId}/{exerciseId}` every 3-5 seconds +6. When ielts-be finishes (via callback or direct DB update), evaluation status becomes `completed` +7. Frontend receives the grading result and displays scores + feedback + +### 8.6 Corporate Payment Activation + +1. Corporate user or agent creates payment record +2. Admin verifies bank transfer received +3. Admin updates payment: `is_paid = true` +4. System sets corporate user's `status = 'active'` +5. System extends `subscription_expiration_date` for the corporate and optionally all entity members + +### 8.7 User Change Propagation + +When a user's entity membership or subscription changes, propagate to related records: + +- When a user is added to an entity: auto-add to the entity's default group (if configured) +- When a corporate's subscription is extended: optionally extend all participants' subscriptions +- When an entity's expiry is extended: optionally extend all entity users' subscriptions + +--- + +## 9. Data Migration Plan + +### 9.1 Migration Strategy + +Perform a one-time data migration from MongoDB + Firebase Auth to Odoo 19 (PostgreSQL). + +### 9.2 Collection-to-Model Mapping + +| MongoDB Collection | Odoo Model | Notes | +|-------------------|------------|-------| +| `users` | `res.users` + `res.partner` | Map `id` (Firebase UID) to `legacy_id`. Create Odoo-native passwords. | +| `entities` | `encoach.entity` | Direct mapping | +| `roles` | `encoach.role` | Direct mapping | +| `groups` | `encoach.group` | Resolve `admin` and `participants` to Odoo user IDs via `legacy_id` | +| `reading` | `encoach.exam` (module=reading) | `parts` stored as JSON | +| `listening` | `encoach.exam` (module=listening) | `parts` stored as JSON | +| `writing` | `encoach.exam` (module=writing) | `parts` stored as JSON | +| `speaking` | `encoach.exam` (module=speaking) | `parts` stored as JSON | +| `level` | `encoach.exam` (module=level) | `parts` stored as JSON | +| `assignments` | `encoach.assignment` | Resolve user references | +| `sessions` | `encoach.session` | Resolve user and exam references | +| `stats` | `encoach.stat` | Resolve user, exam, session references | +| `evaluation` | `encoach.evaluation` | Resolve user, session references | +| `packages` | `encoach.package` | Direct mapping | +| `payments` | `encoach.payment` | Resolve user references | +| `paypalpayments` | `encoach.subscription.payment` | Resolve user references | +| `tickets` | `encoach.ticket` | Resolve user references | +| `codes` | `encoach.code` | Resolve user, entity references | +| `invites` | `encoach.invite` | Resolve user, entity references | +| `permissions` | `encoach.permission` | Resolve user references | +| `discounts` | `encoach.discount` | Direct mapping | +| `training` | `encoach.training` | Resolve user references | +| `walkthrough` | `encoach.walkthrough` | Resolve user references | +| `active-workflows` | `encoach.approval.workflow` | Direct mapping | +| `configured-workflows` | `encoach.approval.workflow` | Direct mapping | + +### 9.3 Migration Script Requirements + +1. **Export MongoDB data** to JSON files (one per collection) +2. **Resolve references:** Build a mapping of `MongoDB _id / legacy_id -> Odoo ID` as records are imported +3. **Import order:** Users first (to resolve references), then entities, roles, groups, exams, then dependent records +4. **Password migration:** + - If using Odoo native auth: generate temporary passwords and force password reset on first login + - If keeping Firebase: no password migration needed (users authenticate via Firebase) +5. **File migration:** Migrate files from Firebase Storage to Odoo `ir.attachment` or a configured file storage +6. **Validation:** After import, run integrity checks: + - All Many2one references resolve to existing records + - User counts match between MongoDB and PostgreSQL + - Exam `parts` JSON is valid and parseable + - Subscription dates are preserved correctly + +### 9.4 Suggested Import Order + +1. `res.users` / `res.partner` (from `users`) +2. `encoach.entity` (from `entities`) +3. `encoach.role` (from `roles`) +4. `encoach.user.entity.rel` (from `users.entities` array) +5. `encoach.group` (from `groups`) +6. `encoach.exam` (from `reading`, `listening`, `writing`, `speaking`, `level`) +7. `encoach.package` (from `packages`) +8. `encoach.discount` (from `discounts`) +9. `encoach.code` (from `codes`) +10. `encoach.permission` (from `permissions`) +11. `encoach.assignment` (from `assignments`) +12. `encoach.session` (from `sessions`) +13. `encoach.stat` (from `stats`) +14. `encoach.evaluation` (from `evaluation`) +15. `encoach.payment` (from `payments`) +16. `encoach.subscription.payment` (from `paypalpayments`) +17. `encoach.ticket` (from `tickets`) +18. `encoach.invite` (from `invites`) +19. `encoach.training` (from `training`) +20. `encoach.walkthrough` (from `walkthrough`) +21. `encoach.approval.workflow` (from workflows) + +--- + +## 10. Non-Functional Requirements + +### 10.1 API Response Format + +All API responses must match the JSON structure the frontend currently expects. The frontend uses Axios and SWR to consume these APIs. + +- Success responses: HTTP 200/201 with JSON body +- Error responses: HTTP 4xx/5xx with `{ "error": "Human-readable message" }` +- List responses should support pagination: `{ "items": [...], "total": N }` or flat arrays depending on the current endpoint behavior +- Empty results: return `[]` for lists, `null` or `{}` for single objects + +### 10.2 CORS Configuration + +The following origins need CORS access: + +| Origin | Endpoints | +|--------|-----------| +| `https://platform.encoach.com` | All authenticated endpoints | +| `https://encoach.com` | `GET /api/packages`, `POST /api/tickets`, `GET /api/users/agents` | +| `http://localhost:3000` | All (development) | + +CORS headers must include: +- `Access-Control-Allow-Origin` (per origin, not `*`) +- `Access-Control-Allow-Credentials: true` +- `Access-Control-Allow-Methods: GET, POST, PATCH, DELETE, OPTIONS` +- `Access-Control-Allow-Headers: Content-Type, Authorization` + +### 10.3 File Storage + +Replace Firebase Storage with Odoo's `ir.attachment` system or configure an external storage backend (S3, GCS). + +**Files stored:** +- User profile pictures +- Exam audio files (listening MP3s) +- Exam image attachments (writing Task 1 charts) +- Speaking video files +- PDF reports + +**Requirements:** +- Files must be accessible via URL (for the frontend to load) +- Support for audio (MP3), image (PNG/JPG), video (MP4), and PDF formats +- Maximum file size: 50 MB (audio/video), 10 MB (images), 5 MB (PDFs) + +### 10.4 Performance Requirements + +| Operation | Target Response Time | +|-----------|---------------------| +| Login / Auth | < 500ms | +| User list (paginated) | < 1s | +| Exam load (full JSON) | < 2s | +| Stat creation | < 500ms | +| Evaluation poll | < 300ms | +| Package list (public) | < 500ms | +| Ticket creation | < 500ms | +| File upload | < 5s (for files < 10 MB) | + +**Grading latency** is handled by ielts-be and is inherently slow (10-30s for writing, 30-60s for speaking). The polling pattern handles this. + +### 10.5 Scalability + +- Support at least 10,000 concurrent users +- Support 500,000+ stat records per exam module +- Efficient pagination for all list endpoints +- JSON fields (exam `parts`, solutions) indexed appropriately in PostgreSQL + +### 10.6 Security + +- All API communication over HTTPS in production +- JWT tokens with short expiry (24h) and secure signing +- Rate limiting on login endpoint (max 10 attempts per minute per IP) +- Input validation on all endpoints (prevent SQL injection, XSS) +- Stripe/PayPal/Paymob webhook signature verification +- No sensitive data in JWT payload (no passwords, no payment details) + +### 10.7 Logging & Monitoring + +- Log all API requests with timestamp, user, endpoint, response status +- Log all ielts-be integration calls with request/response +- Log all payment events +- Error alerting for failed grading callbacks, payment failures + +### 10.8 Testing + +- Unit tests for all business logic (registration, subscription, payments) +- Integration tests for all API endpoints +- End-to-end tests for critical flows (login -> take exam -> get graded) +- Load tests for concurrent exam-taking scenarios + +--- + +## Appendix A: Exercise Type Reference + +Complete list of exercise types used across all exam modules. + +### Reading Exercise Types + +| Type | Fields | Description | +|------|--------|-------------| +| `multipleChoice` | `questions[]` with `prompt`, `options[]`, `solution` | Select correct answer | +| `trueFalse` | `questions[]` with `prompt`, `solution` (TRUE/FALSE/NOT_GIVEN) | True/False/Not Given | +| `fillBlanks` | `text`, `solutions[]`, `words[]`, `allowRepetition` | Drag words into blanks | +| `writeBlanks` | `text`, `maxWords`, `solutions[]` | Type answers into blanks | +| `matchSentences` (HEADING) | `options[]`, `sentences[]` with `solution` | Match headings to paragraphs | +| `matchSentences` (IDEAMATCH) | `options[]`, `sentences[]` with `solution` | Match ideas to paragraphs | + +### Listening Exercise Types + +| Type | Fields | Description | +|------|--------|-------------| +| `multipleChoice` | `questions[]` | Standard MC | +| `multipleChoice3Options` | `questions[]` | MC with 3 options | +| `writeBlanks` (FILL) | `text`, `maxWords`, `solutions[]` | Fill in blanks from audio | +| `writeBlanks` (FORM) | `questions[]`, `maxWords` | Complete a form from audio | +| `writeBlanks` (QUESTIONS) | `questions[]`, `maxWords` | Answer questions from audio | +| `trueFalse` | `questions[]` | True/False from audio | + +### Writing Exercise Types + +| Type | Fields | Description | +|------|--------|-------------| +| `writing` (task 1) | `prompt`, optional `attachment` | Letter or chart description | +| `writing` (task 2) | `prompt` | Essay | + +### Speaking Exercise Types + +| Type | Fields | Description | +|------|--------|-------------| +| `interactiveSpeaking` (part 1) | `prompts[]` | Short Q&A | +| `speaking` (part 2) | `text` | Long turn monologue | +| `interactiveSpeaking` (part 3) | `prompts[]` | Discussion | + +### Level Exercise Types + +| Type | Fields | Description | +|------|--------|-------------| +| `multipleChoice` | `questions[]` with `variant` | MC with text/image variants | +| `fillBlanks` (mc) | `text`, `solutions[]`, `words[]` | Fill blanks with MC options | + +--- + +## Appendix B: Grading Rubric Details + +### Writing Rubric (IELTS Band Descriptors) + +| Criterion | Scale | Description | +|-----------|-------|-------------| +| Task Achievement / Task Response | 0-9 | How well the task requirements are addressed | +| Coherence and Cohesion | 0-9 | Logical organization and paragraph linking | +| Lexical Resource | 0-9 | Vocabulary range and accuracy | +| Grammatical Range and Accuracy | 0-9 | Grammar variety and correctness | +| **Overall** | 0-9 | Average of the four criteria | + +### Speaking Rubric (IELTS Band Descriptors) + +| Criterion | Scale | Description | +|-----------|-------|-------------| +| Fluency and Coherence | 0-9 | Flow, pace, logical connection | +| Lexical Resource | 0-9 | Vocabulary range and appropriateness | +| Grammatical Range and Accuracy | 0-9 | Grammar variety and correctness | +| Pronunciation | 0-9 | Clarity, stress, intonation | +| **Overall** | 0-9 | Average of the four criteria | + +--- + +## Appendix C: Environment Variables + +| Variable | Description | Example | +|----------|-------------|---------| +| `ENCOACH_JWT_SECRET` | JWT signing secret | Random 256-bit string | +| `ENCOACH_IELTS_BE_URL` | ielts-be base URL | `http://ielts-be:8000/api` | +| `ENCOACH_IELTS_BE_JWT` | JWT for ielts-be auth | Pre-shared token | +| `STRIPE_SECRET_KEY` | Stripe secret key | `sk_live_...` | +| `STRIPE_WEBHOOK_SECRET` | Stripe webhook signing secret | `whsec_...` | +| `PAYPAL_CLIENT_ID` | PayPal client ID | `AX...` | +| `PAYPAL_CLIENT_SECRET` | PayPal client secret | `EL...` | +| `PAYPAL_ACCESS_TOKEN_URL` | PayPal OAuth URL | `https://api.paypal.com/v1/oauth2/token` | +| `PAYMOB_API_KEY` | Paymob API key | `ZXlK...` | +| `PAYMOB_SECRET` | Paymob webhook secret | `...` | + +--- + +## Appendix D: Glossary + +| Term | Definition | +|------|-----------| +| **Entity** | An organization (school, company) that manages users under a shared license | +| **Group** | A classroom or user grouping within an entity | +| **Module** | An IELTS exam skill: Reading, Listening, Writing, Speaking, or Level | +| **Session** | A single exam-taking attempt by a student | +| **Stat** | The result of a single exercise attempt within a session | +| **Evaluation** | An AI-graded writing or speaking assessment | +| **Code** | A registration/invite code that grants access or subscription time | +| **Package** | A purchasable subscription plan | +| **ielts-be** | The AI/ML microservice that handles content generation and grading | +| **BFF** | Backend-for-Frontend; the current ielts-ui API routes layer being replaced | diff --git a/docs/ODOO_MIGRATION_SRS_v2.md b/docs/ODOO_MIGRATION_SRS_v2.md index ade8095..92f5e9a 100644 --- a/docs/ODOO_MIGRATION_SRS_v2.md +++ b/docs/ODOO_MIGRATION_SRS_v2.md @@ -1,10 +1,12 @@ # EnCoach Platform -- Odoo 19 Full Migration SRS (v2) +> **SUPERSEDED** -- This document has been replaced by `ENCOACH_ODOO19_BACKEND_SRS.md` (v3.0) and `ENCOACH_UNIFIED_SRS.md` (v2.0). All content below is historical. The migration is complete and the system is deployed at `http://5.189.151.117:8069`. + ## Software Requirements Specification **Version:** 2.0 **Date:** March 11, 2026 -**Status:** Draft +**Status:** ~~Draft~~ **SUPERSEDED** **Supersedes:** ODOO_MIGRATION_SRS.md (v1) **Key change from v1:** The ielts-be (FastAPI) microservice is fully eliminated. All AI/ML functionality is absorbed into custom Odoo modules.