Add event management endpoints
- Implemented endpoints for creating, retrieving, and managing events. - Added `EventSchema` for event serialization and deserialization. - Updated `Event` model to include relationships with `PlayerEvent` and `Team`. - Modified `Player` and `Team` models to include relationships with `Event`. - Added new file `events.py` to handle event-related API routes.master
							parent
							
								
									3394f2271e
								
							
						
					
					
						commit
						ea030e012d
					
				| 
						 | 
				
			
			@ -0,0 +1,117 @@
 | 
			
		|||
#! /usr/bin/env python3
 | 
			
		||||
# vim:fenc=utf-8
 | 
			
		||||
#
 | 
			
		||||
# Copyright © 2024 sandvich <sandvich@archtop>
 | 
			
		||||
#
 | 
			
		||||
# Distributed under terms of the MIT license.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
from datetime import datetime
 | 
			
		||||
 | 
			
		||||
from flask import Blueprint, abort
 | 
			
		||||
from spectree import Response
 | 
			
		||||
from models.player_event import PlayerEvent
 | 
			
		||||
from models.player import Player
 | 
			
		||||
from spec import BaseModel, spec
 | 
			
		||||
from middleware import assert_team_authority, requires_authentication, requires_team_membership
 | 
			
		||||
from models.event import Event, EventSchema
 | 
			
		||||
from models.player_team import PlayerTeam
 | 
			
		||||
from app_db import db
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
api_events = Blueprint("events", __name__, url_prefix="/events")
 | 
			
		||||
 | 
			
		||||
@api_events.get("/<int:event_id>")
 | 
			
		||||
@spec.validate(
 | 
			
		||||
    resp=Response(
 | 
			
		||||
        HTTP_200=EventSchema,
 | 
			
		||||
    ),
 | 
			
		||||
    operation_id="get_event",
 | 
			
		||||
)
 | 
			
		||||
def get_event(event_id: int):
 | 
			
		||||
    event = db.session.query(Event).filter(Event.id == event_id).one_or_none()
 | 
			
		||||
 | 
			
		||||
    if not event:
 | 
			
		||||
        abort(404)
 | 
			
		||||
 | 
			
		||||
    return EventSchema.from_model(event).dict(by_alias=True)
 | 
			
		||||
 | 
			
		||||
@api_events.get("/team/id/<int:team_id>")
 | 
			
		||||
@spec.validate(
 | 
			
		||||
    resp=Response(
 | 
			
		||||
        HTTP_200=list[EventSchema],
 | 
			
		||||
    ),
 | 
			
		||||
    operation_id="get_team_events",
 | 
			
		||||
)
 | 
			
		||||
def get_team_events(team_id: int):
 | 
			
		||||
    events = db.session.query(
 | 
			
		||||
        Event
 | 
			
		||||
    ).filter(
 | 
			
		||||
        Event.team_id == team_id
 | 
			
		||||
    ).all()
 | 
			
		||||
 | 
			
		||||
    def map_to_schema(event: Event):
 | 
			
		||||
        return EventSchema.from_model(event).dict(by_alias=True)
 | 
			
		||||
 | 
			
		||||
    return list(map(map_to_schema, events))
 | 
			
		||||
 | 
			
		||||
@api_events.get("/user/id/<int:user_id>")
 | 
			
		||||
def get_user_events(user_id: int):
 | 
			
		||||
    raise NotImplementedError()
 | 
			
		||||
 | 
			
		||||
class CreateEventJson(BaseModel):
 | 
			
		||||
    name: str
 | 
			
		||||
    description: str
 | 
			
		||||
    start_time: datetime
 | 
			
		||||
    player_ids: list[int]
 | 
			
		||||
 | 
			
		||||
@api_events.post("/team/id/<int:team_id>")
 | 
			
		||||
@spec.validate(
 | 
			
		||||
    resp=Response(
 | 
			
		||||
        HTTP_200=EventSchema,
 | 
			
		||||
    )
 | 
			
		||||
)
 | 
			
		||||
@requires_authentication
 | 
			
		||||
@requires_team_membership
 | 
			
		||||
def create_event(player_team: PlayerTeam, json: CreateEventJson, **_):
 | 
			
		||||
    event = Event()
 | 
			
		||||
    event.team_id = player_team.team_id
 | 
			
		||||
    event.name = json.name
 | 
			
		||||
    event.description = json.description
 | 
			
		||||
    event.start_time = json.start_time
 | 
			
		||||
 | 
			
		||||
    db.session.add(event)
 | 
			
		||||
    db.session.flush()
 | 
			
		||||
    db.session.refresh(event)
 | 
			
		||||
 | 
			
		||||
    players_teams = db.session.query(
 | 
			
		||||
        PlayerTeam
 | 
			
		||||
    ).join(
 | 
			
		||||
        Player
 | 
			
		||||
    ).where(
 | 
			
		||||
        PlayerTeam.team_id == player_team.team_id
 | 
			
		||||
    ).where(
 | 
			
		||||
        PlayerTeam.player_id.in_(json.player_ids)
 | 
			
		||||
    ).all()
 | 
			
		||||
 | 
			
		||||
    for player_team in players_teams:
 | 
			
		||||
        player = player_team.player
 | 
			
		||||
        player_event = PlayerEvent()
 | 
			
		||||
        player_event.player_id = player.steam_id
 | 
			
		||||
        player_event.event_id = event.id
 | 
			
		||||
        db.session.add(player_event)
 | 
			
		||||
 | 
			
		||||
    db.session.commit()
 | 
			
		||||
 | 
			
		||||
    return EventSchema.from_model(event).dict(by_alias=True), 200
 | 
			
		||||
 | 
			
		||||
