from datetime import datetime from typing import List, Optional from sqlalchemy.orm import Session from app.crud.event import get_outcome from app.crud.user import update_user_balance from app.models.bet import Bet, BetStatus from app.models.transaction import Transaction, TransactionStatus, TransactionType from app.schemas.bet import BetCreate def get_bet(db: Session, bet_id: int) -> Optional[Bet]: return db.query(Bet).filter(Bet.id == bet_id).first() def get_user_bets( db: Session, user_id: int, skip: int = 0, limit: int = 100, status: Optional[BetStatus] = None, ) -> List[Bet]: query = db.query(Bet).filter(Bet.user_id == user_id) if status: query = query.filter(Bet.status == status) return query.order_by(Bet.created_at.desc()).offset(skip).limit(limit).all() def create_bet(db: Session, bet_in: BetCreate, user_id: int) -> Optional[Bet]: # Get the outcome to check if it exists and get odds outcome = get_outcome(db, bet_in.outcome_id) if not outcome or not outcome.is_active: return None # Calculate potential win potential_win = bet_in.amount * outcome.odds # Create bet db_bet = Bet( user_id=user_id, outcome_id=bet_in.outcome_id, amount=bet_in.amount, odds=outcome.odds, potential_win=potential_win, status=BetStatus.PENDING, ) # Update user balance update_user_balance(db, user_id, -bet_in.amount) # Create transaction record transaction = Transaction( user_id=user_id, amount=-bet_in.amount, transaction_type=TransactionType.BET_PLACED, status=TransactionStatus.COMPLETED, bet_id=db_bet.id, ) db.add(db_bet) db.commit() db.refresh(db_bet) # Update transaction with bet_id transaction.bet_id = db_bet.id db.add(transaction) db.commit() return db_bet def update_bet_status( db: Session, bet_id: int, status: BetStatus, ) -> Optional[Bet]: bet = get_bet(db, bet_id) if bet and bet.status == BetStatus.PENDING: bet.status = status bet.settled_at = datetime.utcnow() # If bet is won, create a transaction and update user balance if status == BetStatus.WON: transaction = Transaction( user_id=bet.user_id, amount=bet.potential_win, transaction_type=TransactionType.BET_WON, status=TransactionStatus.COMPLETED, bet_id=bet.id, ) db.add(transaction) update_user_balance(db, bet.user_id, bet.potential_win) # If bet is cancelled or voided, refund the amount if status in [BetStatus.CANCELLED, BetStatus.VOIDED]: transaction = Transaction( user_id=bet.user_id, amount=bet.amount, transaction_type=TransactionType.BET_REFUND, status=TransactionStatus.COMPLETED, bet_id=bet.id, ) db.add(transaction) update_user_balance(db, bet.user_id, bet.amount) db.add(bet) db.commit() db.refresh(bet) return bet def settle_bets_for_outcome( db: Session, outcome_id: int, is_winner: bool, ) -> int: """ Settle all pending bets for a specific outcome. Returns the number of bets settled. """ bets = db.query(Bet).filter( Bet.outcome_id == outcome_id, Bet.status == BetStatus.PENDING, ).all() count = 0 for bet in bets: if is_winner: update_bet_status(db, bet.id, BetStatus.WON) else: update_bet_status(db, bet.id, BetStatus.LOST) count += 1 return count