from fastapi import APIRouter, Depends, HTTPException, Query, Response from typing import List, Optional from pandas import DataFrame import logging import pydantic from ..db_engine import db, Transaction, Team, Player, model_to_dict, chunked, fn from ..dependencies import oauth2_scheme, valid_token router = APIRouter( prefix='/api/v3/transactions', tags=['transactions'] ) class TransactionModel(pydantic.BaseModel): week: int player_id: int oldteam_id: int newteam_id: int season: int moveid: str cancelled: Optional[bool] = False frozen: Optional[bool] = False class TransactionList(pydantic.BaseModel): count: int moves: List[TransactionModel] @router.get('') async def get_transactions( season, team_abbrev: list = Query(default=None), week_start: Optional[int] = 0, week_end: Optional[int] = None, cancelled: Optional[bool] = None, frozen: Optional[bool] = None, player_name: list = Query(default=None), player_id: list = Query(default=None), move_id: Optional[str] = None, is_trade: Optional[bool] = None, short_output: Optional[bool] = False): if season: transactions = Transaction.select_season(season) else: transactions = Transaction.select() if team_abbrev is not None: t_list = [x.upper() for x in team_abbrev] these_teams = Team.select().where((Team.abbrev << t_list)) transactions = transactions.where( (Transaction.newteam << these_teams) | (Transaction.oldteam << these_teams) ) if week_start is not None: transactions = transactions.where(Transaction.week >= week_start) if week_end is not None: transactions = transactions.where(Transaction.week <= week_end) if move_id: transactions = transactions.where(Transaction.moveid == move_id) if player_id or player_name: if player_id: p_list = Player.select().where(Player.id << player_id) transactions = transactions.where(Transaction.player << p_list) else: p_list = [x.lower() for x in player_name] these_players = Player.select().where(fn.Lower(Player.name) << p_list) transactions = transactions.where(Transaction.player << these_players) if cancelled: transactions = transactions.where(Transaction.cancelled == 1) else: transactions = transactions.where(Transaction.cancelled == 0) if frozen: transactions = transactions.where(Transaction.frozen == 1) else: transactions = transactions.where(Transaction.frozen == 0) if is_trade is not None: raise HTTPException(status_code=501, detail='The is_trade parameter is not implemented, yet') transactions = transactions.order_by(-Transaction.week, Transaction.moveid) return_trans = { 'count': transactions.count(), 'transactions': [model_to_dict(x, recurse=not short_output) for x in transactions] } db.close() return return_trans @router.patch('/{move_id}') async def patch_transactions( move_id, token: str = Depends(oauth2_scheme), frozen: Optional[bool] = None, cancelled: Optional[bool] = None): if not valid_token(token): logging.warning(f'patch_transactions - Bad Token: {token}') raise HTTPException(status_code=401, detail='Unauthorized') these_moves = Transaction.select().where(Transaction.moveid == move_id) if these_moves.count() == 0: db.close() raise HTTPException(status_code=404, detail=f'Move ID {move_id} not found') if frozen is not None: for x in these_moves: x.frozen = frozen x.save() if cancelled is not None: for x in these_moves: x.cancelled = cancelled x.save() db.close() raise HTTPException(status_code=200, detail=f'Updated {these_moves.count()} transactions') @router.post('') async def post_transactions(moves: TransactionList, token: str = Depends(oauth2_scheme)): if not valid_token(token): logging.warning(f'post_transactions - Bad Token: {token}') raise HTTPException(status_code=401, detail='Unauthorized') all_moves = [] for x in moves.moves: if Team.get_or_none(Team.id == x.oldteam_id) is None: raise HTTPException(status_code=404, detail=f'Team ID {x.oldteam_id} not found') if Team.get_or_none(Team.id == x.newteam_id) is None: raise HTTPException(status_code=404, detail=f'Team ID {x.newteam_id} not found') if Player.get_or_none(Player.id == x.player_id) is None: raise HTTPException(status_code=404, detail=f'Player ID {x.player_id} not found') all_moves.append(x.dict()) with db.atomic(): for batch in chunked(all_moves, 15): Transaction.insert_many(batch).on_conflict_replace().execute() db.close() raise HTTPException(status_code=200, detail=f'{len(all_moves)} transactions have been added') @router.delete('/{move_id}') async def delete_transactions(move_id, token: str = Depends(oauth2_scheme)): if not valid_token(token): logging.warning(f'delete_transactions - Bad Token: {token}') raise HTTPException(status_code=401, detail='Unauthorized') delete_query = Transaction.delete().where(Transaction.moveid == move_id) count = delete_query.execute() db.close() if count > 0: raise HTTPException(status_code=200, detail=f'Removed {count} transactions') else: raise HTTPException(status_code=418, detail=f'Well slap my ass and call me a teapot; ' f'I did not delete any records')