# EnCoach Platform — Odoo 19 Backend SRS **Version:** 1.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. --- ## 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](#25-approval-workflows) 26. [Non-Functional Requirements](#26-non-functional-requirements) 27. [Implementation Priority](#27-implementation-priority) --- ## 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 24 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 | **Total: 8 OpenEduCat (ported) + 23 custom = 31 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 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 | | `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) | --- ## 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 ### 25.1 Model (`encoach.approval.workflow`) | Field | Type | Description | |-------|------|-------------| | `name` | Char | Workflow name | | `type` | Selection | `exam_publish`, `assignment_publish`, `content_publish` | | `steps` | One2many | Approval steps | | `entity_id` | Many2one | Entity | | `active` | Boolean | Active flag | ### 25.2 API Endpoints | Method | Path | Auth | Description | |--------|------|------|-------------| | `GET` | `/api/approval-workflows` | JWT | Paginated workflows | | `POST` | `/api/approval-workflows` | JWT | Create workflow | | `PATCH` | `/api/approval-workflows/{id}` | JWT | Update workflow | | `DELETE` | `/api/approval-workflows/{id}` | JWT | Delete workflow | --- ## 26. Non-Functional Requirements ### 26.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` | ### 26.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 | ### 26.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 | ### 26.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) | ### 26.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 ` | --- ## 27. Implementation Priority | 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** | `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** | `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_subscription` (Stripe, PayPal, Paymob) | Payments | | **P4** | `encoach_ticket` | Support | | **P4** | Approval workflows, storage | Operational features | --- ## Appendix A: Complete Endpoint Summary Total API endpoints: **200+** | 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 | 4 | --- ## 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) ``` --- *This SRS is the definitive backend specification for the EnCoach platform on Odoo 19. It covers all 200+ REST API endpoints expected by the React frontend, all Odoo models (OpenEduCat + custom), and all AI service integrations.*