Add shop
This commit is contained in:
@@ -7,7 +7,7 @@ from typing import Optional
|
||||
|
||||
from app.api.deps import DbSession, CurrentUser, require_admin_with_2fa
|
||||
from app.models import (
|
||||
User, UserRole, Marathon, MarathonStatus, Participant, Game, AdminLog, AdminActionType, StaticContent,
|
||||
User, UserRole, Marathon, MarathonStatus, CertificationStatus, Participant, Game, AdminLog, AdminActionType, StaticContent,
|
||||
Dispute, DisputeStatus, Assignment, AssignmentStatus, Challenge, BonusAssignment, BonusAssignmentStatus
|
||||
)
|
||||
from app.schemas import (
|
||||
@@ -37,6 +37,8 @@ class AdminMarathonResponse(BaseModel):
|
||||
start_date: str | None
|
||||
end_date: str | None
|
||||
created_at: str
|
||||
certification_status: str = "none"
|
||||
is_certified: bool = False
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
@@ -219,7 +221,12 @@ async def list_marathons(
|
||||
|
||||
query = (
|
||||
select(Marathon)
|
||||
.options(selectinload(Marathon.creator))
|
||||
.options(
|
||||
selectinload(Marathon.creator).selectinload(User.equipped_frame),
|
||||
selectinload(Marathon.creator).selectinload(User.equipped_title),
|
||||
selectinload(Marathon.creator).selectinload(User.equipped_name_color),
|
||||
selectinload(Marathon.creator).selectinload(User.equipped_background),
|
||||
)
|
||||
.order_by(Marathon.created_at.desc())
|
||||
)
|
||||
|
||||
@@ -248,6 +255,8 @@ async def list_marathons(
|
||||
start_date=marathon.start_date.isoformat() if marathon.start_date else None,
|
||||
end_date=marathon.end_date.isoformat() if marathon.end_date else None,
|
||||
created_at=marathon.created_at.isoformat(),
|
||||
certification_status=marathon.certification_status,
|
||||
is_certified=marathon.is_certified,
|
||||
))
|
||||
|
||||
return response
|
||||
@@ -1102,3 +1111,75 @@ async def resolve_dispute(
|
||||
return MessageResponse(
|
||||
message=f"Dispute resolved as {'valid' if data.is_valid else 'invalid'}"
|
||||
)
|
||||
|
||||
|
||||
# ============ Marathon Certification ============
|
||||
@router.post("/marathons/{marathon_id}/certify", response_model=MessageResponse)
|
||||
async def certify_marathon(
|
||||
request: Request,
|
||||
marathon_id: int,
|
||||
current_user: CurrentUser,
|
||||
db: DbSession,
|
||||
):
|
||||
"""Certify (verify) a marathon. Admin only."""
|
||||
require_admin_with_2fa(current_user)
|
||||
|
||||
result = await db.execute(select(Marathon).where(Marathon.id == marathon_id))
|
||||
marathon = result.scalar_one_or_none()
|
||||
if not marathon:
|
||||
raise HTTPException(status_code=404, detail="Marathon not found")
|
||||
|
||||
if marathon.certification_status == CertificationStatus.CERTIFIED.value:
|
||||
raise HTTPException(status_code=400, detail="Marathon is already certified")
|
||||
|
||||
marathon.certification_status = CertificationStatus.CERTIFIED.value
|
||||
marathon.certified_at = datetime.utcnow()
|
||||
marathon.certified_by_id = current_user.id
|
||||
marathon.certification_rejection_reason = None
|
||||
|
||||
await db.commit()
|
||||
|
||||
# Log action
|
||||
await log_admin_action(
|
||||
db, current_user.id, AdminActionType.MARATHON_CERTIFY.value,
|
||||
"marathon", marathon_id,
|
||||
{"title": marathon.title},
|
||||
request.client.host if request.client else None
|
||||
)
|
||||
|
||||
return MessageResponse(message="Marathon certified successfully")
|
||||
|
||||
|
||||
@router.post("/marathons/{marathon_id}/revoke-certification", response_model=MessageResponse)
|
||||
async def revoke_marathon_certification(
|
||||
request: Request,
|
||||
marathon_id: int,
|
||||
current_user: CurrentUser,
|
||||
db: DbSession,
|
||||
):
|
||||
"""Revoke certification from a marathon. Admin only."""
|
||||
require_admin_with_2fa(current_user)
|
||||
|
||||
result = await db.execute(select(Marathon).where(Marathon.id == marathon_id))
|
||||
marathon = result.scalar_one_or_none()
|
||||
if not marathon:
|
||||
raise HTTPException(status_code=404, detail="Marathon not found")
|
||||
|
||||
if marathon.certification_status != CertificationStatus.CERTIFIED.value:
|
||||
raise HTTPException(status_code=400, detail="Marathon is not certified")
|
||||
|
||||
marathon.certification_status = CertificationStatus.NONE.value
|
||||
marathon.certified_at = None
|
||||
marathon.certified_by_id = None
|
||||
|
||||
await db.commit()
|
||||
|
||||
# Log action
|
||||
await log_admin_action(
|
||||
db, current_user.id, AdminActionType.MARATHON_REVOKE_CERTIFICATION.value,
|
||||
"marathon", marathon_id,
|
||||
{"title": marathon.title},
|
||||
request.client.host if request.client else None
|
||||
)
|
||||
|
||||
return MessageResponse(message="Marathon certification revoked")
|
||||
|
||||
Reference in New Issue
Block a user