feat(market): basic page + submit
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
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
|
||||
Reference in New Issue
Block a user