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
This commit is contained in:
1
custom_addons/encoach_pdf_report/controllers/__init__.py
Normal file
1
custom_addons/encoach_pdf_report/controllers/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import reports
|
||||
55
custom_addons/encoach_pdf_report/controllers/reports.py
Normal file
55
custom_addons/encoach_pdf_report/controllers/reports.py
Normal file
@@ -0,0 +1,55 @@
|
||||
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__)
|
||||
|
||||
|
||||
class EncoachReportsController(http.Controller):
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# GET /api/reports/exam/<int:attempt_id>/pdf
|
||||
# ------------------------------------------------------------------
|
||||
@http.route('/api/reports/exam/<int:attempt_id>/pdf', type='http',
|
||||
auth='none', methods=['GET'], csrf=False)
|
||||
@jwt_required
|
||||
def download_exam_pdf(self, attempt_id, **kw):
|
||||
try:
|
||||
Attempt = request.env['encoach.student.attempt'].sudo()
|
||||
attempt = Attempt.browse(attempt_id)
|
||||
if not attempt.exists():
|
||||
return _error_response('Attempt not found', 404)
|
||||
|
||||
user = request.env.user.sudo()
|
||||
is_owner = attempt.student_id.id == user.id
|
||||
is_admin = (
|
||||
user.user_type in ('admin', 'mastercorporate')
|
||||
or user.has_group('base.group_system')
|
||||
)
|
||||
is_teacher = user.user_type == 'teacher'
|
||||
|
||||
if not (is_owner or is_admin or is_teacher):
|
||||
return _error_response('You do not have access to this report', 403)
|
||||
|
||||
from odoo.addons.encoach_pdf_report.services.pdf_generator import PdfGenerator
|
||||
pdf_bytes = PdfGenerator.generate_exam_report(request.env, attempt_id)
|
||||
|
||||
student_name = (attempt.student_id.name or 'student').replace(' ', '_')
|
||||
filename = f"exam_report_{student_name}_{attempt_id}.pdf"
|
||||
|
||||
return request.make_response(
|
||||
pdf_bytes,
|
||||
headers=[
|
||||
('Content-Type', 'application/pdf'),
|
||||
('Content-Disposition', f'attachment; filename="{filename}"'),
|
||||
('Content-Length', str(len(pdf_bytes))),
|
||||
],
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
_logger.exception('download_exam_pdf failed')
|
||||
return _error_response(str(e), 500)
|
||||
Reference in New Issue
Block a user