feat: integrate client requirements (courseware, communication, notifications, FAQ, enhanced approvals)

Add 4 new Odoo modules coverage:
- encoach_courseware: chapters, materials, chapter progress, AI workbench
- encoach_communication: discussion boards, announcements, messaging
- encoach_notification: notification engine, rules, preferences
- encoach_faq: FAQ categories and items, role-filtered

Frontend changes:
- 4 new type files (courseware, communication, notification, faq)
- 5 new service files (courseware, communication, notification, faq, plagiarism)
- 4 new hook files (useCourseware, useCommunication, useNotifications, useFaq)
- 15 new page components (teacher: chapters, chapter detail, AI workbench,
  discussions, announcements; student: chapter view, discussions, announcements,
  messages, journey; admin: FAQ manager, notification rules, approval config;
  public: official exam access, FAQ page)
- Updated App.tsx routing with all new pages
- Updated TeacherLayout, StudentLayout, AdminLmsLayout sidebars

SRS updates:
- ENCOACH_UNIFIED_SRS.md: added Parts IX-XI (Courseware, Communication,
  Notifications/FAQ), enhanced exam management (exercise vs exam, official
  access modes), enhanced approval workflows (timed stages, escalation,
  bypass), enhanced assignments (late submissions, extensions), plagiarism
  detection. Total modules: 35
- ENCOACH_ODOO19_BACKEND_SRS.md v2.0: added sections 26-31, updated module
  inventory to 35, updated endpoint count to 280+, added enhanced assignment
  models with late submission/extension support

Made-with: Cursor
This commit is contained in:
Talal Sharabi
2026-03-27 00:20:30 +04:00
parent 19d7e01be1
commit 5980451ea8
38 changed files with 4849 additions and 63 deletions

View File

