# EnCoach Platform — Odoo 19 Backend SRS **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). --- ## Table of Contents 1. [Introduction](#1-introduction) 2. [Architecture Overview](#2-architecture-overview) 3. [OpenEduCat Integration Strategy](#3-openeducat-integration-strategy) 4. [Module Inventory](#4-module-inventory) 5. [Authentication and User Management](#5-authentication-and-user-management) 6. [Entity and Permission System](#6-entity-and-permission-system) 7. [LMS Core (OpenEduCat Bridge)](#7-lms-core-openeducat-bridge) 8. [Academic Year, Term, and Department](#8-academic-year-term-and-department) 9. [Admission and Enrollment](#9-admission-and-enrollment) 10. [Subject Registration](#10-subject-registration) 11. [Exam Engine (EnCoach AI)](#11-exam-engine-encoach-ai) 12. [Institutional Exams (OpenEduCat)](#12-institutional-exams-openeducat) 13. [Assignment System](#13-assignment-system) 14. [Course Assignment Submissions (OpenEduCat)](#14-course-assignment-submissions-openeducat) 15. [Classroom and Group Management](#15-classroom-and-group-management) 16. [Subject Taxonomy Engine](#16-subject-taxonomy-engine) 17. [Adaptive Learning Engine](#17-adaptive-learning-engine) 18. [Learning Resources](#18-learning-resources) 19. [AI Services](#19-ai-services) 20. [Training Content](#20-training-content) 21. [Analytics and Statistics](#21-analytics-and-statistics) 22. [Subscription and Payments](#22-subscription-and-payments) 23. [Support Tickets](#23-support-tickets) 24. [File Storage](#24-file-storage) 25. [Approval Workflows (Enhanced)](#25-approval-workflows-enhanced) 26. [Courseware and Content Delivery](#26-courseware-and-content-delivery) 27. [Communication System](#27-communication-system) 28. [Notification Engine](#28-notification-engine) 29. [FAQ System](#29-faq-system) 30. [Plagiarism Detection](#30-plagiarism-detection) 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) --- ## 1. Introduction ### 1.1 Scope This document specifies the complete Odoo 19 backend for the EnCoach Adaptive Learning Platform. The backend serves a React SPA frontend via REST API. All endpoints use JSON request/response with JWT authentication (except explicitly public endpoints). ### 1.2 Frontend Contract The React frontend has 29 API service modules that define the exact endpoints the backend must implement. This SRS documents every endpoint, its expected request/response shape, and the underlying Odoo models. ### 1.3 Key Principles - **OpenEduCat First:** All traditional LMS features (courses, batches, students, faculty, timetable, attendance, exams, assignments, admissions) use OpenEduCat community modules ported to Odoo 19. - **EnCoach Extensions:** Custom modules extend OpenEduCat models with fields the platform needs (e.g., `description`, `image`, `max_capacity` on `op.course`). - **REST API Layer:** All data is exposed via REST controllers in `encoach_api` and `encoach_lms_api` modules. The frontend never uses Odoo's web client or XML-RPC. - **AI Services:** AI functionality (GPT, Whisper, Polly, ELAI, GPTZero, FAISS) is encapsulated in dedicated `encoach_ai_*` modules with API endpoints. --- ## 2. Architecture Overview ``` React SPA (Vite + TypeScript) │ ▼ REST API (JSON + JWT) ┌─────────────────────────────────┐ │ Odoo 19 Server │ │ │ │ ┌──────────┐ ┌──────────────┐ │ │ │ encoach_ │ │ OpenEduCat │ │ │ │ modules │ │ (ported v19)│ │ │ └──────────┘ └──────────────┘ │ │ │ │ │ │ ▼ ▼ │ │ PostgreSQL 16 │ └─────────────────────────────────┘ │ ▼ External Services OpenAI API │ AWS Polly │ ELAI │ GPTZero ``` ### 2.1 Technology Stack | Layer | Technology | |-------|-----------| | Framework | Odoo 19 Community Edition | | Language | Python 3.12+ | | Database | PostgreSQL 16 | | LMS Foundation | OpenEduCat (ported from v17 to v19) | | AI/ML | OpenAI GPT-4o, Whisper (local), AWS Polly, Sentence Transformers, FAISS | | Authentication | JWT (PyJWT) | | File Storage | Odoo ir.attachment + optional S3 | | Deployment | Docker, Docker Compose | --- ## 3. OpenEduCat Integration Strategy ### 3.1 Modules to Port (v17 → v19) | Module | Models | Porting Notes | |--------|--------|---------------| | `openeducat_core` | `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` | Core dependency for all other modules | | `openeducat_timetable` | `op.session`, `op.timing` | Depends on `openeducat_core` | | `openeducat_attendance` | `op.attendance.register`, `op.attendance.sheet`, `op.attendance.line`, `op.attendance.type` | Depends on `openeducat_core`, `openeducat_timetable` | | `openeducat_classroom` | `op.classroom` | Depends on `openeducat_facility` | | `openeducat_facility` | `op.facility`, `op.facility.line` | Dependency of classroom | | `openeducat_exam` | `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` | Depends on `openeducat_core` | | `openeducat_assignment` | `op.assignment`, `op.assignment.sub.line`, `grading.assignment`, `grading.assignment.type` | Depends on `openeducat_core` | | `openeducat_admission` | `op.admission`, `op.admission.register` | Depends on `openeducat_core` | ### 3.2 Model Extensions (via `encoach_lms_api`) The `encoach_lms_api` module uses `_inherit` to add fields missing from OpenEduCat but required by the frontend: | Model | Added Fields | |-------|-------------| | `op.course` | `description` (Text), `image` (Binary), `max_capacity` (Integer), `status` (Selection: draft/active/archived), `department_id` (Many2one to `op.department`) | | `op.batch` | `max_students` (Integer), `status` (Selection: draft/active/completed) | | `op.student` | `enrollment_date` (Date), `status` (Selection: active/inactive/graduated/suspended) | | `op.faculty` | `department_id` (Many2one to `op.department`), `specialization` (Char) | | `op.subject` | `credits` (Float), `department_id` (Many2one to `op.department`) | ### 3.3 Serialization All OpenEduCat models need `to_api_dict()` methods on the `encoach_lms_api` inheriting models that convert records to JSON-serializable dictionaries with snake_case keys. Many2one fields are serialized as `{field}_id` (integer) and `{field}_name` (string). --- ## 4. Module Inventory | # | Module | Type | Description | |---|--------|------|-------------| | 1 | `openeducat_core` | OpenEduCat (port v19) | Course, batch, student, faculty, subject, department, academic year/term | | 2 | `openeducat_timetable` | OpenEduCat (port v19) | Timetable sessions and timings | | 3 | `openeducat_attendance` | OpenEduCat (port v19) | Attendance sheets, lines, registers | | 4 | `openeducat_classroom` | OpenEduCat (port v19) | Physical classrooms | | 5 | `openeducat_facility` | OpenEduCat (port v19) | Facility management | | 6 | `openeducat_exam` | OpenEduCat (port v19) | Institutional exam sessions, marksheets, grading | | 7 | `openeducat_assignment` | OpenEduCat (port v19) | Course assignments and submissions | | 8 | `openeducat_admission` | OpenEduCat (port v19) | Admission registers and applications | | 9 | `encoach_core` | Custom | `encoach.user` extensions on `res.users`, entities, roles, permissions, codes, invites | | 10 | `encoach_api` | Custom | REST API controllers for auth, users, entities, permissions, exams, assignments, classrooms, tickets, subscriptions, stats, storage, approvals | | 11 | `encoach_lms_api` | Custom | REST API bridge for OpenEduCat models (courses, batches, timetable, attendance, grades, academic years, departments, admissions, subject registration, institutional exams, marksheets, course assignments) | | 12 | `encoach_ai` | Custom | OpenAI service wrapper, token counting, blacklist, system parameter management | | 13 | `encoach_ai_media` | Custom | TTS (AWS Polly), STT (Whisper), ELAI avatar video generation | | 14 | `encoach_ai_generation` | Custom | AI exam content generation for all subjects | | 15 | `encoach_ai_grading` | Custom | AI grading for writing, speaking, math, IT | | 16 | `encoach_exam` | Custom | `encoach.exam` model for AI-powered exams | | 17 | `encoach_assignment` | Custom | `encoach.assignment` model (exam-wrapper assignments) | | 18 | `encoach_evaluation` | Custom | Evaluation job tracking | | 19 | `encoach_stats` | Custom | Session tracking and statistics | | 20 | `encoach_training` | Custom | Training tips, walkthroughs, FAISS embeddings | | 21 | `encoach_classroom` | Custom | `encoach.classroom.group` for virtual classrooms | | 22 | `encoach_subscription` | Custom | Packages, payments, discounts, Stripe/PayPal/Paymob | | 23 | `encoach_registration` | Custom | User registration and batch import | | 24 | `encoach_ticket` | Custom | Support tickets | | 25 | `encoach_taxonomy` | Custom | Subject, domain, topic, learning objective models | | 26 | `encoach_resources` | Custom | Learning resource library | | 27 | `encoach_adaptive` | Custom | Proficiency tracking, learning plans, progress, content cache | | 28 | `encoach_adaptive_api` | Custom | REST controllers for adaptive learning | | 29 | `encoach_adaptive_ai` | Custom | AI services for diagnostics, plan generation, coaching, content generation | | 30 | `encoach_sis` | Custom | UTAS SIS integration (sync, mapping) | | 31 | `encoach_branding` | Custom | Whitelabeling configuration | | 32 | `encoach_courseware` | Custom | Course chapters, chapter materials, chapter progress tracking, AI workbench for content generation | | 33 | `encoach_communication` | Custom | Discussion boards, threaded posts, announcements, direct messaging | | 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 | **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** --- ## 5. Authentication and User Management ### 5.1 Authentication Model JWT-based authentication. Tokens are issued on login and validated on every API request. ### 5.2 User Model Extends `res.users` with `encoach.user` mixin: | Field | Type | Description | |-------|------|-------------| | `user_type` | Selection | `student`, `teacher`, `admin`, `corporate`, `mastercorporate`, `agent`, `developer` | | `is_verified` | Boolean | Email verification status | | `entity_ids` | Many2many | Associated entities | | `phone` | Char | Phone number | | `birth_date` | Date | Date of birth | | `gender` | Selection | `m`, `f`, `o` | | `op_student_id` | Many2one | Link to `op.student` if user_type is student | | `op_faculty_id` | Many2one | Link to `op.faculty` if user_type is teacher | ### 5.3 API Endpoints | Method | Path | Auth | Description | |--------|------|------|-------------| | `POST` | `/api/login` | Public | Authenticate user, return JWT + user object | | `POST` | `/api/logout` | JWT | Invalidate token | | `GET` | `/api/user` | JWT | Get current authenticated user | | `POST` | `/api/reset/sendVerification` | Public | Send password reset / verification email | | `GET` | `/api/users/list` | JWT | Paginated user list with filters (`type`, `entity_id`, `page`, `size`) | | `GET` | `/api/users/{id}` | JWT | Get user by ID | | `PATCH` | `/api/users/update` | JWT | Update user (id in body) | | `POST` | `/api/users/create` | JWT | Create user | | `POST` | `/api/batch_users` | JWT | Batch create users from CSV/JSON | | `GET` | `/api/users/export` | JWT | Export users as CSV blob | ### 5.4 Login Response Shape ```json { "token": "eyJ...", "user": { "id": 1, "name": "John Doe", "email": "john@example.com", "user_type": "admin", "is_verified": true, "entities": [ { "id": 1, "name": "UTAS", "logo": "..." } ] } } ``` --- ## 6. Entity and Permission System ### 6.1 Entity Model (`encoach.entity`) | Field | Type | Description | |-------|------|-------------| | `name` | Char | Entity name | | `code` | Char | Unique code | | `type` | Selection | `corporate`, `university`, `freelance` | | `logo` | Binary | Entity logo | | `active` | Boolean | Active status | | `user_ids` | Many2many | Members | | `role_ids` | One2many | Custom roles | ### 6.2 Role and Permission Models **`encoach.role`** | Field | Type | Description | |-------|------|-------------| | `name` | Char | Role name | | `entity_id` | Many2one | Parent entity | | `permission_ids` | Many2many | Assigned permissions | **`encoach.permission`** 77+ entity-scoped permissions (e.g., `view_students`, `edit_exam`, `view_payment_record`, `manage_entities`). ### 6.3 API Endpoints | Method | Path | Auth | Description | |--------|------|------|-------------| | `GET` | `/api/entities` | JWT | Paginated entities | | `GET` | `/api/entities/{id}` | JWT | Entity detail | | `POST` | `/api/entities` | JWT | Create entity | | `PATCH` | `/api/entities/{id}` | JWT | Update entity | | `DELETE` | `/api/entities/{id}` | JWT | Delete entity | | `GET` | `/api/entities/{entityId}/roles` | JWT | Roles for entity | | `POST` | `/api/entities/{entityId}/roles` | JWT | Create role | | `PATCH` | `/api/roles/{roleId}/permissions` | JWT | Update role permissions | | `GET` | `/api/permissions` | JWT | List permissions (filter by `entity_id`) | --- ## 7. LMS Core (OpenEduCat Bridge) ### 7.1 Course API Backed by `op.course` (extended via `_inherit` in `encoach_lms_api`). | Method | Path | Auth | Description | |--------|------|------|-------------| | `GET` | `/api/courses` | JWT | Paginated courses (filter: `status`, `department_id`) | | `GET` | `/api/courses/{id}` | JWT | Course detail with subjects, batches | | `POST` | `/api/courses` | JWT | Create course | | `PATCH` | `/api/courses/{id}` | JWT | Update course | | `DELETE` | `/api/courses/{id}` | JWT | Delete course | | `POST` | `/api/courses/ai-generate` | JWT | AI-generate course outline (calls OpenAI) | **Course Response Shape:** ```json { "id": 1, "name": "IELTS Preparation", "code": "IELTS-101", "description": "Comprehensive IELTS preparation course", "department_id": 1, "department_name": "English", "max_capacity": 30, "status": "active", "subject_ids": [1, 2, 3], "subject_names": ["Reading", "Writing", "Listening"], "batch_count": 2, "student_count": 45, "image": "base64..." } ``` ### 7.2 Batch API Backed by `op.batch` (extended). | Method | Path | Auth | Description | |--------|------|------|-------------| | `GET` | `/api/batches` | JWT | Paginated batches (filter: `course_id`, `status`) | | `GET` | `/api/batches/{id}` | JWT | Batch detail with student list | | `POST` | `/api/batches` | JWT | Create batch | | `PATCH` | `/api/batches/{id}` | JWT | Update batch | | `DELETE` | `/api/batches/{id}` | JWT | Delete batch | ### 7.3 Timetable API Backed by `op.session` and `op.timing`. | Method | Path | Auth | Description | |--------|------|------|-------------| | `GET` | `/api/timetable` | JWT | Sessions (filter: `course_id`, `batch_id`, `faculty_id`, `start_date`, `end_date`) | | `POST` | `/api/timetable` | JWT | Create timetable session | **Session Response Shape:** ```json { "id": 1, "name": "IELTS Reading - Week 1", "course_id": 1, "course_name": "IELTS Preparation", "batch_id": 1, "batch_name": "Batch A", "faculty_id": 5, "faculty_name": "Dr. Smith", "subject_id": 1, "subject_name": "Reading", "classroom_id": 3, "classroom_name": "Room 101", "start_datetime": "2026-03-15T09:00:00", "end_datetime": "2026-03-15T10:30:00", "day": "Monday" } ``` ### 7.4 Attendance API Backed by `op.attendance.sheet` and `op.attendance.line`. | Method | Path | Auth | Description | |--------|------|------|-------------| | `GET` | `/api/attendance` | JWT | Attendance records (filter: `course_id`, `batch_id`, `student_id`, `date_from`, `date_to`) | | `POST` | `/api/attendance` | JWT | Record attendance (batch of student attendance lines) | **Attendance Record Request:** ```json { "session_id": 1, "attendance_date": "2026-03-15", "lines": [ { "student_id": 1, "present": true }, { "student_id": 2, "present": false, "remark": "Sick leave" } ] } ``` ### 7.5 Grades API | Method | Path | Auth | Description | |--------|------|------|-------------| | `GET` | `/api/grades` | JWT | Grade records (filter: `student_id`, `course_id`, `batch_id`) | --- ## 8. Academic Year, Term, and Department ### 8.1 Academic Year and Term Backed by `op.academic.year` and `op.academic.term` (OpenEduCat core). | Method | Path | Auth | Description | |--------|------|------|-------------| | `GET` | `/api/academic-years` | JWT | List academic years with terms | | `GET` | `/api/academic-years/{id}` | JWT | Year detail with terms | | `POST` | `/api/academic-years` | JWT | Create academic year | | `PATCH` | `/api/academic-years/{id}` | JWT | Update year | | `DELETE` | `/api/academic-years/{id}` | JWT | Delete year | | `POST` | `/api/academic-years/{id}/generate-terms` | JWT | Auto-generate terms from `term_structure` | | `GET` | `/api/academic-terms` | JWT | List terms (filter: `year_id`) | | `POST` | `/api/academic-terms` | JWT | Create term | | `PATCH` | `/api/academic-terms/{id}` | JWT | Update term | | `DELETE` | `/api/academic-terms/{id}` | JWT | Delete term | **Generate Terms Logic:** Given `term_structure` on the academic year, compute term dates: - `two_sem`: 2 terms splitting the year in half - `two_sem_qua`: 2 semesters, each with 2 quarters (4 terms total) - `three_sem`: 3 trimesters - `four_Quarter`: 4 quarters - `final_year`: single term spanning the full year ### 8.2 Department Backed by `op.department` (OpenEduCat core). | Method | Path | Auth | Description | |--------|------|------|-------------| | `GET` | `/api/departments` | JWT | List departments | | `POST` | `/api/departments` | JWT | Create department | | `PATCH` | `/api/departments/{id}` | JWT | Update department | | `DELETE` | `/api/departments/{id}` | JWT | Delete department | **Department Response:** ```json { "id": 1, "name": "Department of Mathematics", "code": "MATH", "parent_id": null, "parent_name": null, "course_count": 5, "faculty_count": 12 } ``` --- ## 9. Admission and Enrollment ### 9.1 Admission Register Backed by `op.admission.register` (OpenEduCat). | Method | Path | Auth | Description | |--------|------|------|-------------| | `GET` | `/api/admission-registers` | JWT | List registers | | `POST` | `/api/admission-registers` | JWT | Create register | | `PATCH` | `/api/admission-registers/{id}` | JWT | Update register | | `POST` | `/api/admission-registers/{id}/confirm` | JWT | Confirm register (opens enrollment) | | `POST` | `/api/admission-registers/{id}/close` | JWT | Close register | ### 9.2 Admission Backed by `op.admission` (OpenEduCat). | Method | Path | Auth | Description | |--------|------|------|-------------| | `GET` | `/api/admissions` | JWT | List admissions (filter: `state`, `register_id`, `course_id`, `page`, `size`) | | `GET` | `/api/admissions/{id}` | JWT | Admission detail | | `POST` | `/api/admissions` | Public* | Submit admission application | | `POST` | `/api/admissions/{id}/submit` | JWT | Submit for review | | `POST` | `/api/admissions/{id}/confirm` | JWT | Confirm admission | | `POST` | `/api/admissions/{id}/admit` | JWT | Admit applicant | | `POST` | `/api/admissions/{id}/reject` | JWT | Reject admission | *Note: `POST /api/admissions` is public when submitted via the `/apply` page. Backend should allow unauthenticated submission when the register allows public applications. ### 9.3 Admit Action Logic When an admission is admitted (`/admit`): 1. Create `op.student` record from admission data 2. Create `res.users` record with `user_type=student` 3. Create `op.student.course` linking student to course/batch 4. Set `admission.student_id` to the new student 5. Set `admission.state` to `admission` 6. Send welcome email with login credentials --- ## 10. Subject Registration ### 10.1 Model Backed by `op.subject.registration` (OpenEduCat core). ### 10.2 API Endpoints | Method | Path | Auth | Description | |--------|------|------|-------------| | `GET` | `/api/subject-registrations` | JWT | List registrations (filter: `student_id`, `course_id`, `state`) | | `POST` | `/api/subject-registrations` | JWT | Create registration | | `PATCH` | `/api/subject-registrations/{id}` | JWT | Update selected subjects | | `POST` | `/api/subject-registrations/{id}/confirm` | JWT | Confirm registration | | `POST` | `/api/subject-registrations/{id}/reject` | JWT | Reject registration | | `GET` | `/api/subject-registrations/available` | JWT | Get available subjects for current student's enrolled courses | ### 10.3 Available Subjects Logic For the current user (student): 1. Find all `op.student.course` records for this student 2. Get subjects linked to those courses 3. Exclude subjects already registered in confirmed registrations 4. Check unit load limits from `op.course` configuration 5. Return list with `min_unit_load`, `max_unit_load` --- ## 11. Exam Engine (EnCoach AI) ### 11.1 Model (`encoach.exam`) | Field | Type | Description | |-------|------|-------------| | `name` | Char | Exam title | | `module` | Selection | `reading`, `writing`, `listening`, `speaking`, `math`, `it`, ... | | `subject_id` | Many2one | Link to `encoach.subject` (taxonomy) | | `topic_ids` | Many2many | Link to `encoach.topic` | | `entity_id` | Many2one | Owning entity | | `structure_id` | Many2one | Exam structure template | | `rubric_id` | Many2one | Grading rubric | | `exercises` | Text (JSON) | Generated exercises content | | `is_public` | Boolean | Public access flag | | `status` | Selection | `draft`, `published`, `archived` | ### 11.2 API Endpoints | Method | Path | Auth | Description | |--------|------|------|-------------| | `GET` | `/api/exam/{module}` | JWT | List exams for module (paginated) | | `GET` | `/api/exam/{module}/{id}` | JWT | Exam detail | | `POST` | `/api/exam` | JWT | Create exam | | `PATCH` | `/api/exam/{id}` | JWT | Update exam | | `DELETE` | `/api/exam/{id}` | JWT | Delete exam | | `PATCH` | `/api/exam/{id}/access` | JWT | Set public/private | | `GET` | `/api/rubrics` | JWT | List rubrics (paginated) | | `POST` | `/api/rubrics` | JWT | Create rubric | | `GET` | `/api/rubric-groups` | JWT | List rubric groups | | `GET` | `/api/exam-structures` | JWT | List exam structures | | `POST` | `/api/exam-structures` | JWT | Create exam structure | | `DELETE` | `/api/exam-structures/{id}` | JWT | Delete structure | | `GET` | `/api/exam/avatars` | JWT | List ELAI avatars | | `POST` | `/api/exam/{module}/generate` | JWT | Generate exercises from existing exam | | `POST` | `/api/exam/{module}/generate/scratch` | JWT | Generate full exam from scratch | ### 11.3 Generation Logic Uses OpenAI GPT-4o to generate exam content. Prompt templates vary by module: - **Reading/Listening:** Passage + comprehension questions - **Writing:** Task description + sample topics - **Speaking:** Dialogue prompts + follow-up questions - **Math:** Problem sets with numerical answers, configurable difficulty - **IT:** Code completion, debugging, conceptual questions --- ## 12. Institutional Exams (OpenEduCat) ### 12.1 Overview Traditional institutional exams (midterms, finals) managed through OpenEduCat. Separate from EnCoach AI exams. ### 12.2 API Endpoints | Method | Path | Auth | Description | |--------|------|------|-------------| | `GET` | `/api/inst-exam-sessions` | JWT | List exam sessions | | `POST` | `/api/inst-exam-sessions` | JWT | Create session | | `GET` | `/api/inst-exam-sessions/{id}` | JWT | Session detail with exams | | `PATCH` | `/api/inst-exam-sessions/{id}` | JWT | Update session | | `DELETE` | `/api/inst-exam-sessions/{id}` | JWT | Delete session | | `POST` | `/api/inst-exam-sessions/{id}/schedule` | JWT | Schedule session | | `POST` | `/api/inst-exam-sessions/{id}/done` | JWT | Mark session done | | `POST` | `/api/inst-exams` | JWT | Add exam to session | | `PATCH` | `/api/inst-exams/{id}` | JWT | Update exam | | `POST` | `/api/inst-exams/{id}/attendees` | JWT | Add attendees to exam | | `PATCH` | `/api/inst-exams/{id}/marks` | JWT | Enter marks for attendees | | `GET` | `/api/exam-types` | JWT | List exam types | | `POST` | `/api/exam-types` | JWT | Create exam type | | `GET` | `/api/grade-config` | JWT | List grade configurations | | `POST` | `/api/grade-config` | JWT | Create grade config | | `GET` | `/api/result-templates` | JWT | List result templates | | `POST` | `/api/result-templates` | JWT | Create result template | | `POST` | `/api/result-templates/{id}/generate` | JWT | Generate marksheets | | `GET` | `/api/marksheets` | JWT | List marksheets | | `GET` | `/api/marksheets/{id}` | JWT | Marksheet detail with student results | | `POST` | `/api/marksheets/{id}/validate` | JWT | Validate marksheet | ### 12.3 Enter Marks Request ```json { "attendees": [ { "student_id": 1, "marks": 85 }, { "student_id": 2, "marks": 72 } ] } ``` ### 12.4 Generate Marksheets Logic 1. Create `op.marksheet.register` from `op.result.template` 2. For each student in the batch: - Create `op.marksheet.line` - For each exam in the session: create `op.result.line` with marks from `op.exam.attendees` - Compute total marks, percentage - If evaluation_type is `grade`: lookup `op.grade.configuration` to assign grade - Compute pass/fail from `min_marks` on each exam 3. Compute `total_pass` and `total_failed` on register --- ## 13. Assignment System (EnCoach AI) ### 13.1 Model (`encoach.assignment`) Exam-wrapper assignments where an EnCoach exam is assigned to students/classrooms. ### 13.2 Enhanced Fields (Late Submission + Plagiarism) Add to `encoach.assignment`: | Field | Type | Description | |-------|------|-------------| | `late_deadline` | Datetime | Final late submission cutoff | | `penalty_type` | Selection | `none`, `percentage`, `fixed_deduction` | | `penalty_value` | Float | Penalty amount | | `max_submissions` | Integer | Maximum allowed submissions (0 = unlimited) | | `allow_extensions` | Boolean | Student extension requests | | `plagiarism_enabled` | Boolean | Enable GPTZero plagiarism check | | `plagiarism_max_checks` | Integer | Max plagiarism checks per submission | | `reminder_count` | Integer | Number of reminders | | `reminder_frequency` | Selection | `once`, `daily`, `custom` | ### 13.3 Extension Request Model (`encoach.extension.request`) | Field | Type | Description | |-------|------|-------------| | `student_id` | Many2one (`res.users`) | Requesting student | | `assignment_id` | Many2one | Target assignment | | `reason` | Text | Justification | | `requested_date` | Datetime | New deadline | | `status` | Selection | `pending`, `approved`, `rejected` | | `approved_by` | Many2one | Approving teacher | | `response_note` | Text | Teacher response | ### 13.4 API Endpoints | Method | Path | Auth | Description | |--------|------|------|-------------| | `GET` | `/api/assignments` | JWT | Paginated assignments | | `GET` | `/api/assignments/{id}` | JWT | Assignment detail | | `POST` | `/api/assignments` | JWT | Create assignment (includes late submission fields) | | `PATCH` | `/api/assignments/{id}` | JWT | Update assignment | | `DELETE` | `/api/assignments/{id}` | JWT | Delete assignment | | `POST` | `/api/assignments/{id}/archive` | JWT | Archive assignment | | `POST` | `/api/assignments/{id}/start` | JWT | Start assignment (student) | | `POST` | `/api/assignments/{id}/request-extension` | JWT (student) | Request deadline extension | | `GET` | `/api/assignments/{id}/extension-requests` | JWT (teacher) | List extension requests | | `POST` | `/api/extension-requests/{id}/respond` | JWT (teacher) | Approve/reject extension | --- ## 14. Course Assignment Submissions (OpenEduCat) ### 14.1 Overview Traditional file-based assignments where students upload work and teachers grade it. Uses OpenEduCat models. ### 14.2 API Endpoints | Method | Path | Auth | Description | |--------|------|------|-------------| | `GET` | `/api/course-assignments` | JWT | List course assignments (filter: `course_id`, `batch_id`, `state`) | | `POST` | `/api/course-assignments` | JWT | Create course assignment | | `GET` | `/api/course-assignments/{id}` | JWT | Assignment detail with submissions | | `PATCH` | `/api/course-assignments/{id}` | JWT | Update assignment | | `POST` | `/api/course-assignments/{id}/publish` | JWT | Publish assignment | | `POST` | `/api/course-assignments/{id}/finish` | JWT | Close assignment | | `GET` | `/api/course-assignments/{id}/submissions` | JWT | List student submissions | | `POST` | `/api/course-assignments/{id}/submit` | JWT | Student file upload (multipart/form-data) | | `PATCH` | `/api/submissions/{id}` | JWT | Grade submission (marks, feedback, status) | | `GET` | `/api/assignment-types` | JWT | List assignment types | | `POST` | `/api/assignment-types` | JWT | Create assignment type | ### 14.3 File Upload Student submission accepts `multipart/form-data`: - `file`: Binary file attachment - `description`: Optional text description Files are stored as `ir.attachment` records linked to `op.assignment.sub.line`. ### 14.4 Grading Request ```json { "marks": 85, "state": "accept", "note": "Well researched paper. Minor formatting issues." } ``` --- ## 15. Classroom and Group Management ### 15.1 Model (`encoach.classroom.group`) Virtual classrooms for grouping students within entities. ### 15.2 API Endpoints | Method | Path | Auth | Description | |--------|------|------|-------------| | `GET` | `/api/groups` | JWT | Paginated groups | | `GET` | `/api/groups/{id}` | JWT | Group detail with members | | `POST` | `/api/groups` | JWT | Create group | | `DELETE` | `/api/groups/{id}` | JWT | Delete group | | `POST` | `/api/groups/transfer` | JWT | Transfer students between groups | | `POST` | `/api/groups/{id}/members` | JWT | Add members | | `POST` | `/api/groups/{id}/members/remove` | JWT | Remove members | --- ## 16. Subject Taxonomy Engine ### 16.1 Models **`encoach.subject`** (distinct from `op.subject`) | Field | Type | Description | |-------|------|-------------| | `name` | Char | Subject name (e.g., "IELTS", "Mathematics", "Information Technology") | | `code` | Char | Unique code | | `description` | Text | Description | | `icon` | Char | Icon identifier | | `active` | Boolean | Active flag | | `domain_ids` | One2many | Child domains | **`encoach.domain`** | Field | Type | Description | |-------|------|-------------| | `name` | Char | Domain name (e.g., "Algebra", "Networking") | | `subject_id` | Many2one | Parent subject | | `topic_ids` | One2many | Child topics | **`encoach.topic`** | Field | Type | Description | |-------|------|-------------| | `name` | Char | Topic name | | `domain_id` | Many2one | Parent domain | | `subject_id` | Many2one (related) | Subject via domain | | `difficulty` | Selection | `beginner`, `intermediate`, `advanced` | | `prerequisite_ids` | Many2many | Prerequisite topics | | `learning_objective_ids` | One2many | Learning objectives | **`encoach.learning.objective`** | Field | Type | Description | |-------|------|-------------| | `name` | Char | Objective description | | `topic_id` | Many2one | Parent topic | | `bloom_level` | Selection | `remember`, `understand`, `apply`, `analyze`, `evaluate`, `create` | ### 16.2 API Endpoints | Method | Path | Auth | Description | |--------|------|------|-------------| | `GET` | `/api/subjects` | JWT | List subjects | | `GET` | `/api/subjects/{id}` | JWT | Subject detail | | `POST` | `/api/subjects` | JWT | Create subject | | `PATCH` | `/api/subjects/{id}` | JWT | Update subject | | `DELETE` | `/api/subjects/{id}` | JWT | Delete subject | | `GET` | `/api/subjects/{subjectId}/taxonomy` | JWT | Full taxonomy tree (domains → topics → objectives) | | `POST` | `/api/subjects/{subjectId}/taxonomy/import` | JWT | Import taxonomy from file (multipart) | | `GET` | `/api/domains` | JWT | List domains (filter: `subject_id`) | | `POST` | `/api/domains` | JWT | Create domain | | `PATCH` | `/api/domains/{id}` | JWT | Update domain | | `DELETE` | `/api/domains/{id}` | JWT | Delete domain | | `POST` | `/api/domains/{domainId}/ai-suggest` | JWT | AI-suggest topics for domain | | `GET` | `/api/topics` | JWT | List topics (filter: `domain_id`, `subject_id`) | | `POST` | `/api/topics` | JWT | Create topic | | `PATCH` | `/api/topics/{id}` | JWT | Update topic | | `DELETE` | `/api/topics/{id}` | JWT | Delete topic | --- ## 17. Adaptive Learning Engine ### 17.1 Models **`encoach.proficiency`** | Field | Type | Description | |-------|------|-------------| | `student_id` | Many2one | Student user | | `subject_id` | Many2one | Subject | | `topic_id` | Many2one | Topic | | `mastery_score` | Float | 0.0 to 1.0 | | `confidence` | Float | Statistical confidence | | `last_assessed` | Datetime | Last assessment time | | `assessment_count` | Integer | Number of assessments | **`encoach.learning.plan`** | Field | Type | Description | |-------|------|-------------| | `student_id` | Many2one | Student | | `subject_id` | Many2one | Subject | | `status` | Selection | `active`, `paused`, `completed` | | `items` | One2many | Plan items (topics in order) | | `generated_by` | Selection | `ai`, `manual` | | `progress` | Float | Computed completion percentage | **`encoach.learning.plan.item`** | Field | Type | Description | |-------|------|-------------| | `plan_id` | Many2one | Parent plan | | `topic_id` | Many2one | Topic | | `sequence` | Integer | Order in plan | | `status` | Selection | `locked`, `available`, `in_progress`, `completed` | | `estimated_hours` | Float | Estimated time | | `mastery_threshold` | Float | Required mastery to complete | **`encoach.diagnostic.session`** | Field | Type | Description | |-------|------|-------------| | `student_id` | Many2one | Student | | `subject_id` | Many2one | Subject | | `status` | Selection | `in_progress`, `completed` | | `questions_answered` | Integer | Count | | `result_data` | Text (JSON) | Topic-level results | **`encoach.content.cache`** | Field | Type | Description | |-------|------|-------------| | `topic_id` | Many2one | Topic | | `content_type` | Selection | `explanation`, `practice`, `quiz` | | `content` | Text (JSON) | Cached AI content | | `generated_at` | Datetime | Generation time | | `ttl_hours` | Integer | Cache TTL | ### 17.2 API Endpoints | Method | Path | Auth | Description | |--------|------|------|-------------| | `POST` | `/api/diagnostic/start` | JWT | Start diagnostic for subject | | `POST` | `/api/diagnostic/answer` | JWT | Submit diagnostic answer (adaptive next question) | | `GET` | `/api/diagnostic/{sessionId}/result` | JWT | Get diagnostic result | | `GET` | `/api/proficiency` | JWT | Get proficiency records (filter: `subject_id`, `student_id`) | | `GET` | `/api/proficiency/summary` | JWT | Aggregate proficiency summary | | `GET` | `/api/proficiency/class` | JWT | Class-wide proficiency | | `GET` | `/api/learning-plan` | JWT | Get learning plan (filter: `subject_id`) | | `POST` | `/api/learning-plan/generate` | JWT | AI-generate learning plan | | `PATCH` | `/api/learning-plan/{id}` | JWT | Update plan | | `POST` | `/api/learning-plan/{id}/pause` | JWT | Pause plan | | `POST` | `/api/learning-plan/{id}/resume` | JWT | Resume plan | | `GET` | `/api/topics/{topicId}/content` | JWT | Get topic learning content | | `POST` | `/api/topics/{topicId}/generate-content` | JWT | AI-generate topic content | | `POST` | `/api/topics/{topicId}/practice` | JWT | Generate practice questions | | `POST` | `/api/topics/{topicId}/practice/grade` | JWT | Grade practice answers | | `POST` | `/api/topics/{topicId}/mastery-quiz` | JWT | Start mastery quiz | | `POST` | `/api/topics/{topicId}/mastery-quiz/submit` | JWT | Submit mastery quiz and update proficiency | ### 17.3 Diagnostic Algorithm Computer Adaptive Testing (CAT): 1. Start with medium-difficulty questions 2. If correct → harder question; if incorrect → easier question 3. Uses Item Response Theory (IRT) to estimate ability 4. Covers multiple topics within the subject 5. Terminates after sufficient confidence or max questions (20-30) 6. Produces per-topic mastery scores ### 17.4 Learning Plan Generation AI-generated study plan: 1. Read student's proficiency profile 2. Identify weak topics (mastery < threshold) 3. Respect prerequisite graph (topological sort) 4. Estimate time per topic based on gap 5. Order topics: prerequisites first, then weakest areas 6. Return ordered list of `plan_items` --- ## 18. Learning Resources ### 18.1 Model (`encoach.resource`) | Field | Type | Description | |-------|------|-------------| | `name` | Char | Resource title | | `type` | Selection | `video`, `document`, `link`, `interactive` | | `subject_id` | Many2one | Subject | | `topic_ids` | Many2many | Topics | | `file` | Binary | Uploaded file | | `url` | Char | External URL | | `difficulty` | Selection | `beginner`, `intermediate`, `advanced` | | `duration_minutes` | Integer | Estimated duration | | `active` | Boolean | Soft-delete flag | ### 18.2 API Endpoints | Method | Path | Auth | Description | |--------|------|------|-------------| | `GET` | `/api/resources` | JWT | Paginated resources (filter: `subject_id`, `topic_id`, `type`, `difficulty`) | | `POST` | `/api/resources` | JWT | Upload resource (multipart) | | `PATCH` | `/api/resources/{id}` | JWT | Update resource metadata | | `DELETE` | `/api/resources/{id}` | JWT | Soft-delete resource | | `POST` | `/api/resources/{id}/complete` | JWT | Mark resource as completed by student | | `POST` | `/api/resources/{id}/rate` | JWT | Rate resource (1-5) | | `GET` | `/api/resources/{id}/download` | JWT | Download resource file | --- ## 19. AI Services ### 19.1 AI Coaching | Method | Path | Auth | Description | |--------|------|------|-------------| | `POST` | `/api/coach/chat` | JWT | General AI chat (context-aware) | | `POST` | `/api/coach/hint` | JWT | Hint for topic/question | | `POST` | `/api/coach/explain` | JWT | Explain scores or concepts | | `POST` | `/api/coach/suggest` | JWT | Study suggestions | | `POST` | `/api/coach/writing-help` | JWT | Writing feedback with improved text | | `GET` | `/api/coach/tip` | JWT | Context-aware tip (FAISS similarity) | ### 19.2 AI Evaluation | Method | Path | Auth | Description | |--------|------|------|-------------| | `POST` | `/api/evaluate/writing` | JWT | Evaluate writing (IELTS band scoring / rubric-based) | | `POST` | `/api/evaluate/speaking` | JWT | Evaluate speaking (audio → transcribe → grade) | | `POST` | `/api/grading/multiple` | JWT | Grade multiple-choice / numerical answers | | `POST` | `/api/transcribe` | JWT | Audio transcription (Whisper, multipart upload) | ### 19.3 AI Generation | Method | Path | Auth | Description | |--------|------|------|-------------| | `POST` | `/api/exam/{module}/generate` | JWT | Generate exam exercises from template | | `POST` | `/api/exam/{module}/generate/scratch` | JWT | Generate full exam from scratch | ### 19.4 Media Generation | Method | Path | Auth | Description | |--------|------|------|-------------| | `POST` | `/api/exam/listening/media` | JWT | Generate listening audio (AWS Polly TTS) | | `POST` | `/api/exam/speaking/media` | JWT | Generate speaking video (ELAI) | | `GET` | `/api/exam/avatars` | JWT | List ELAI avatars with voice metadata | ### 19.5 AI Analytics | Method | Path | Auth | Description | |--------|------|------|-------------| | `POST` | `/api/ai/search` | JWT | AI-powered semantic search | | `POST` | `/api/ai/insights` | JWT | AI-generated insights from data | | `GET` | `/api/ai/alerts` | JWT | AI-detected alerts (at-risk students, anomalies) | | `POST` | `/api/ai/report-narrative` | JWT | AI narrative for reports | | `POST` | `/api/ai/batch-optimize` | JWT | Batch optimization suggestions | | `POST` | `/api/ai/grade-suggest` | JWT | AI grading suggestion | ### 19.6 AI Service Configuration All AI services read configuration from `ir.config_parameter`: | Parameter Key | Description | Default | |--------------|-------------|---------| | `encoach.openai_api_key` | OpenAI API key | Required | | `encoach.openai_model` | Default model | `gpt-4o` | | `encoach.openai_model_light` | Light model for simple tasks | `gpt-3.5-turbo` | | `encoach.aws_access_key_id` | AWS access key | Required | | `encoach.aws_secret_access_key` | AWS secret key | Required | | `encoach.aws_region` | AWS region | `eu-west-1` | | `encoach.polly_voice_id` | Default Polly voice | `Joanna` | | `encoach.polly_engine` | Polly engine | `neural` | | `encoach.whisper_model` | Whisper model size | `base` | | `encoach.whisper_workers` | Whisper worker threads | `4` | | `encoach.elai_api_key` | ELAI API key | Required | | `encoach.gptzero_api_key` | GPTZero API key | Required | | `encoach.faiss_embedding_model` | Sentence transformer model | `all-MiniLM-L6-v2` | --- ## 20. Training Content ### 20.1 Models **`encoach.training.tip`** | Field | Type | Description | |-------|------|-------------| | `title` | Char | Tip title | | `content` | Text | Tip content | | `subject_id` | Many2one | Subject | | `module` | Char | Module tag | | `embedding` | Binary(attachment=False) | FAISS embedding vector | **`encoach.training.walkthrough`** | Field | Type | Description | |-------|------|-------------| | `title` | Char | Walkthrough title | | `steps` | Text (JSON) | Step-by-step content | | `module` | Char | Module tag | ### 20.2 API Endpoints | Method | Path | Auth | Description | |--------|------|------|-------------| | `GET` | `/api/training` | JWT | Training records (filter: `entity_id`, `user_id`, `module`) | | `GET` | `/api/training/tips` | JWT | Training tips | | `GET` | `/api/training/walkthrough` | JWT | Walkthroughs (filter: `module`) | --- ## 21. Analytics and Statistics ### 21.1 API Endpoints | Method | Path | Auth | Description | |--------|------|------|-------------| | `GET` | `/api/sessions` | JWT | Exam sessions | | `GET` | `/api/stats` | JWT | Exam statistics | | `GET` | `/api/statistical` | JWT | Aggregated statistical data | | `GET` | `/api/stats/performance` | JWT | Performance metrics | | `GET` | `/api/analytics/student` | JWT | Student analytics (filter: `student_id`, `subject_id`, `date_range`) | | `GET` | `/api/analytics/class` | JWT | Class analytics (filter: `batch_id`, `course_id`) | | `GET` | `/api/analytics/subject` | JWT | Subject analytics (filter: `subject_id`) | | `GET` | `/api/analytics/content-gaps` | JWT | Content gap analysis | --- ## 22. Subscription and Payments ### 22.1 Models **`encoach.package`** | Field | Type | Description | |-------|------|-------------| | `name` | Char | Package name | | `description` | Text | Description | | `price` | Float | Price | | `currency` | Char | Currency code | | `duration_days` | Integer | Access duration | | `subject_ids` | Many2many | Included subjects | | `features` | Text (JSON) | Feature list | | `active` | Boolean | Available for purchase | **`encoach.payment`** | Field | Type | Description | |-------|------|-------------| | `user_id` | Many2one | Paying user | | `entity_id` | Many2one | Entity (if institutional) | | `package_id` | Many2one | Package | | `amount` | Float | Payment amount | | `currency` | Char | Currency | | `provider` | Selection | `stripe`, `paypal`, `paymob`, `invoice` | | `status` | Selection | `pending`, `completed`, `failed`, `refunded` | | `provider_ref` | Char | External reference | | `created_at` | Datetime | Payment date | **`encoach.discount`** | Field | Type | Description | |-------|------|-------------| | `code` | Char | Discount code | | `percentage` | Float | Discount percentage | | `valid_from` | Datetime | Start date | | `valid_to` | Datetime | End date | | `max_uses` | Integer | Maximum uses | | `current_uses` | Integer | Current use count | ### 22.2 API Endpoints | Method | Path | Auth | Description | |--------|------|------|-------------| | `GET` | `/api/packages` | JWT | List packages | | `GET` | `/api/payments` | JWT | Paginated payments | | `POST` | `/api/stripe/checkout` | JWT | Create Stripe checkout session, return URL | | `POST` | `/api/paypal/checkout` | JWT | Create PayPal order, return approval URL | | `POST` | `/api/paymob/checkout` | JWT | Create Paymob payment, return URL | | `GET` | `/api/discounts` | JWT | List discounts | | `POST` | `/api/discounts` | JWT | Create discount | | `DELETE` | `/api/discounts/{id}` | JWT | Delete discount | ### 22.3 Webhook Endpoints | Method | Path | Auth | Description | |--------|------|------|-------------| | `POST` | `/api/stripe/webhook` | Webhook signature | Stripe payment events | | `POST` | `/api/paypal/webhook` | Webhook signature | PayPal payment events | | `POST` | `/api/paymob/webhook` | Webhook HMAC | Paymob transaction callback | --- ## 23. Support Tickets ### 23.1 Model (`encoach.ticket`) | Field | Type | Description | |-------|------|-------------| | `subject` | Char | Ticket subject | | `description` | Text | Description | | `type` | Selection | `bug`, `feature`, `support`, `feedback` | | `status` | Selection | `open`, `in_progress`, `resolved`, `closed` | | `reporter_id` | Many2one | Reporter user | | `assignee_id` | Many2one | Assigned staff | | `entity_id` | Many2one | Entity context | | `source` | Selection | `platform`, `webpage` | ### 23.2 API Endpoints | Method | Path | Auth | Description | |--------|------|------|-------------| | `GET` | `/api/tickets` | JWT | Paginated tickets (filter: `status`, `type`, `assignee_id`, `source`) | | `POST` | `/api/tickets` | JWT | Create ticket | | `PATCH` | `/api/tickets/{id}` | JWT | Update ticket | | `GET` | `/api/tickets/assignedToUser` | JWT | Tickets assigned to current user | --- ## 24. File Storage ### 24.1 API Endpoints | Method | Path | Auth | Description | |--------|------|------|-------------| | `POST` | `/api/storage/upload` | JWT | Upload file (multipart/form-data), return attachment ID and URL | | `GET` | `/api/storage/url` | JWT | Resolve download URL for filename | Files are stored as `ir.attachment` records. For production, configure Odoo to use S3-compatible storage. --- ## 25. Approval Workflows (Enhanced) ### 25.1 Model (`encoach.approval.workflow`) | Field | Type | Description | |-------|------|-------------| | `name` | Char | Workflow name | | `type` | Selection | `exam_publish`, `assignment_publish`, `content_publish`, `material_publish` | | `stage_ids` | One2many | Approval stages (ordered) | | `entity_id` | Many2one | Entity | | `allow_bypass` | Boolean | Whether bypass is allowed | | `active` | Boolean | Active flag | ### 25.2 Model (`encoach.approval.stage`) | Field | Type | Description | |-------|------|-------------| | `workflow_id` | Many2one | Parent workflow | | `sequence` | Integer | Stage order | | `approver_id` | Many2one | Assigned approver (`res.users`) | | `max_days` | Integer | Maximum days before auto-escalation | | `auto_escalate` | Boolean | Whether to auto-escalate on timeout | | `notification_email` | Char | Email for stage notifications | | `status` | Selection | `pending`, `approved`, `rejected`, `escalated`, `bypassed` | | `comment` | Text | Reviewer comment | | `acted_at` | Datetime | When action was taken | ### 25.3 Model (`encoach.approval.request`) | Field | Type | Description | |-------|------|-------------| | `workflow_id` | Many2one | Workflow template | | `res_model` | Char | Target model (e.g., `encoach.exam`) | | `res_id` | Integer | Target record ID | | `current_stage_id` | Many2one | Current active stage | | `requester_id` | Many2one | User who submitted for approval | | `state` | Selection | `in_progress`, `approved`, `rejected`, `bypassed` | | `bypass_reason` | Text | Justification if bypassed | | `created_at` | Datetime | Request creation time | ### 25.4 API Endpoints | Method | Path | Auth | Description | |--------|------|------|-------------| | `GET` | `/api/approval-workflows` | JWT | Paginated workflows | | `POST` | `/api/approval-workflows` | JWT | Create workflow with stages | | `GET` | `/api/approval-workflows/{id}` | JWT | Get workflow with stages | | `PATCH` | `/api/approval-workflows/{id}` | JWT | Update workflow and stages | | `DELETE` | `/api/approval-workflows/{id}` | JWT | Delete workflow | | `POST` | `/api/approval-requests` | JWT | Submit item for approval | | `GET` | `/api/approval-requests` | JWT | List approval requests (filter: state, type) | | `POST` | `/api/approval-requests/{id}/approve` | JWT | Approve current stage | | `POST` | `/api/approval-requests/{id}/reject` | JWT | Reject at current stage | | `POST` | `/api/approval-requests/{id}/bypass` | JWT | Bypass approval (requires justification) | | `POST` | `/api/approval-requests/{id}/return` | JWT | Return to specific stage | ### 25.5 Cron: Auto-Escalation A server cron runs daily to check approval stages that have exceeded `max_days`. For stages with `auto_escalate = True`, the system automatically advances to the next stage and sends a notification email to the new approver with escalation reason. --- ## 26. Courseware and Content Delivery **Module:** `encoach_courseware` **Dependencies:** `encoach_core`, `openeducat_core`, `encoach_ai` ### 26.1 Model (`encoach.course.chapter`) | Field | Type | Description | |-------|------|-------------| | `name` | Char (required) | Chapter title | | `course_id` | Many2one (`op.course`) | Parent course | | `sequence` | Integer | Display order | | `description` | Text | Chapter description | | `start_date` | Datetime | Scheduled start date | | `end_date` | Datetime | Optional end date | | `unlock_mode` | Selection | `auto_date`, `manual`, `prerequisite` | | `is_unlocked` | Boolean | Current unlock status | | `topic_id` | Many2one (`encoach.topic`) | Bridge to adaptive engine | | `material_ids` | One2many | Chapter materials | | `assignment_ids` | Many2many (`encoach.assignment`) | Linked assignments | | `exam_ids` | Many2many (`encoach.exam`) | Linked exams/quizzes | | `active` | Boolean | Soft-delete flag | ### 26.2 Model (`encoach.chapter.material`) | Field | Type | Description | |-------|------|-------------| | `name` | Char (required) | Material title | | `chapter_id` | Many2one | Parent chapter | | `type` | Selection | `pdf`, `document`, `video`, `audio`, `image`, `link`, `article` | | `file` | Binary (attachment=True) | Uploaded file | | `url` | Char | External URL | | `description` | Text | Description | | `sequence` | Integer | Display order | | `allow_download` | Boolean | Student download permission | | `is_book` | Boolean | Course book flag | | `book_chapters` | Text | JSON book chapter structure | | `active` | Boolean | Soft-delete flag | ### 26.3 Model (`encoach.chapter.progress`) | Field | Type | Description | |-------|------|-------------| | `student_id` | Many2one (`res.users`) | Student | | `chapter_id` | Many2one | Chapter | | `status` | Selection | `not_started`, `in_progress`, `completed` | | `started_at` | Datetime | First access time | | `completed_at` | Datetime | Completion time | | `materials_completed` | Integer | Count of materials viewed | | `materials_total` | Integer | Computed total materials | ### 26.4 API Endpoints | Method | Path | Auth | Description | |--------|------|------|-------------| | `GET` | `/api/courses/{courseId}/chapters` | JWT | List chapters (ordered by sequence) | | `POST` | `/api/courses/{courseId}/chapters` | JWT (teacher) | Create chapter | | `GET` | `/api/chapters/{id}` | JWT | Chapter detail with material count | | `PATCH` | `/api/chapters/{id}` | JWT (teacher) | Update chapter | | `DELETE` | `/api/chapters/{id}` | JWT (teacher) | Soft-delete chapter | | `POST` | `/api/chapters/{id}/unlock` | JWT (teacher) | Manually unlock | | `POST` | `/api/chapters/{id}/lock` | JWT (teacher) | Manually lock | | `PATCH` | `/api/courses/{courseId}/chapters/reorder` | JWT (teacher) | Reorder (body: `{ids: []}`) | | `GET` | `/api/chapters/{id}/progress` | JWT | Student progress | | `POST` | `/api/chapters/{id}/progress/complete` | JWT (student) | Mark chapter completed | | `GET` | `/api/chapters/{chapterId}/materials` | JWT | List materials | | `POST` | `/api/chapters/{chapterId}/materials` | JWT (teacher) | Upload material (multipart) | | `PATCH` | `/api/materials/{id}` | JWT (teacher) | Update material metadata | | `DELETE` | `/api/materials/{id}` | JWT (teacher) | Delete material | | `GET` | `/api/materials/{id}/download` | JWT | Download file (streaming response) | | `POST` | `/api/materials/{id}/viewed` | JWT (student) | Record material view | | `PATCH` | `/api/chapters/{chapterId}/materials/reorder` | JWT (teacher) | Reorder materials | ### 26.5 AI Workbench Endpoints | Method | Path | Auth | Description | |--------|------|------|-------------| | `POST` | `/api/workbench/generate-outline` | JWT (teacher) | AI generates course outline from requirements (topic, objectives, complexity) | | `POST` | `/api/workbench/generate-chapter` | JWT (teacher) | AI generates content for a specific chapter | | `POST` | `/api/workbench/generate-rubric` | JWT (teacher) | AI generates grading rubric | | `POST` | `/api/workbench/regenerate` | JWT (teacher) | Regenerate specific section | | `POST` | `/api/workbench/suggest-materials` | JWT (teacher) | AI suggests supplementary materials based on student performance profiles | | `POST` | `/api/workbench/publish` | JWT (teacher) | Publish generated content to course chapters (may trigger approval workflow) | AI Workbench uses GPT-4o (temp 0.7 for generation) and calls `encoach_ai` service layer. ### 26.6 Cron: Auto-Unlock Chapters Server cron runs every hour. For chapters with `unlock_mode = 'auto_date'` and `start_date <= now()` and `is_unlocked = False`, set `is_unlocked = True` and trigger notification. --- ## 27. Communication System **Module:** `encoach_communication` **Dependencies:** `encoach_core`, `openeducat_core` ### 27.1 Model (`encoach.discussion.board`) | Field | Type | Description | |-------|------|-------------| | `name` | Char (required) | Board title | | `course_id` | Many2one (`op.course`) | Associated course | | `batch_id` | Many2one (`op.batch`) | Associated batch (optional) | | `chapter_id` | Many2one (`encoach.course.chapter`) | Associated chapter (optional) | | `assignment_id` | Many2one | Associated assignment (optional) | | `is_enabled` | Boolean | Teacher toggle | | `allow_student_posts` | Boolean | Student thread creation permission | | `post_count` | Integer | Computed count of posts | ### 27.2 Model (`encoach.discussion.post`) | Field | Type | Description | |-------|------|-------------| | `board_id` | Many2one | Parent board | | `parent_id` | Many2one (self) | Parent post for threading | | `author_id` | Many2one (`res.users`) | Author | | `title` | Char | Thread title (root posts only) | | `content` | Text | Post body (markdown) | | `attachment_ids` | Many2many (`ir.attachment`) | File attachments | | `is_pinned` | Boolean | Teacher pin | | `is_resolved` | Boolean | Resolved flag (Q&A mode) | | `reply_count` | Integer | Computed child count | | `created_at` | Datetime | Post timestamp | ### 27.3 Model (`encoach.announcement`) | Field | Type | Description | |-------|------|-------------| | `title` | Char (required) | Announcement title | | `content` | Text | Body (markdown) | | `author_id` | Many2one (`res.users`) | Author | | `course_id` | Many2one (`op.course`) | Target course (null = system-wide) | | `batch_id` | Many2one (`op.batch`) | Target batch (null = all batches) | | `priority` | Selection | `normal`, `important`, `urgent` | | `is_published` | Boolean | Published status | | `published_at` | Datetime | Publish timestamp | | `expires_at` | Datetime | Expiry time | | `send_email` | Boolean | Also send via email | | `attachment_ids` | Many2many (`ir.attachment`) | Attachments | ### 27.4 Model (`encoach.message`) | Field | Type | Description | |-------|------|-------------| | `sender_id` | Many2one (`res.users`) | Sender | | `recipient_id` | Many2one (`res.users`) | Recipient | | `subject` | Char | Subject line | | `content` | Text | Message body | | `is_read` | Boolean | Read flag | | `read_at` | Datetime | Read timestamp | | `attachment_ids` | Many2many (`ir.attachment`) | Attachments | | `send_email_copy` | Boolean | Send email copy | | `created_at` | Datetime | Sent time | ### 27.5 API Endpoints | Method | Path | Auth | Description | |--------|------|------|-------------| | `GET` | `/api/discussion-boards` | JWT | List boards (filter: `course_id`, `batch_id`) | | `POST` | `/api/discussion-boards` | JWT (teacher) | Create board | | `PATCH` | `/api/discussion-boards/{id}` | JWT (teacher) | Update settings | | `GET` | `/api/discussion-boards/{id}/posts` | JWT | Paginated posts (threaded) | | `POST` | `/api/discussion-boards/{id}/posts` | JWT | Create post/reply | | `PATCH` | `/api/posts/{id}` | JWT | Update own post | | `DELETE` | `/api/posts/{id}` | JWT (teacher/admin) | Delete post | | `POST` | `/api/posts/{id}/pin` | JWT (teacher) | Pin/unpin toggle | | `POST` | `/api/posts/{id}/resolve` | JWT (teacher) | Mark as resolved | | `GET` | `/api/announcements` | JWT | List announcements (filter: `course_id`, `priority`) | | `POST` | `/api/announcements` | JWT (teacher/admin) | Create announcement | | `PATCH` | `/api/announcements/{id}` | JWT | Update | | `DELETE` | `/api/announcements/{id}` | JWT | Delete | | `POST` | `/api/announcements/{id}/publish` | JWT | Publish | | `GET` | `/api/messages` | JWT | Inbox (filter: `is_read`) | | `GET` | `/api/messages/sent` | JWT | Sent messages | | `POST` | `/api/messages` | JWT | Send message | | `GET` | `/api/messages/{id}` | JWT | Message detail (auto-marks read) | | `DELETE` | `/api/messages/{id}` | JWT | Delete message | | `GET` | `/api/messages/unread-count` | JWT | Unread count `{count: N}` | ### 27.6 Email Integration When `send_email = True` on announcements or `send_email_copy = True` on messages, the module uses Odoo's `mail.thread` mixin to send emails through the configured outgoing mail server. --- ## 28. Notification Engine **Module:** `encoach_notification` **Dependencies:** `encoach_core` ### 28.1 Model (`encoach.notification`) | Field | Type | Description | |-------|------|-------------| | `user_id` | Many2one (`res.users`) | Recipient | | `title` | Char | Notification title | | `message` | Text | Body | | `type` | Selection | `deadline`, `chapter_unlock`, `result_release`, `announcement`, `assignment`, `exam`, `message`, `system` | | `action_url` | Char | Frontend URL to navigate to | | `is_read` | Boolean | Read status | | `read_at` | Datetime | Read timestamp | | `channel` | Selection | `in_app`, `email`, `both` | | `created_at` | Datetime | Created time | ### 28.2 Model (`encoach.notification.rule`) | Field | Type | Description | |-------|------|-------------| | `name` | Char | Rule name | | `event_type` | Selection | `assignment_due`, `exam_due`, `chapter_unlock`, `result_release`, `submission_graded`, `extension_response` | | `days_before` | Integer | Days before event to trigger | | `frequency` | Selection | `once`, `daily`, `custom` | | `custom_intervals` | Text (JSON) | Custom intervals array (e.g., `[7, 3, 1]`) | | `channel` | Selection | `in_app`, `email`, `both` | | `entity_id` | Many2one | Entity scope | | `active` | Boolean | Active flag | ### 28.3 Model (`encoach.notification.preferences`) | Field | Type | Description | |-------|------|-------------| | `user_id` | Many2one (`res.users`) | One per user | | `email_enabled` | Boolean | Master email toggle | | `assignment_alerts` | Boolean | Assignment notifications | | `exam_alerts` | Boolean | Exam notifications | | `chapter_alerts` | Boolean | Chapter unlock notifications | | `announcement_alerts` | Boolean | Announcement notifications | | `message_alerts` | Boolean | Message notifications | ### 28.4 API Endpoints | Method | Path | Auth | Description | |--------|------|------|-------------| | `GET` | `/api/notifications` | JWT | Paginated list (filter: `type`, `is_read`) | | `POST` | `/api/notifications/{id}/read` | JWT | Mark as read | | `POST` | `/api/notifications/read-all` | JWT | Mark all as read | | `GET` | `/api/notifications/unread-count` | JWT | `{count: N}` | | `GET` | `/api/notification-rules` | JWT (admin) | List rules | | `POST` | `/api/notification-rules` | JWT (admin) | Create rule | | `PATCH` | `/api/notification-rules/{id}` | JWT (admin) | Update rule | | `DELETE` | `/api/notification-rules/{id}` | JWT (admin) | Delete rule | | `GET` | `/api/notification-preferences` | JWT | Get user preferences | | `PATCH` | `/api/notification-preferences` | JWT | Update preferences | ### 28.5 Crons 1. **Deadline Reminders:** Runs daily. Checks all active rules, matches upcoming events (assignments, exams) within `days_before`, creates notifications and sends emails per user preferences. 2. **Chapter Unlock Notifications:** Triggered by the courseware cron when chapters are auto-unlocked. --- ## 29. FAQ System **Module:** `encoach_faq` **Dependencies:** `encoach_core` ### 29.1 Model (`encoach.faq.category`) | Field | Type | Description | |-------|------|-------------| | `name` | Char | Category name | | `sequence` | Integer | Display order | | `icon` | Char | Icon identifier | | `audience` | Selection | `student`, `entity`, `both` | | `active` | Boolean | Active flag | ### 29.2 Model (`encoach.faq.item`) | Field | Type | Description | |-------|------|-------------| | `question` | Char | Question text | | `answer` | Text | Answer (markdown, embedded images/video) | | `category_id` | Many2one | Parent category | | `audience` | Selection | `student`, `entity`, `both` | | `image` | Binary | Optional image | | `video_url` | Char | Optional video URL | | `sequence` | Integer | Display order | | `active` | Boolean | Active flag | ### 29.3 API Endpoints | Method | Path | Auth | Description | |--------|------|------|-------------| | `GET` | `/api/faq/categories` | Public/JWT | List categories (filter: `audience`) | | `POST` | `/api/faq/categories` | JWT (admin) | Create category | | `PATCH` | `/api/faq/categories/{id}` | JWT (admin) | Update category | | `DELETE` | `/api/faq/categories/{id}` | JWT (admin) | Delete category | | `GET` | `/api/faq/items` | Public/JWT | List items (filter: `category_id`, `audience`, `search`) | | `POST` | `/api/faq/items` | JWT (admin) | Create item | | `PATCH` | `/api/faq/items/{id}` | JWT (admin) | Update item | | `DELETE` | `/api/faq/items/{id}` | JWT (admin) | Delete item | --- ## 30. Plagiarism Detection **Module enhancement:** `encoach_ai_grading` (add plagiarism sub-service) ### 30.1 Plagiarism Report Storage Add to `encoach.submission` or create `encoach.plagiarism.report`: | Field | Type | Description | |-------|------|-------------| | `submission_id` | Many2one | Target submission | | `overall_score` | Float | AI probability score (0-1) | | `per_sentence` | Text (JSON) | Per-sentence analysis from GPTZero | | `report_pdf` | Binary | Generated PDF report | | `checked_at` | Datetime | When check was run | ### 30.2 API Endpoints | Method | Path | Auth | Description | |--------|------|------|-------------| | `POST` | `/api/plagiarism/check` | JWT (teacher) | Submit text for GPTZero analysis | | `GET` | `/api/plagiarism/report/{submissionId}` | JWT | Get plagiarism report | | `GET` | `/api/plagiarism/report/{submissionId}/download` | JWT | Download PDF report | ### 30.3 Integration - Uses GPTZero `v2/predict/text` endpoint (already configured in `encoach_ai_grading`) - Can be enabled/disabled per assignment via `plagiarism_enabled` boolean on `encoach.assignment` - Configurable max submissions for plagiarism check via `plagiarism_max_checks` integer --- ## 31. Official Exam Access **Module enhancement:** `encoach_exam` (add official access modes) ### 31.1 Model Extensions Add to `encoach.exam`: | Field | Type | Description | |-------|------|-------------| | `is_exercise` | Boolean | Exercise (practice, no journey tracking) vs Exam | | `is_official` | Boolean | Official exam flag | | `access_mode` | Selection | `normal`, `link`, `landing_page`, `separate_login` | | `access_token` | Char | Unique access token (auto-generated) | | `access_code` | Char | Exam access code | | `activation_start` | Datetime | Exam start time | | `activation_end` | Datetime | Exam end time | | `generate_unique_per_student` | Boolean | AI generates unique variant per student | | `reminder_count` | Integer | Number of reminders to send | | `reminder_frequency` | Selection | `once`, `daily`, `custom` | ### 31.2 API Endpoints | Method | Path | Auth | Description | |--------|------|------|-------------| | `POST` | `/api/exam/{id}/generate-link` | JWT (teacher) | Generate unique access token/URL | | `GET` | `/api/exam/access/{token}` | Public | Access exam via token (validates token, returns exam info) | | `POST` | `/api/exam/official-login` | Public | Login with exam code + credentials | | `POST` | `/api/exam/{id}/suspend` | JWT (teacher) | Suspend exam | | `POST` | `/api/exam/{id}/revoke` | JWT (teacher) | Revoke exam access | --- ## 32. Non-Functional Requirements ### 32.1 Performance | ID | Requirement | |----|-------------| | NFR-PERF-01 | API response time < 500ms for CRUD endpoints | | NFR-PERF-02 | AI endpoints may take up to 30s (use async job for long operations) | | NFR-PERF-03 | Pagination: default `size=20`, max `size=100` | ### 32.2 Security | ID | Requirement | |----|-------------| | NFR-SEC-01 | JWT tokens expire after 24 hours | | NFR-SEC-02 | All endpoints validate entity-scoped permissions | | NFR-SEC-03 | Rate limiting on AI endpoints (configurable) | | NFR-SEC-04 | CORS configured for frontend origin | | NFR-SEC-05 | File upload size limit: 50MB | | NFR-SEC-06 | API keys stored in `ir.config_parameter`, never in code | ### 32.3 Scalability | ID | Requirement | |----|-------------| | NFR-SCALE-01 | Support 10,000+ concurrent students | | NFR-SCALE-02 | Support 50+ subjects, 500+ topics per subject, 1000+ resources per subject | | NFR-SCALE-03 | Database indices on all foreign keys and frequently filtered fields | ### 32.4 Reliability | ID | Requirement | |----|-------------| | NFR-REL-01 | AI service failures return graceful error (never 500) | | NFR-REL-02 | Webhook processing is idempotent | | NFR-REL-03 | Soft-delete for resources (preserve completion records) | ### 32.5 API Conventions | Convention | Detail | |-----------|--------| | Date format | ISO 8601 (`YYYY-MM-DD` or `YYYY-MM-DDTHH:MM:SS`) | | Pagination | `?page=1&size=20` returns `{ "items": [...], "total": N, "page": 1, "size": 20 }` | | Error shape | `{ "error": "message", "code": "ERROR_CODE" }` with HTTP status | | ID fields | Many2one serialized as `{field}_id` (int) + `{field}_name` (str) | | List fields | Many2many serialized as `{field}_ids` (int[]) + `{field}_names` (str[]) | | Binary fields | Base64-encoded strings or separate download endpoint | | Auth header | `Authorization: Bearer ` | --- ## 33. Implementation Status 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** | --- ## 34. Beyond-SRS Features (Implemented) The developer implemented the following features beyond the original SRS scope. These leverage OpenEduCat Enterprise modules and add significant institutional management capabilities. ### 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)** | --- ## Appendix B: Model Relationship Diagram ``` res.users ──extends──> encoach.user │ │ │ ├── entity_ids ──> encoach.entity │ │ └── role_ids ──> encoach.role │ │ └── permission_ids ──> encoach.permission │ │ │ ├── op_student_id ──> op.student ──> op.student.course ──> op.course │ │ ├── op.batch │ │ ├── op.subject │ │ └── op.department │ │ │ └── op_faculty_id ──> op.faculty │ ├── encoach.exam ──> encoach.subject (taxonomy) │ ├── encoach.domain │ │ └── encoach.topic │ │ ├── encoach.learning.objective │ │ ├── encoach.proficiency │ │ └── encoach.resource │ │ │ └── encoach.learning.plan │ └── encoach.learning.plan.item ──> encoach.topic │ ├── op.academic.year ──> op.academic.term │ ├── op.admission.register ──> op.admission ──> op.student │ ├── op.exam.session ──> op.exam ──> op.exam.attendees │ └── op.marksheet.register ──> op.marksheet.line │ ├── op.assignment ──> op.assignment.sub.line (submissions) │ ├── encoach.course.chapter ──> op.course │ ├── encoach.chapter.material │ ├── encoach.chapter.progress ──> res.users │ └── encoach.topic (bridge to adaptive) │ ├── encoach.discussion.board ──> op.course / op.batch / encoach.course.chapter │ └── encoach.discussion.post (self-referencing for threads) │ ├── encoach.announcement ──> op.course / op.batch │ ├── encoach.message ──> res.users (sender/recipient) │ ├── encoach.notification ──> res.users │ └── encoach.notification.rule (event triggers) │ ├── encoach.faq.category ──> encoach.faq.item │ ├── encoach.approval.workflow ──> encoach.approval.stage │ └── encoach.approval.request │ └── encoach.plagiarism.report ──> submission ``` --- *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.*