feat: add complete EnCoach frontend application

Full React 18 + TypeScript + Vite frontend with:
- 90+ pages (admin, student, teacher, public)
- shadcn/ui component library with 50+ components
- JWT authentication with role-based access control
- TanStack React Query for server state management
- 30+ API service modules
- AI-powered features (coaching, grading, generation)
- Adaptive learning UI (diagnostics, proficiency, plans)
- Institutional LMS management (courses, batches, timetable)
- Communication suite (discussions, announcements, DMs)
- Full CRUD with validation and confirmation dialogs

Made-with: Cursor
This commit is contained in:
Yamen Ahmad
2026-04-01 16:59:11 +04:00
commit 110a0b7105
307 changed files with 46583 additions and 0 deletions

249
docs/DEVELOPER_FEEDBACK.md Normal file
View File

@@ -0,0 +1,249 @@
# EnCoach Odoo 19 -- Developer Feedback
**Date:** March 11, 2026
**Status:** ALL ITEMS RESOLVED (March 13, 2026)
**Reference:** ODOO_MIGRATION_SRS_v2.md
---
## Overall Assessment
The delivery covers approximately **85% of the SRS v2 requirements**. All 15 custom modules are present, the core AI/ML services are well-implemented, data models match the specification, and 67-72 API endpoints are wired up with proper JWT authentication and security groups. The code quality is solid -- clean structure, proper error handling, and good separation of concerns.
The items below still need to be implemented to reach full SRS compliance.
---
## 1. Payment Integration (Critical -- Not Implemented)
**SRS Reference:** Section 7
All three payment services are currently stubs that return `"not yet implemented"`. The SRS requires full integration with:
### 1.1 Stripe
**Files:** `encoach_subscription/services/stripe_service.py`
Required functionality:
- Install and use the `stripe` Python SDK
- `create_checkout_session()` -- Create a Stripe Checkout Session using `stripe.checkout.Session.create()` with:
- `line_items` from the selected `encoach.package`
- `success_url` and `cancel_url` from the request
- `client_reference_id` = user ID
- `customer_email` = user email
- Apply discount if `discount_code` is provided (validate against `encoach.discount`)
- Return `{ "sessionId": "cs_...", "url": "https://checkout.stripe.com/..." }`
- **Webhook endpoint** (`POST /api/stripe/webhook`):
- Verify signature using `stripe.Webhook.construct_event()` with `STRIPE_WEBHOOK_SECRET`
- Handle `checkout.session.completed` event:
- Find user by `client_reference_id`
- Extend `subscription_expiration` by the package's `duration_days`
- Create `encoach.subscription.payment` record
- For corporate users, propagate subscription to entity members
### 1.2 PayPal
**Files:** `encoach_subscription/services/paypal_service.py`
Required functionality:
- Use PayPal REST API (`httpx` or `requests`)
- Obtain access token from `PAYPAL_ACCESS_TOKEN_URL` using `client_id` + `client_secret`
- `create_order()` -- Create PayPal order via `POST /v2/checkout/orders`:
- `intent: "CAPTURE"`
- `purchase_units` with amount from package (minus discount)
- Return `{ "orderId": "...", "approvalUrl": "https://paypal.com/..." }`
- `capture_order()` -- Capture approved order via `POST /v2/checkout/orders/{id}/capture`:
- On success, extend subscription and create payment record
- Return `{ "ok": true }`
### 1.3 Paymob
**Files:** `encoach_subscription/services/paymob_service.py`
Required functionality:
- Use Paymob API (`httpx` or `requests`)
- `create_intention()` -- Create payment intention:
- Authenticate with `PAYMOB_API_KEY`
- Create order, then payment key
- Return `{ "intentionId": "...", "clientSecret": "..." }`
- `verify_transaction()` -- Verify webhook callback:
- Validate HMAC using `PAYMOB_SECRET`
- On success, extend subscription and create payment record
- **Webhook endpoint** (`POST /api/paymob/webhook`):
- Verify transaction authenticity
- Update subscription on success
### 1.4 Subscription Extension Logic
After any successful payment (all providers), the system must:
1. Calculate new expiration: `max(current_expiration, now()) + duration_days`
2. Update `user.subscription_expiration`
3. Create `encoach.subscription.payment` record with provider, amount, transaction ID
4. For corporate users: propagate the new expiration to all entity members
---
## 2. Missing API Endpoints
**SRS Reference:** Section 4
The following endpoints are specified in the SRS but not present in the delivery:
### 2.1 Exam Variants (add to `encoach_api/controllers/generation.py` or `exams.py`)
| Endpoint | Method | Description |
|----------|--------|-------------|
| `POST /api/exam/writing/<task>/attachment` | POST | Academic writing Task 1 with image upload (multipart form with `file` + `difficulty`). Must send image to GPT-4o vision API for prompt generation. |
| `GET /api/exam/level/` | GET | Return a pre-built level exam (no AI generation) |
| `GET /api/exam/level/utas` | GET | Return a UTAS-format level exam |
| `POST /api/exam/level/import/` | POST | Import level exam from uploaded file |
| `POST /api/exam/level/custom/` | POST | Generate custom level exam from JSON specification |
| `POST /api/exam/reading/import` | POST | Import reading exam from Word/Excel file |
| `POST /api/exam/listening/import` | POST | Import listening exam from file |
### 2.2 Entity/Role/Permission Management (new controller files needed)
| Endpoint | Method | Description |
|----------|--------|-------------|
| `GET /api/entities` | GET | List entities (with pagination) |
| `POST /api/entities` | POST | Create entity |
| `PATCH /api/entities/<id>` | PATCH | Update entity |
| `DELETE /api/entities/<id>` | DELETE | Delete entity |
| `GET /api/roles` | GET | List roles (filter by entityID) |
| `POST /api/roles` | POST | Create role |
| `PATCH /api/roles/<id>` | PATCH | Update role |
| `DELETE /api/roles/<id>` | DELETE | Delete role |
| `GET /api/permissions` | GET | List permissions |
### 2.3 Other Missing Endpoints
| Endpoint | Method | Description |
|----------|--------|-------------|
| `GET /api/discounts` | GET | List discount codes |
| `POST /api/discounts` | POST | Create discount code |
| `PATCH /api/discounts/<id>` | PATCH | Update discount code |
| `DELETE /api/discounts/<id>` | DELETE | Delete discount code |
| `GET /api/approval-workflows` | GET | List approval workflows |
| `POST /api/approval-workflows` | POST | Create approval workflow |
| `PATCH /api/approval-workflows/<id>` | PATCH | Update approval workflow |
| `DELETE /api/approval-workflows/<id>` | DELETE | Delete approval workflow |
---
## 3. Evaluation Status Endpoint Path
**SRS Reference:** Section 4.2
**Current:** `GET /api/evaluate/status?sessionId=...&exerciseId=...` (query params)
**SRS specifies:** `GET /api/evaluate/<sessionId>/<exerciseId>` (path params)
The frontend SRS document (`ODOO_MIGRATION_FRONTEND_SRS.md`) references the path-param version. Please either:
- (A) Change the endpoint to use path params to match the SRS, OR
- (B) Confirm that query params are intentional so we can update the frontend SRS
---
## 4. Record-Level Security Rules (`ir.rule`)
**SRS Reference:** Section 5
The delivery has model-level ACL rules (`ir.model.access.csv`) for each module, which is good. However, record-level security rules (`ir.rule`) are also needed to ensure:
- **Students** can only read/write their own records (sessions, stats, evaluations, training, tickets)
- **Teachers** can see records for students in their groups/assignments
- **Corporate** users can see records within their entity
- **Admin/Developer** users have unrestricted access
Example rules needed (add to each module's `security/` directory):
```xml
<!-- encoach_stats/security/rules.xml -->
<record id="rule_stat_student_own" model="ir.rule">
<field name="name">Students see own stats</field>
<field name="model_id" ref="model_encoach_stat"/>
<field name="groups" eval="[(4, ref('encoach_core.group_encoach_student'))]"/>
<field name="domain_force">[('user_id', '=', user.id)]</field>
</record>
```
Models that need record rules:
- `encoach.session` -- students see own sessions only
- `encoach.stat` -- students see own stats only
- `encoach.evaluation` -- students see own evaluations only
- `encoach.training` -- students see own training only
- `encoach.ticket` -- students see own tickets, admins see all
- `encoach.assignment` -- students see assignments they're assigned to
- `encoach.exam` -- filtered by access field (public/private/entity)
---
## 5. Whisper Scaling
**SRS Reference:** Section 6.5
**Current:** Single lazy-loaded Whisper model instance in `whisper_service.py`
**SRS specifies:** 4 model instances with `ThreadPoolExecutor(max_workers=4)` for parallel transcription
Update `encoach_ai_media/services/whisper_service.py` to:
1. Load the configurable number of model instances (from `encoach.whisper_workers` system parameter, default 4)
2. Use `concurrent.futures.ThreadPoolExecutor` to process transcription requests in parallel
3. Round-robin or queue-based assignment of requests to model instances
This is important for production performance when multiple students submit speaking exams simultaneously.
---
## 6. FAISS Index Type
**SRS Reference:** Section 6.8
**Current:** `faiss.IndexFlatIP` (inner product)
**SRS specifies:** `faiss.IndexFlatL2` (L2/Euclidean distance)
The current implementation normalizes vectors and uses inner product, which effectively gives cosine similarity. This works correctly, but it's a deviation from the SRS. If the original `ielts-be` training data was built with L2 distance, the results may differ slightly. Please verify which index type the original system used and align accordingly.
---
## 7. Payment Webhook Endpoints
**SRS Reference:** Section 7
In addition to the payment service implementations (Item 1 above), the following webhook controller routes need to be added to `encoach_api/controllers/subscriptions.py`:
```python
@http.route('/api/stripe/webhook', type='http', auth='public', methods=['POST'], csrf=False, cors='*')
def stripe_webhook(self, **kwargs):
"""Handle Stripe webhook events (checkout.session.completed, etc.)."""
...
@http.route('/api/paymob/webhook', type='http', auth='public', methods=['POST'], csrf=False, cors='*')
def paymob_webhook(self, **kwargs):
"""Handle Paymob transaction callbacks."""
...
```
These must be `auth='public'` (no JWT) since they're called by external services.
---
## Summary of Action Items
| # | Item | Priority | Status |
|---|------|----------|--------|
| 1 | Payment integration (Stripe/PayPal/Paymob) | **Critical** | RESOLVED |
| 2 | Missing API endpoints (~20 endpoints) | **High** | RESOLVED |
| 3 | Evaluation status endpoint path alignment | **Medium** | RESOLVED |
| 4 | `ir.rule` record-level security rules | **High** | RESOLVED |
| 5 | Whisper multi-instance scaling | **Medium** | RESOLVED |
| 6 | FAISS index type verification | **Low** | RESOLVED |
| 7 | Payment webhook endpoints | **Critical** | RESOLVED |
---
## Changes Already Applied
The following small fixes have been applied directly to the codebase:
1. **`encoach_ai_media/__manifest__.py`** -- Added missing `external_dependencies`: `numpy`, `openai-whisper`, `librosa`, `soundfile`, `httpx`
2. **`encoach_training/__manifest__.py`** -- Added missing `external_dependencies`: `numpy`, `faiss-cpu`, `sentence-transformers`
3. **`requirements.txt`** -- Created at project root with all Python dependencies and versions from SRS Section 6.10