@@ -1,9 +1,9 @@
# EnCoach Platform — Odoo 19 Backend SRS
**Version:** 1.0
**Version:** 2.0
**Date:** March 2026
**Status:** Definitive
**Purpose:** Complete backend specification for an Odoo 19 developer to build all required modules, models, and REST API endpoints for the EnCoach Adaptive Learning Platform.
**Purpose:** Complete backend specification for an Odoo 19 developer to build all required modules, models, and REST API endpoints for the EnCoach Adaptive Learning Platform. Includes courseware, communication, notification, FAQ, enhanced approval workflows, plagiarism detection, and official exam access modes.
---
@@ -33,9 +33,15 @@
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)
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)
---
@@ -47,7 +53,7 @@ This document specifies the complete Odoo 19 backend for the EnCoach Adaptive Le
### 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.
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
@@ -163,8 +169,12 @@ All OpenEduCat models need `to_api_dict()` methods on the `encoach_lms_api` inhe
| 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 |
**Total: 8 OpenEduCat (ported) + 23 custom = 31 modules**
**Total: 8 OpenEduCat (ported) + 27 custom = 35 modules**
---
@@ -611,17 +621,48 @@ Traditional institutional exams (midterms, finals) managed through OpenEduCat. S
Exam-wrapper assignments where an EnCoach exam is assigned to students/classrooms.
### 13.2 API Endpoints
### 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 |
| `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 |
---
@@ -1107,32 +1148,431 @@ Files are stored as `ir.attachment` records. For production, configure Odoo to u
---
## 25. Approval Workflows
## 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` |
| `steps` | One2many | Approval steps |
| `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 API Endpoints
### 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 |
| `PATCH` | `/api/approval-workflows/{id}` | JWT | Update workflow |
| `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. Non-Functional Requirements
## 26. Courseware and Content Delivery
### 26.1 Performance
**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 |
|----|-------------|
@@ -1140,7 +1580,7 @@ Files are stored as `ir.attachment` records. For production, configure Odoo to u
| 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
### 32.2 Security
| ID | Requirement |
|----|-------------|
@@ -1151,7 +1591,7 @@ Files are stored as `ir.attachment` records. For production, configure Odoo to u
| NFR-SEC-05 | File upload size limit: 50MB |
| NFR-SEC-06 | API keys stored in `ir.config_parameter`, never in code |
### 26.3 Scalability
### 32.3 Scalability
| ID | Requirement |
|----|-------------|
@@ -1159,7 +1599,7 @@ Files are stored as `ir.attachment` records. For production, configure Odoo to u
| 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
### 32.4 Reliability
| ID | Requirement |
|----|-------------|
@@ -1167,7 +1607,7 @@ Files are stored as `ir.attachment` records. For production, configure Odoo to u
| NFR-REL-02 | Webhook processing is idempotent |
| NFR-REL-03 | Soft-delete for resources (preserve completion records) |
### 26.5 API Conventions
### 32.5 API Conventions
| Convention | Detail |
|-----------|--------|
@@ -1181,7 +1621,7 @@ Files are stored as `ir.attachment` records. For production, configure Odoo to u
---
## 27. Implementation Priority
## 33. Implementation Priority
| Priority | Modules | Rationale |
|----------|---------|-----------|
@@ -1190,25 +1630,33 @@ Files are stored as `ir.attachment` records. For production, configure Odoo to u
| **P1** | `encoach_taxonomy`, `encoach_adaptive`, `encoach_adaptive_api`, `encoach_adaptive_ai` | Core adaptive learning loop |
| **P1** | `encoach_exam`, `encoach_ai_generation`, `encoach_ai_grading` | Exam engine |
| **P1** | `encoach_resources` | Learning content |
| **P2** | `encoach_courseware` (chapters, materials, progress, AI workbench) | Structured course delivery |
| **P2** | `encoach_communication` (discussions, announcements, messaging) | Collaboration |
| **P2** | `openeducat_timetable`, `openeducat_attendance`, `openeducat_classroom` (port to v19) | LMS timetable/attendance |
| **P2** | `openeducat_admission` (port to v19) + admission endpoints | Enrollment workflow |
| **P2** | Academic years/terms, departments endpoints | Institutional calendar |
| **P2** | `encoach_ai`, `encoach_ai_media` | AI services + media |
| **P2** | `encoach_assignment`, `encoach_classroom` | Assignments + groups |
| **P3** | `encoach_notification` (rules, email delivery, preferences) | User engagement |
| **P3** | Enhanced approval workflows (stages, escalation, bypass) | Governance |
| **P3** | Plagiarism detection (GPTZero integration) | Academic integrity |
| **P3** | Official exam access modes (link, landing, separate login) | Exam security |
| **P3** | Late submission handling, extension requests | Assignment workflow |
| **P3** | `openeducat_exam` (port to v19) + institutional exam endpoints | Institutional assessment |
| **P3** | `openeducat_assignment` (port to v19) + submission endpoints | Homework workflow |
| **P3** | Subject registration endpoints | Student subject selection |
| **P3** | `encoach_training`, analytics endpoints | Training + analytics |
| **P3** | `encoach_sis`, `encoach_branding` | University integration |
| **P4** | `encoach_faq` (categories, items, role-filtered) | User support |
| **P4** | `encoach_subscription` (Stripe, PayPal, Paymob) | Payments |
| **P4** | `encoach_ticket` | Support |
| **P4** | Approval workflows, storage | Operational features |
| **P4** | Storage | Operational features |
---
## Appendix A: Complete Endpoint Summary
Total API endpoints: **200+**
Total API endpoints: **280+**
| Service Area | Endpoint Count |
|-------------|---------------|
@@ -1236,7 +1684,15 @@ Total API endpoints: **200+**
| Subscriptions & Payments | 8 + 3 webhooks |
| Tickets | 4 |
| Storage | 2 |
| Approval Workflows | 4 |
| Approval Workflows (Enhanced) | 11 |
| **Courseware (Chapters + Materials + Workbench)** | **23** |
| **Discussion Boards + Posts** | **9** |
| **Announcements** | **5** |
| **Messaging** | **6** |
| **Notifications + Rules + Preferences** | **10** |
| **FAQ (Categories + Items)** | **8** |
| **Plagiarism Detection** | **3** |
| **Official Exam Access** | **5** |
---
@@ -1273,9 +1729,31 @@ res.users ──extends──> encoach.user
├── op.exam.session ──> op.exam ──> op.exam.attendees
│ └── op.marksheet.register ──> op.marksheet.line
── op.assignment ──> op.assignment.sub.line (submissions)
── 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. It covers all 200+ REST API endpoints expected by the React frontend, all Odoo models (OpenEduCat + custom), and all AI service integrations.*
*This SRS is the definitive backend specification for the EnCoach platform on Odoo 19. It covers all 280+ REST API endpoints expected by the React frontend, 35 Odoo modules (8 OpenEduCat + 27 custom), and all AI service integrations.*