Automated Action 4cfc9775ae Create betting application API with FastAPI and SQLite
- Set up project structure with FastAPI and SQLite
- Implement user authentication with JWT
- Create database models for users, events, bets, and transactions
- Add API endpoints for user management
- Add API endpoints for events and betting functionality
- Add wallet management for deposits and withdrawals
- Configure Alembic for database migrations
- Add linting with Ruff
- Add documentation in README
2025-06-02 15:02:41 +00:00

137 lines
4.2 KiB
Python

from typing import Any, Optional
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from app import crud, models, schemas
from app.api import deps
from app.models.bet import BetStatus
router = APIRouter()
@router.get("/", response_model=list[schemas.Bet])
def read_bets(
db: Session = Depends(deps.get_db),
skip: int = 0,
limit: int = 100,
status: Optional[BetStatus] = None,
current_user: models.User = Depends(deps.get_current_active_user),
) -> Any:
"""
Retrieve bets for current user.
"""
bets = crud.get_user_bets(
db, user_id=current_user.id, skip=skip, limit=limit, status=status,
)
return bets
@router.post("/", response_model=schemas.Bet)
def create_bet(
*,
db: Session = Depends(deps.get_db),
bet_in: schemas.BetCreate,
current_user: models.User = Depends(deps.get_current_active_user),
) -> Any:
"""
Create a new bet.
"""
# Check if user has enough balance
if current_user.balance < bet_in.amount:
raise HTTPException(
status_code=400, detail="Insufficient balance for this bet",
)
# Check if amount is positive
if bet_in.amount <= 0:
raise HTTPException(
status_code=400, detail="Bet amount must be greater than 0",
)
# Check if outcome exists and is active
outcome = crud.get_outcome(db, outcome_id=bet_in.outcome_id)
if not outcome:
raise HTTPException(status_code=404, detail="Outcome not found")
if not outcome.is_active:
raise HTTPException(status_code=400, detail="This outcome is not available for betting")
# Check if market is active
if not outcome.market.is_active:
raise HTTPException(status_code=400, detail="This market is not available for betting")
# Check if event is upcoming or live
event = outcome.market.event
if event.status not in [models.event.EventStatus.UPCOMING, models.event.EventStatus.LIVE]:
raise HTTPException(
status_code=400,
detail=f"Cannot place bets on events with status {event.status}",
)
bet = crud.create_bet(db, bet_in=bet_in, user_id=current_user.id)
if not bet:
raise HTTPException(status_code=400, detail="Could not create bet")
return bet
@router.get("/{bet_id}", response_model=schemas.Bet)
def read_bet(
*,
db: Session = Depends(deps.get_db),
bet_id: int,
current_user: models.User = Depends(deps.get_current_active_user),
) -> Any:
"""
Get specific bet by ID.
"""
bet = crud.get_bet(db, bet_id=bet_id)
if not bet:
raise HTTPException(status_code=404, detail="Bet not found")
# Only allow user to see their own bets (or admin)
if bet.user_id != current_user.id and not current_user.is_admin:
raise HTTPException(status_code=403, detail="Not enough permissions")
return bet
@router.post("/{bet_id}/cancel", response_model=schemas.Bet)
def cancel_bet(
*,
db: Session = Depends(deps.get_db),
bet_id: int,
current_user: models.User = Depends(deps.get_current_active_user),
) -> Any:
"""
Cancel a pending bet.
"""
bet = crud.get_bet(db, bet_id=bet_id)
if not bet:
raise HTTPException(status_code=404, detail="Bet not found")
# Only allow user to cancel their own bets (or admin)
if bet.user_id != current_user.id and not current_user.is_admin:
raise HTTPException(status_code=403, detail="Not enough permissions")
# Only pending bets can be cancelled
if bet.status != BetStatus.PENDING:
raise HTTPException(
status_code=400,
detail=f"Cannot cancel a bet with status {bet.status}",
)
# Get the outcome and check if event has started
outcome = crud.get_outcome(db, outcome_id=bet.outcome_id)
event = outcome.market.event
# Only allow cancellation if event hasn't started yet
if event.status != models.event.EventStatus.UPCOMING:
raise HTTPException(
status_code=400,
detail="Cannot cancel bets on events that have already started",
)
bet = crud.update_bet_status(db, bet_id=bet_id, status=BetStatus.CANCELLED)
return bet