Files
encoach_backend_v4/custom_addons/encoach_exam_template/controllers/templates.py
Yamen Ahmad 907a5c0e92 feat(v3): restructure project + add complete frontend
- Restructure: move backend from new_project/ to backend/
- Add full React/TypeScript frontend (37 pages, 17 services, 16 type defs, 11 query hooks)
- Add docs/ with SRS specs, user stories, and workflow documentation
- Update .gitignore for new directory layout

Workflows implemented:
  WF1 User Signup, WF2 Placement Test, WF3 Exam Configuration,
  WF4 General English Exam, WF5 Course Generation,
  WF6 Entity Student Onboarding, AI Course Generation,
  Adaptive Learning Engine UI, White-Label Branding, Score Release

Made-with: Cursor
2026-04-10 17:26:42 +04:00

131 lines
4.8 KiB
Python

import json
import logging
from odoo import http
from odoo.http import request
from odoo.addons.encoach_api.controllers.base import (
jwt_required, _json_response, _error_response, _get_json_body, _paginate
)
_logger = logging.getLogger(__name__)
def _template_to_dict(rec):
structure = None
if rec.structure:
try:
structure = json.loads(rec.structure)
except (json.JSONDecodeError, TypeError):
structure = rec.structure
return {
'id': rec.id,
'name': rec.name,
'code': rec.code or '',
'type': rec.type,
'editable': rec.editable,
'active': rec.active,
'subject_id': rec.subject_id.id if rec.subject_id else None,
'subject_name': rec.subject_id.name if rec.subject_id else None,
'entity_id': rec.entity_id.id if rec.entity_id else None,
'teacher_id': rec.teacher_id.id if rec.teacher_id else None,
'structure': structure,
'total_time_min': rec.total_time_min or 0,
'pass_threshold': rec.pass_threshold or 0.0,
'results_release_mode': rec.results_release_mode or 'auto',
'randomize_questions': rec.randomize_questions,
'description': rec.description or '',
}
class EncoachTemplatesController(http.Controller):
# ------------------------------------------------------------------
# GET /api/exam/templates
# ------------------------------------------------------------------
@http.route('/api/exam/templates', type='http', auth='none',
methods=['GET'], csrf=False)
@jwt_required
def list_templates(self, **kw):
try:
domain = [('active', '=', True)]
tpl_type = kw.get('type')
if tpl_type in ('international', 'custom'):
domain.append(('type', '=', tpl_type))
subject_id = kw.get('subject_id')
if subject_id:
domain.append(('subject_id', '=', int(subject_id)))
page = int(kw.get('page', 1))
size = int(kw.get('size', 20))
Template = request.env['encoach.exam.template'].sudo()
records, total = _paginate(Template, domain, page=page, size=size)
return _json_response({
'items': [_template_to_dict(r) for r in records],
'total': total,
'page': page,
'size': size,
})
except Exception as e:
_logger.exception('list_templates failed')
return _error_response(str(e), 500)
# ------------------------------------------------------------------
# GET /api/exam/templates/<int:template_id>
# ------------------------------------------------------------------
@http.route('/api/exam/templates/<int:template_id>', type='http',
auth='none', methods=['GET'], csrf=False)
@jwt_required
def get_template(self, template_id, **kw):
try:
rec = request.env['encoach.exam.template'].sudo().browse(template_id)
if not rec.exists():
return _error_response('Template not found', 404)
return _json_response(_template_to_dict(rec))
except Exception as e:
_logger.exception('get_template failed')
return _error_response(str(e), 500)
# ------------------------------------------------------------------
# POST /api/exam/templates/custom
# ------------------------------------------------------------------
@http.route('/api/exam/templates/custom', type='http', auth='none',
methods=['POST'], csrf=False)
@jwt_required
def create_custom_template(self, **kw):
try:
body = _get_json_body()
name = body.get('name', '').strip()
if not name:
return _error_response('name is required', 400)
structure = body.get('structure')
if structure and not isinstance(structure, str):
structure = json.dumps(structure)
vals = {
'name': name,
'type': 'custom',
'teacher_id': request.env.user.id,
'subject_id': body.get('subject_id'),
'structure': structure,
'total_time_min': body.get('total_time_min', 0),
'pass_threshold': body.get('pass_threshold', 0.0),
'results_release_mode': body.get('results_release_mode', 'auto'),
'randomize_questions': body.get('randomize_questions', False),
'description': body.get('description', ''),
}
rec = request.env['encoach.exam.template'].sudo().create(vals)
return _json_response(_template_to_dict(rec), 201)
except Exception as e:
_logger.exception('create_custom_template failed')
return _error_response(str(e), 500)