feat: complete UI tasks, backend optimizations, coupon admin, user kundli
This commit is contained in:
@@ -147,6 +147,14 @@ def submit_test_attempt(payload: Dict[str, Any], session: Session = Depends(get_
|
||||
attempt_id_str = payload.get("id")
|
||||
import uuid as _uuid
|
||||
attempt_id = _uuid.UUID(attempt_id_str) if attempt_id_str else _uuid.uuid4()
|
||||
|
||||
# Check if this is a retake
|
||||
existing_attempts_query = select(models.Attempt).where(
|
||||
models.Attempt.user_id == user_id,
|
||||
models.Attempt.source_id == source_id
|
||||
)
|
||||
existing_attempts = session.exec(existing_attempts_query).all()
|
||||
is_retake = len(existing_attempts) > 0
|
||||
|
||||
attempt_record = models.Attempt(
|
||||
id=attempt_id,
|
||||
@@ -160,7 +168,8 @@ def submit_test_attempt(payload: Dict[str, Any], session: Session = Depends(get_
|
||||
score=0,
|
||||
total_questions=total_questions,
|
||||
accuracy=0.0,
|
||||
status="Submitted"
|
||||
status="Submitted",
|
||||
is_retake=is_retake
|
||||
)
|
||||
session.add(attempt_record)
|
||||
session.flush()
|
||||
@@ -522,7 +531,8 @@ async def upload_user_avatar(user_id: UUID, file: UploadFile = File(...), sessio
|
||||
|
||||
contents = await file.read()
|
||||
file_extension = file.filename.split(".")[-1] if "." in file.filename else "jpg"
|
||||
object_name = f"avatar_{user_id}.{file_extension}"
|
||||
current_year = datetime.utcnow().year
|
||||
object_name = f"avatars/{current_year}/avatar_{user_id}.{file_extension}"
|
||||
public_url = upload_file(contents, object_name, content_type=file.content_type)
|
||||
|
||||
if not public_url:
|
||||
@@ -579,7 +589,8 @@ async def upload_admin_test(
|
||||
from worker import process_pdf_test
|
||||
|
||||
pdf_bytes = await file.read()
|
||||
object_name = f"tests/{uuid.uuid4()}_{file.filename}"
|
||||
current_year = datetime.utcnow().year
|
||||
object_name = f"tests/{current_year}/{uuid.uuid4()}_{file.filename}"
|
||||
url = storage.upload_file(pdf_bytes, object_name, content_type="application/pdf")
|
||||
if not url:
|
||||
raise HTTPException(status_code=500, detail="Failed to upload PDF to MinIO")
|
||||
@@ -739,4 +750,58 @@ def delete_test(test_id: UUID, session: Session = Depends(get_session)):
|
||||
# 7. Delete the Test itself
|
||||
session.delete(test_obj)
|
||||
session.commit()
|
||||
return {"status": "success", "message": "Test and all associated questions, attempts, and mistakes deleted successfully"}
|
||||
return {"status": "success", "message": "Test and all associated questions, attempts, and mistakes deleted successfully"}
|
||||
|
||||
# --- COUPON CRUD ROUTES ---
|
||||
|
||||
class CouponCreate(BaseModel):
|
||||
code: str
|
||||
discount_percent: float
|
||||
max_discount_amount: float
|
||||
is_active: bool = True
|
||||
expires_at: Optional[datetime] = None
|
||||
|
||||
class CouponUpdate(BaseModel):
|
||||
code: Optional[str] = None
|
||||
discount_percent: Optional[float] = None
|
||||
max_discount_amount: Optional[float] = None
|
||||
is_active: Optional[bool] = None
|
||||
expires_at: Optional[datetime] = None
|
||||
|
||||
@app.get("/api/admin/coupons", tags=["Admin"])
|
||||
def get_admin_coupons(session: Session = Depends(get_session)):
|
||||
coupons = session.exec(select(models.Coupon)).all()
|
||||
return coupons
|
||||
|
||||
@app.post("/api/admin/coupons", tags=["Admin"])
|
||||
def create_coupon(payload: CouponCreate, session: Session = Depends(get_session)):
|
||||
coupon = models.Coupon(**payload.dict())
|
||||
session.add(coupon)
|
||||
session.commit()
|
||||
session.refresh(coupon)
|
||||
return coupon
|
||||
|
||||
@app.put("/api/admin/coupons/{coupon_id}", tags=["Admin"])
|
||||
def update_coupon(coupon_id: UUID, payload: CouponUpdate, session: Session = Depends(get_session)):
|
||||
coupon = session.get(models.Coupon, coupon_id)
|
||||
if not coupon:
|
||||
raise HTTPException(status_code=404, detail="Coupon not found")
|
||||
|
||||
update_data = payload.dict(exclude_unset=True)
|
||||
for key, value in update_data.items():
|
||||
setattr(coupon, key, value)
|
||||
|
||||
session.add(coupon)
|
||||
session.commit()
|
||||
session.refresh(coupon)
|
||||
return coupon
|
||||
|
||||
@app.delete("/api/admin/coupons/{coupon_id}", tags=["Admin"])
|
||||
def delete_coupon(coupon_id: UUID, session: Session = Depends(get_session)):
|
||||
coupon = session.get(models.Coupon, coupon_id)
|
||||
if not coupon:
|
||||
raise HTTPException(status_code=404, detail="Coupon not found")
|
||||
|
||||
session.delete(coupon)
|
||||
session.commit()
|
||||
return {"status": "success", "message": "Coupon deleted successfully"}
|
||||
Reference in New Issue
Block a user