from typing import List from ninja import Router from ninja.errors import HttpError from django.shortcuts import get_object_or_404 from market.models import Market, MarketOption, UserBet from market.schemas import ( MarketListSchema, ResolveMarketSchema, UserBetCreateSchema, UserBetSchema, ) router = Router(tags=["market"]) @router.get("/", response=List[MarketListSchema]) def list_markets(request): """List all markets.""" return Market.objects.prefetch_related("options").all() @router.get("/user/bets", response=List[UserBetSchema]) def list_user_bets(request): """List all bets placed by the current user.""" if not request.user.is_authenticated: raise HttpError(401, "Authentication required") return UserBet.objects.filter(user=request.user).select_related( "option__market" ).prefetch_related("option__market__options") @router.post("/{market_uuid}/actions/close") def close_market(request, market_uuid: str): """Close a market. Admin only.""" if not request.user.is_staff: raise HttpError(403, "Permission denied") market = get_object_or_404(Market, uuid=market_uuid) market.status = Market.Status.CLOSED market.save(update_fields=["status", "updated_at"]) return {"status": "closed"} @router.post("/{market_uuid}/actions/resolve", response=MarketListSchema) def resolve_market(request, market_uuid: str, payload: ResolveMarketSchema): """Resolve a market with a winning option. Admin only.""" if not request.user.is_staff: raise HttpError(403, "Permission denied") market = get_object_or_404(Market, uuid=market_uuid) winning_option = get_object_or_404(MarketOption, uuid=payload.winning_option_uuid) if winning_option.market_id != market.id: raise HttpError(400, "Option does not belong to this market") market.winning_option = winning_option market.status = Market.Status.RESOLVED market.save(update_fields=["winning_option", "status", "updated_at"]) return market @router.post("/{market_uuid}/bets", response=UserBetSchema) def create_bet(request, market_uuid: str, payload: UserBetCreateSchema): """Place a bet on a market option.""" if not request.user.is_authenticated: raise HttpError(401, "Authentication required") market = get_object_or_404(Market, uuid=market_uuid) option = get_object_or_404(MarketOption, uuid=payload.option_uuid) if option.market_id != market.id: raise HttpError(400, "Option does not belong to this market") if market.status != Market.Status.OPEN: raise HttpError(400, "Market is not open for betting") # Check if user already has a bet on a different option in this market existing_bet_on_market = UserBet.objects.filter( user=request.user, option__market=market ).exclude(option=option).first() if existing_bet_on_market: raise HttpError(400, "You can only bet on one option per market") # Check if user already has a bet on this option existing_bet = UserBet.objects.filter(user=request.user, option=option).first() if existing_bet and payload.amount < existing_bet.amount: raise HttpError(400, "Cannot decrease bet amount. You can only increase it.") user_bet, created = UserBet.objects.update_or_create( user=request.user, option=option, defaults={"amount": payload.amount}, ) return user_bet