EnCoach Odoo 19 custom modules
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
This commit is contained in:
117
encoach_api/controllers/training.py
Normal file
117
encoach_api/controllers/training.py
Normal file
@@ -0,0 +1,117 @@
|
||||
import json
|
||||
import logging
|
||||
|
||||
from odoo import http
|
||||
from odoo.http import request
|
||||
|
||||
from .base import EncoachMixin
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class TrainingController(EncoachMixin, http.Controller):
|
||||
|
||||
# ----------------------------------------------------------- generate
|
||||
@http.route('/api/training', type='http', auth='public', methods=['POST', 'OPTIONS'], csrf=False, cors='*')
|
||||
def generate_training(self, **kwargs):
|
||||
"""Generate personalised training content using FAISS + GPT."""
|
||||
try:
|
||||
user = self._authenticate()
|
||||
if not user:
|
||||
return self._error_response('Unauthorized', 401)
|
||||
|
||||
body = self._get_json_body()
|
||||
target_user_id = body.get('userID', user.id)
|
||||
stats = body.get('stats', [])
|
||||
|
||||
Training = request.env['encoach.training'].sudo()
|
||||
training = Training.generate_training(
|
||||
user_id=int(target_user_id),
|
||||
stats=stats,
|
||||
)
|
||||
|
||||
return self._json_response({
|
||||
'id': training.id,
|
||||
'_id': str(training.id),
|
||||
})
|
||||
except Exception:
|
||||
_logger.exception("Generate training error")
|
||||
return self._error_response('Internal server error', 500)
|
||||
|
||||
# -------------------------------------------------------- get record
|
||||
@http.route(
|
||||
'/api/training/<int:tid>', type='http', auth='public',
|
||||
methods=['GET', 'OPTIONS'], csrf=False, cors='*',
|
||||
)
|
||||
def get_training(self, tid, **kwargs):
|
||||
try:
|
||||
user = self._authenticate()
|
||||
if not user:
|
||||
return self._error_response('Unauthorized', 401)
|
||||
|
||||
training = request.env['encoach.training'].sudo().browse(tid)
|
||||
if not training.exists():
|
||||
return self._error_response('Training record not found', 404)
|
||||
|
||||
return self._json_response({
|
||||
'_id': str(training.id),
|
||||
'id': training.id,
|
||||
'userId': str(training.user_id.id) if training.user_id else None,
|
||||
'createdAt': training.created_at.isoformat() if getattr(training, 'created_at', None) else (
|
||||
training.create_date.isoformat() if training.create_date else None
|
||||
),
|
||||
'exams': json.loads(training.exams) if getattr(training, 'exams', None) else [],
|
||||
'tips': json.loads(training.tips) if getattr(training, 'tips', None) else {},
|
||||
'weakAreas': json.loads(training.weak_areas) if getattr(training, 'weak_areas', None) else [],
|
||||
})
|
||||
except Exception:
|
||||
_logger.exception("Get training error")
|
||||
return self._error_response('Internal server error', 500)
|
||||
|
||||
# ------------------------------------------------------------- tips
|
||||
@http.route('/api/training/tips', type='http', auth='public', methods=['POST', 'OPTIONS'], csrf=False, cors='*')
|
||||
def fetch_tips(self, **kwargs):
|
||||
"""Retrieve contextual tips using FAISS semantic search + GPT."""
|
||||
try:
|
||||
user = self._authenticate()
|
||||
if not user:
|
||||
return self._error_response('Unauthorized', 401)
|
||||
|
||||
body = self._get_json_body()
|
||||
Training = request.env['encoach.training'].sudo()
|
||||
tips = Training.fetch_tips(
|
||||
context=body.get('context', ''),
|
||||
question=body.get('question', ''),
|
||||
answer=body.get('answer', ''),
|
||||
correct_answer=body.get('correct_answer', ''),
|
||||
)
|
||||
|
||||
return self._json_response({'tips': tips})
|
||||
except Exception:
|
||||
_logger.exception("Fetch tips error")
|
||||
return self._error_response('Internal server error', 500)
|
||||
|
||||
# ------------------------------------------------------ walkthrough
|
||||
@http.route('/api/training/walkthrough', type='http', auth='public', methods=['GET', 'OPTIONS'], csrf=False, cors='*')
|
||||
def get_walkthrough(self, **kwargs):
|
||||
try:
|
||||
user = self._authenticate()
|
||||
if not user:
|
||||
return self._error_response('Unauthorized', 401)
|
||||
|
||||
Walkthrough = request.env['encoach.walkthrough'].sudo()
|
||||
records = Walkthrough.search([], order='sequence asc')
|
||||
|
||||
data = [{
|
||||
'_id': str(w.id),
|
||||
'id': w.id,
|
||||
'title': getattr(w, 'title', ''),
|
||||
'description': getattr(w, 'description', ''),
|
||||
'steps': json.loads(w.steps) if getattr(w, 'steps', None) else [],
|
||||
'module': getattr(w, 'module', ''),
|
||||
} for w in records]
|
||||
|
||||
return self._json_response(data)
|
||||
except Exception:
|
||||
_logger.exception("Get walkthrough error")
|
||||
return self._error_response('Internal server error', 500)
|
||||
Reference in New Issue
Block a user