fix: harden admin access, repair ORM joins, and add migration/tests
This commit is contained in:
@@ -18,7 +18,7 @@ from dataclasses import dataclass, field
|
||||
import logging
|
||||
|
||||
import pandas as pd
|
||||
from sqlalchemy import select, func, and_, or_
|
||||
from sqlalchemy import Integer, and_, cast, func, or_, select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy.orm import selectinload
|
||||
|
||||
@@ -415,7 +415,7 @@ async def generate_item_analysis_report(
|
||||
resp_result = await db.execute(
|
||||
select(
|
||||
func.count().label("total"),
|
||||
func.sum(func.cast(UserAnswer.is_correct, type_=func.INTEGER)).label("correct")
|
||||
func.sum(cast(UserAnswer.is_correct, Integer)).label("correct")
|
||||
).where(UserAnswer.item_id == item.id)
|
||||
)
|
||||
resp_stats = resp_result.first()
|
||||
@@ -678,7 +678,7 @@ async def generate_tryout_comparison_report(
|
||||
cal_result = await db.execute(
|
||||
select(
|
||||
func.count().label("total"),
|
||||
func.sum(func.cast(Item.calibrated, type_=func.INTEGER)).label("calibrated")
|
||||
func.sum(cast(Item.calibrated, Integer)).label("calibrated")
|
||||
).where(
|
||||
Item.tryout_id == tryout_id,
|
||||
Item.website_id == website_id,
|
||||
@@ -704,15 +704,56 @@ async def generate_tryout_comparison_report(
|
||||
if tryout:
|
||||
date_str = tryout.created_at.strftime("%Y-%m-%d")
|
||||
|
||||
session_result = await db.execute(
|
||||
select(
|
||||
func.count(Session.id).label("participant_count"),
|
||||
func.avg(Session.NM).label("avg_nm"),
|
||||
func.avg(Session.NN).label("avg_nn"),
|
||||
func.avg(Session.theta).label("avg_theta"),
|
||||
func.stddev_pop(Session.NM).label("std_nm"),
|
||||
).where(
|
||||
Session.tryout_id == tryout_id,
|
||||
Session.website_id == website_id,
|
||||
Session.is_completed.is_(True),
|
||||
)
|
||||
)
|
||||
session_stats = session_result.first()
|
||||
|
||||
participant_count = (
|
||||
int(session_stats.participant_count)
|
||||
if session_stats and session_stats.participant_count
|
||||
else (stats.participant_count if stats else 0)
|
||||
)
|
||||
avg_nm = (
|
||||
round(float(session_stats.avg_nm), 2)
|
||||
if session_stats and session_stats.avg_nm is not None
|
||||
else (round(float(stats.rataan), 2) if stats and stats.rataan is not None else None)
|
||||
)
|
||||
avg_nn = (
|
||||
round(float(session_stats.avg_nn), 2)
|
||||
if session_stats and session_stats.avg_nn is not None
|
||||
else None
|
||||
)
|
||||
avg_theta = (
|
||||
round(float(session_stats.avg_theta), 4)
|
||||
if session_stats and session_stats.avg_theta is not None
|
||||
else None
|
||||
)
|
||||
std_nm = (
|
||||
round(float(session_stats.std_nm), 2)
|
||||
if session_stats and session_stats.std_nm is not None
|
||||
else (round(float(stats.sb), 2) if stats and stats.sb is not None else None)
|
||||
)
|
||||
|
||||
record = TryoutComparisonRecord(
|
||||
tryout_id=tryout_id,
|
||||
date=date_str,
|
||||
subject=subject,
|
||||
participant_count=stats.participant_count if stats else 0,
|
||||
avg_nm=round(stats.rataan, 2) if stats and stats.rataan else None,
|
||||
avg_nn=round(stats.rataan + 500, 2) if stats and stats.rataan else None,
|
||||
avg_theta=None, # Would need to calculate from sessions
|
||||
std_nm=round(stats.sb, 2) if stats and stats.sb else None,
|
||||
participant_count=participant_count,
|
||||
avg_nm=avg_nm,
|
||||
avg_nn=avg_nn,
|
||||
avg_theta=avg_theta,
|
||||
std_nm=std_nm,
|
||||
calibration_percentage=round(cal_percentage, 2),
|
||||
)
|
||||
comparison_records.append(record)
|
||||
|
||||
Reference in New Issue
Block a user