diff --git a/backend/bracket/routes/matches.py b/backend/bracket/routes/matches.py index e6430114..80807de6 100644 --- a/backend/bracket/routes/matches.py +++ b/backend/bracket/routes/matches.py @@ -1,7 +1,9 @@ from fastapi import APIRouter, Depends, HTTPException from bracket.logic.planning.matches import ( + get_scheduled_matches, handle_match_reschedule, + reorder_matches_for_court, schedule_all_unscheduled_matches, ) from bracket.logic.ranking.elo import recalculate_ranking_for_tournament_id @@ -25,6 +27,7 @@ from bracket.routes.models import SingleMatchResponse, SuccessResponse, Upcoming from bracket.routes.util import match_dependency, round_dependency, round_with_matches_dependency from bracket.sql.courts import get_all_courts_in_tournament from bracket.sql.matches import sql_create_match, sql_delete_match, sql_update_match +from bracket.sql.stages import get_full_tournament_details from bracket.sql.tournaments import sql_get_tournament from bracket.sql.validation import check_foreign_keys_belong_to_tournament from bracket.utils.id_types import MatchId, TournamentId @@ -184,4 +187,11 @@ async def update_match_by_id( await sql_update_match(assert_some(match.id), match_body, tournament) await recalculate_ranking_for_tournament_id(tournament_id) + if ( + match_body.custom_duration_minutes != match.custom_duration_minutes + or match_body.custom_margin_minutes != match.custom_margin_minutes + ): + tournament = await sql_get_tournament(tournament_id) + scheduled_matches = get_scheduled_matches(await get_full_tournament_details(tournament_id)) + await reorder_matches_for_court(tournament, scheduled_matches, assert_some(match.court_id)) return SuccessResponse() diff --git a/backend/tests/integration_tests/api/matches_test.py b/backend/tests/integration_tests/api/matches_test.py index b3e86153..1faefcd5 100644 --- a/backend/tests/integration_tests/api/matches_test.py +++ b/backend/tests/integration_tests/api/matches_test.py @@ -174,6 +174,67 @@ async def test_update_match( await assert_row_count_and_clear(matches, 1) +async def test_update_endpoint_custom_duration_margin( + startup_and_shutdown_uvicorn_server: None, auth_context: AuthContext +) -> None: + async with ( + inserted_stage( + DUMMY_STAGE1.model_copy(update={"tournament_id": auth_context.tournament.id}) + ) as stage_inserted, + inserted_stage_item( + DUMMY_STAGE_ITEM1.model_copy(update={"stage_id": stage_inserted.id}) + ) as stage_item_inserted, + inserted_round( + DUMMY_ROUND1.model_copy(update={"stage_item_id": stage_item_inserted.id}) + ) as round_inserted, + inserted_team( + DUMMY_TEAM1.model_copy(update={"tournament_id": auth_context.tournament.id}) + ) as team1_inserted, + inserted_team( + DUMMY_TEAM2.model_copy(update={"tournament_id": auth_context.tournament.id}) + ) as team2_inserted, + inserted_court( + DUMMY_COURT1.model_copy(update={"tournament_id": auth_context.tournament.id}) + ) as court1_inserted, + inserted_match( + DUMMY_MATCH1.model_copy( + update={ + "round_id": round_inserted.id, + "team1_id": team1_inserted.id, + "team2_id": team2_inserted.id, + "court_id": court1_inserted.id, + "custom_duration_minutes": 20, + "custom_margin_minutes": 10, + } + ) + ) as match_inserted, + ): + body = { + "round_id": round_inserted.id, + "custom_duration_minutes": 30, + "custom_margin_minutes": 20, + } + assert ( + await send_tournament_request( + HTTPMethod.PUT, + f"matches/{match_inserted.id}", + auth_context, + None, + body, + ) + == SUCCESS_RESPONSE + ) + updated_match = await fetch_one_parsed_certain( + database, + Match, + query=matches.select().where(matches.c.id == match_inserted.id), + ) + assert updated_match.custom_duration_minutes == body["custom_duration_minutes"] + assert updated_match.custom_margin_minutes == body["custom_margin_minutes"] + + await assert_row_count_and_clear(matches, 1) + + async def test_upcoming_matches_endpoint( startup_and_shutdown_uvicorn_server: None, auth_context: AuthContext ) -> None: