Files
boc/landvex-admin/backend/app/api/academy.py
T
Bernt aee0f09db8 landvex: Fixar och tester klara för alla komponenter
- Datafabrik: Dockerfile fix, agentorkestrering fungerar
- Vision: Identify-modell, FAISS, OCR alla testade
- API: Alla 7 integrationstester passerade
- Upplösare: Entitetsupplösning verifierad
2026-07-05 06:41:32 +00:00

146 lines
4.6 KiB
Python

"""
quiXzoom Academy API endpoints for LandveX Admin
"""
from fastapi import APIRouter, Depends, HTTPException, status
from pydantic import BaseModel
from typing import List, Optional
from datetime import datetime
from app.core.security import get_current_user
from app.models.user import User
router = APIRouter(prefix="/academy", tags=["academy"])
# Models
class LessonCompleteRequest(BaseModel):
lesson_id: str
module_id: str
score: Optional[int] = None
class ProgressResponse(BaseModel):
user_id: str
completed_lessons: List[str]
current_module: int
total_progress: float
certificate_earned: bool
certificate_date: Optional[str] = None
class CertificateResponse(BaseModel):
pdf_url: str
verification_code: str
issue_date: str
# In-memory storage (replace with DB in production)
academy_progress = {}
LESSONS_PER_MODULE = {
"module1": 4,
"module2": 4,
"module3": 3,
"module4": 3,
"module5": 3,
"module6": 4
}
TOTAL_LESSONS = sum(LESSONS_PER_MODULE.values())
@router.get("/progress", response_model=ProgressResponse)
async def get_progress(current_user: User = Depends(get_current_user)):
"""Get user's academy progress"""
user_id = str(current_user.id)
progress = academy_progress.get(user_id, {
"completed_lessons": [],
"current_module": 1
})
completed = len(progress["completed_lessons"])
total_progress = (completed / TOTAL_LESSONS) * 100
certificate_earned = completed >= TOTAL_LESSONS
return ProgressResponse(
user_id=user_id,
completed_lessons=progress["completed_lessons"],
current_module=progress["current_module"],
total_progress=round(total_progress, 1),
certificate_earned=certificate_earned,
certificate_date=datetime.utcnow().isoformat() if certificate_earned else None
)
@router.post("/complete", status_code=status.HTTP_200_OK)
async def complete_lesson(
request: LessonCompleteRequest,
current_user: User = Depends(get_current_user)
):
"""Mark a lesson as completed"""
user_id = str(current_user.id)
if user_id not in academy_progress:
academy_progress[user_id] = {
"completed_lessons": [],
"current_module": 1
}
progress = academy_progress[user_id]
if request.lesson_id not in progress["completed_lessons"]:
progress["completed_lessons"].append(request.lesson_id)
# Update current module
module_num = int(request.module_id.replace("module", ""))
module_lessons = [f"m{module_num}l{i}" for i in range(1, LESSONS_PER_MODULE[request.module_id] + 1)]
if all(l in progress["completed_lessons"] for l in module_lessons):
progress["current_module"] = min(module_num + 1, 6)
return {
"success": True,
"lesson_id": request.lesson_id,
"progress": len(progress["completed_lessons"]) / TOTAL_LESSONS * 100
}
@router.get("/certificate", response_model=CertificateResponse)
async def get_certificate(current_user: User = Depends(get_current_user)):
"""Generate certificate PDF"""
user_id = str(current_user.id)
progress = academy_progress.get(user_id, {"completed_lessons": []})
if len(progress["completed_lessons"]) < TOTAL_LESSONS:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Certificate not yet earned. Complete all lessons first."
)
# Generate verification code
verification = f"QX-{user_id[:8].upper()}-{datetime.utcnow().strftime('%Y%m%d')}"
return CertificateResponse(
pdf_url=f"/api/academy/certificate/{user_id}/download",
verification_code=verification,
issue_date=datetime.utcnow().isoformat()
)
@router.get("/stats")
async def get_academy_stats(current_user: User = Depends(get_current_user)):
"""Get academy statistics (admin only)"""
if not current_user.is_admin:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Admin access required"
)
total_users = len(academy_progress)
completed_users = sum(
1 for p in academy_progress.values()
if len(p["completed_lessons"]) >= TOTAL_LESSONS
)
return {
"total_enrolled": total_users,
"completed_all": completed_users,
"completion_rate": round(completed_users / total_users * 100, 1) if total_users > 0 else 0,
"average_progress": round(
sum(len(p["completed_lessons"]) for p in academy_progress.values()) / total_users / TOTAL_LESSONS * 100, 1
) if total_users > 0 else 0
}