@api_events.patch("/<int:event_id>/players")
 | 
			
		||||
@requires_authentication
 | 
			
		||||
@requires_team_membership
 | 
			
		||||
def set_event_players(player_team: PlayerTeam, event_id: int, **_):
 | 
			
		||||
    assert_team_authority(player_team, None)
 | 
			
		||||
 | 
			
		||||
    # merge players into event
 | 
			
		||||
    db.session.query(Event).filter(Event.id == event_id).update({"players": []})
 | 
			
		||||
 | 
			
		||||
    raise NotImplementedError()
 | 
			
		||||
| 
						 | 
				
			
			@ -1,10 +1,12 @@
 | 
			
		|||
from datetime import datetime
 | 
			
		||||
from sqlalchemy.orm import mapped_column, relationship
 | 
			
		||||
from sqlalchemy.orm.attributes import Mapped
 | 
			
		||||
from sqlalchemy.orm.properties import ForeignKey
 | 
			
		||||
from sqlalchemy.types import TIMESTAMP, Integer, String, Text
 | 
			
		||||
from sqlalchemy.sql import func
 | 
			
		||||
from sqlalchemy_utc import UtcDateTime
 | 
			
		||||
import app_db
 | 
			
		||||
import spec
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Event(app_db.BaseModel):
 | 
			
		||||
| 
						 | 
				
			
			@ -14,10 +16,30 @@ class Event(app_db.BaseModel):
 | 
			
		|||
    name: Mapped[str] = mapped_column(String(255), nullable=False)
 | 
			
		||||
    description: Mapped[str] = mapped_column(Text, nullable=True)
 | 
			
		||||
    start_time: Mapped[datetime] = mapped_column(UtcDateTime, nullable=False)
 | 
			
		||||
    team_id: Mapped[int] = mapped_column(Integer, nullable=False)
 | 
			
		||||
    team_id: Mapped[int] = mapped_column(ForeignKey("teams.id"), nullable=False)
 | 
			
		||||
    created_at: Mapped[datetime] = mapped_column(TIMESTAMP, server_default=func.now())
 | 
			
		||||
 | 
			
		||||
    team: Mapped["Team"] = relationship("Team", back_populates="events")
 | 
			
		||||
    players: Mapped["PlayerEvent"] = relationship("PlayerEvent", back_populates="event")
 | 
			
		||||
 | 
			
		||||
class EventSchema(spec.BaseModel):
 | 
			
		||||
    id: int
 | 
			
		||||
    team_id: int
 | 
			
		||||
    name: str
 | 
			
		||||
    description: str
 | 
			
		||||
    start_time: datetime
 | 
			
		||||
    created_at: datetime
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def from_model(cls, model: Event) -> "EventSchema":
 | 
			
		||||
        return cls(
 | 
			
		||||
            id=model.id,
 | 
			
		||||
            name=model.name,
 | 
			
		||||
            description=model.description,
 | 
			
		||||
            start_time=model.start_time,
 | 
			
		||||
            team_id=model.team_id,
 | 
			
		||||
            created_at=model.created_at,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
from models.team import Team
 | 
			
		||||
from models.player_event import PlayerEvent
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,6 +15,7 @@ class Player(app_db.BaseModel):
 | 
			
		|||
 | 
			
		||||
    teams: Mapped[list["PlayerTeam"]] = relationship(back_populates="player")
 | 
			
		||||
    auth_sessions: Mapped[list["AuthSession"]] = relationship(back_populates="player")
 | 
			
		||||
    events: Mapped[list["PlayerEvent"]] = relationship(back_populates="player")
 | 
			
		||||
 | 
			
		||||
    created_at: Mapped[datetime] = mapped_column(TIMESTAMP, server_default=func.now())
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -28,4 +29,5 @@ class PlayerSchema(spec.BaseModel):
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
from models.auth_session import AuthSession
 | 
			
		||||
from models.player_event import PlayerEvent
 | 
			
		||||
from models.player_team import PlayerTeam
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,6 +19,7 @@ class Team(app_db.BaseModel):
 | 
			
		|||
    players: Mapped[list["PlayerTeam"]] = relationship(back_populates="team")
 | 
			
		||||
    invites: Mapped[list["TeamInvite"]] = relationship(back_populates="team")
 | 
			
		||||
    integrations: Mapped[list["TeamIntegration"]] = relationship(back_populates="team")
 | 
			
		||||
    events: Mapped[list["Event"]] = relationship(back_populates="team")
 | 
			
		||||
 | 
			
		||||
    created_at: Mapped[datetime] = mapped_column(TIMESTAMP, server_default=func.now())
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -42,3 +43,4 @@ class TeamSchema(spec.BaseModel):
 | 
			
		|||
from models.player_team import PlayerTeam
 | 
			
		||||
from models.team_integration import TeamIntegration
 | 
			
		||||
from models.team_invite import TeamInvite
 | 
			
		||||
from models.event import Event
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue