Fix UI bugs, admin bulk upload limits, test ingestion bugs, and reset demo users

This commit is contained in:
2026-09-25 14:21:48 +05:30
parent 08e54ac055
commit eefcb12ffc
9 changed files with 5911 additions and 146 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -236,9 +236,13 @@ async def bulk_register_students(file: UploadFile = File(...), session: Session
decoded = content.decode('utf-8-sig')
csv_reader = csv.DictReader(io.StringIO(decoded))
rows = list(csv_reader)
if len(rows) > 500:
raise HTTPException(status_code=400, detail="Maximum limit of 500 users per bulk registration exceeded.")
results = []
for row in csv_reader:
for row in rows:
email = row.get("email", "").strip()
name = row.get("name", "").strip()
phone = row.get("phone", "").strip()
@@ -436,7 +440,7 @@ def login(payload: LoginPayload, session: Session = Depends(get_session)):
# --- CBT ENGINE ---
@app.get("/api/tests", response_model=List[models.Test], tags=["CBT Engine"])
def list_active_tests(exam_pattern: Optional[str] = None, type: Optional[str] = None, session: Session = Depends(get_session), current_user: models.User = Depends(require_tier([models.TierEnum.PRO, models.TierEnum.AI_COACH]))):
def list_active_tests(exam_pattern: Optional[str] = None, type: Optional[str] = None, session: Session = Depends(get_session), current_user: models.User = Depends(get_current_user)):
query = select(models.Test).where(models.Test.is_active == True)
if exam_pattern:
if exam_pattern == 'JEE_NEET':
@@ -450,14 +454,14 @@ def list_active_tests(exam_pattern: Optional[str] = None, type: Optional[str] =
return session.exec(query).all()
@app.get("/api/tests/{test_id}", response_model=models.Test, tags=["CBT Engine"])
def get_test_by_id(test_id: UUID, user_id: Optional[UUID] = None, session: Session = Depends(get_session), current_user: models.User = Depends(require_tier([models.TierEnum.PRO, models.TierEnum.AI_COACH]))):
def get_test_by_id(test_id: UUID, user_id: Optional[UUID] = None, session: Session = Depends(get_session), current_user: models.User = Depends(get_current_user)):
test = session.get(models.Test, test_id)
if not test:
raise HTTPException(status_code=404, detail="Requested examination structure not found.")
return test
@app.get("/api/tests/{test_id}/questions", response_model=List[models.Question], tags=["CBT Engine"])
def get_questions_by_test_id(test_id: UUID, session: Session = Depends(get_session), current_user: models.User = Depends(require_tier([models.TierEnum.PRO, models.TierEnum.AI_COACH]))):
def get_questions_by_test_id(test_id: UUID, session: Session = Depends(get_session), current_user: models.User = Depends(get_current_user)):
test = session.get(models.Test, test_id)
if not test:
raise HTTPException(status_code=404, detail="Requested examination structure not found.")
@@ -498,7 +502,7 @@ def get_question_by_id(question_id: UUID, session: Session = Depends(get_session
return question
@app.post("/api/attempts/submit", response_model=models.Attempt, tags=["CBT Engine"])
def submit_test_attempt(payload: Dict[str, Any], session: Session = Depends(get_session), current_user: models.User = Depends(require_tier([models.TierEnum.PRO, models.TierEnum.AI_COACH]))):
def submit_test_attempt(payload: Dict[str, Any], session: Session = Depends(get_session), current_user: models.User = Depends(get_current_user)):
user_id = payload.get("user_id")
source_type_raw = payload.get("source_type", "Test")
source_id = payload.get("source_id")

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,30 @@
from uuid import UUID
from sqlmodel import Session
from database import engine
import models
from main import ensure_demo_user
demo_ids = [
UUID("11111111-1111-1111-1111-111111111111"),
UUID("22222222-2222-2222-2222-222222222222"),
UUID("33333333-3333-3333-3333-333333333333"),
UUID("44444444-4444-4444-4444-444444444444")
]
with Session(engine) as session:
for uid in demo_ids:
existing = session.get(models.User, uid)
if existing:
print(f"Deleting {existing.name}...")
session.exec(models.Subscription.__table__.delete().where(models.Subscription.user_id == uid))
session.exec(models.Mistake.__table__.delete().where(models.Mistake.user_id == uid))
session.exec(models.Attempt.__table__.delete().where(models.Attempt.user_id == uid))
session.exec(models.StudyPlan.__table__.delete().where(models.StudyPlan.user_id == uid))
session.exec(models.Transaction.__table__.delete().where(models.Transaction.user_id == uid))
session.delete(existing)
session.commit()
user = ensure_demo_user(uid, session)
print(f"Recreated: {user.name}")

64
backend/upload_test.py Normal file
View File

@@ -0,0 +1,64 @@
import sys
sys.path.append('.')
from sqlmodel import Session, select
from database import engine
from models import User, Test, Question, QuestionTypeEnum, ExamEnum
def upload_json():
import json
with open('neet_180_questions.json', 'r', encoding='utf-8') as f:
questions = json.load(f)
with Session(engine) as session:
admin = session.exec(select(User).where(User.tier == 'AI Coach')).first()
if not admin:
print('No admin found')
return
payload = {
'title': 'Test NEET Mock Upload',
'type': 'Mock',
'exam_pattern': 'NEET',
'time_limit': 180,
'admin_id': str(admin.id),
'questions_json': questions
}
test_obj = Test(
title=payload['title'],
type=payload['type'],
exam_pattern=ExamEnum.NEET,
sections={},
total_time=payload['time_limit'],
difficulty='Hard',
is_active=True,
created_by=admin.id
)
session.add(test_obj)
session.flush()
for q in questions:
q_obj = Question(
subject=q.get('subject'),
topic=q.get('topic', 'General'),
subtopic=q.get('subtopic', ''),
difficulty=q.get('difficulty', 'Medium'),
type=QuestionTypeEnum(q.get('type', 'SCQ')),
question_text=q.get('question_text', ''),
options_json=q.get('options', []),
correct_answer=q.get('correct_answer', ''),
solution_text=q.get('explanation', ''), language='English',
test_id=test_obj.id, created_by=admin.id,
section_name=q.get('subject')
)
session.add(q_obj)
session.commit()
print('Successfully added test with ID:', test_obj.id)
upload_json()