Full backend implementation with custom Odoo modules: - encoach_api: Core API, user management, JWT auth - encoach_exam: Exam generation (reading, writing, listening, speaking) - encoach_evaluate: AI-powered evaluation (writing, speaking) - encoach_training: Training tips and walkthrough - encoach_storage: File storage management - encoach_payment: Stripe, PayPal, Paymob integration - encoach_mail: Email notifications Made-with: Cursor
10 KiB
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
stripePython SDK create_checkout_session()-- Create a Stripe Checkout Session usingstripe.checkout.Session.create()with:line_itemsfrom the selectedencoach.packagesuccess_urlandcancel_urlfrom the requestclient_reference_id= user IDcustomer_email= user email- Apply discount if
discount_codeis provided (validate againstencoach.discount)
- Return
{ "sessionId": "cs_...", "url": "https://checkout.stripe.com/..." } - Webhook endpoint (
POST /api/stripe/webhook):- Verify signature using
stripe.Webhook.construct_event()withSTRIPE_WEBHOOK_SECRET - Handle
checkout.session.completedevent:- Find user by
client_reference_id - Extend
subscription_expirationby the package'sduration_days - Create
encoach.subscription.paymentrecord - For corporate users, propagate subscription to entity members
- Find user by
- Verify signature using
1.2 PayPal
Files: encoach_subscription/services/paypal_service.py
Required functionality:
- Use PayPal REST API (
httpxorrequests) - Obtain access token from
PAYPAL_ACCESS_TOKEN_URLusingclient_id+client_secret create_order()-- Create PayPal order viaPOST /v2/checkout/orders:intent: "CAPTURE"purchase_unitswith amount from package (minus discount)- Return
{ "orderId": "...", "approvalUrl": "https://paypal.com/..." }
capture_order()-- Capture approved order viaPOST /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 (
httpxorrequests) create_intention()-- Create payment intention:- Authenticate with
PAYMOB_API_KEY - Create order, then payment key
- Return
{ "intentionId": "...", "clientSecret": "..." }
- Authenticate with
verify_transaction()-- Verify webhook callback:- Validate HMAC using
PAYMOB_SECRET - On success, extend subscription and create payment record
- Validate HMAC using
- 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:
- Calculate new expiration:
max(current_expiration, now()) + duration_days - Update
user.subscription_expiration - Create
encoach.subscription.paymentrecord with provider, amount, transaction ID - 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):
<!-- 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 onlyencoach.stat-- students see own stats onlyencoach.evaluation-- students see own evaluations onlyencoach.training-- students see own training onlyencoach.ticket-- students see own tickets, admins see allencoach.assignment-- students see assignments they're assigned toencoach.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:
- Load the configurable number of model instances (from
encoach.whisper_workerssystem parameter, default 4) - Use
concurrent.futures.ThreadPoolExecutorto process transcription requests in parallel - 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:
@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:
encoach_ai_media/__manifest__.py-- Added missingexternal_dependencies:numpy,openai-whisper,librosa,soundfile,httpxencoach_training/__manifest__.py-- Added missingexternal_dependencies:numpy,faiss-cpu,sentence-transformersrequirements.txt-- Created at project root with all Python dependencies and versions from SRS Section 6.10